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:
authorSeverin <eiseljulian@gmail.com>2018-06-30 22:12:19 +0300
committerSeverin <eiseljulian@gmail.com>2018-06-30 22:12:19 +0300
commite5f49598b037ef8476efd458d060d3db348b9b60 (patch)
treeb3a3fe2796ad1ad2ba831e53b944e98013df0648 /source/blender/editors
parentb088a387915950c9419d5326e7269bea3869d140 (diff)
parent7d48a342d66cc7664b008ff512bd00e740eb7629 (diff)
Merge branch 'blender2.8' into temp-tab_drag_drop
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/CMakeLists.txt1
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c1167
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c924
-rw-r--r--source/blender/editors/animation/anim_deps.c119
-rw-r--r--source/blender/editors/animation/anim_draw.c65
-rw-r--r--source/blender/editors/animation/anim_filter.c969
-rw-r--r--source/blender/editors/animation/anim_intern.h9
-rw-r--r--source/blender/editors/animation/anim_ipo_utils.c60
-rw-r--r--source/blender/editors/animation/anim_markers.c266
-rw-r--r--source/blender/editors/animation/anim_ops.c121
-rw-r--r--source/blender/editors/animation/drivers.c448
-rw-r--r--source/blender/editors/animation/fmodifier_ui.c252
-rw-r--r--source/blender/editors/animation/keyframes_draw.c272
-rw-r--r--source/blender/editors/animation/keyframes_edit.c335
-rw-r--r--source/blender/editors/animation/keyframes_general.c224
-rw-r--r--source/blender/editors/animation/keyframing.c727
-rw-r--r--source/blender/editors/animation/keyingsets.c302
-rw-r--r--source/blender/editors/armature/armature_add.c178
-rw-r--r--source/blender/editors/armature/armature_edit.c266
-rw-r--r--source/blender/editors/armature/armature_intern.h15
-rw-r--r--source/blender/editors/armature/armature_naming.c85
-rw-r--r--source/blender/editors/armature/armature_ops.c111
-rw-r--r--source/blender/editors/armature/armature_relations.c254
-rw-r--r--source/blender/editors/armature/armature_select.c73
-rw-r--r--source/blender/editors/armature/armature_skinning.c78
-rw-r--r--source/blender/editors/armature/armature_utils.c94
-rw-r--r--source/blender/editors/armature/editarmature_retarget.c2644
-rw-r--r--source/blender/editors/armature/meshlaplacian.c58
-rw-r--r--source/blender/editors/armature/meshlaplacian.h1
-rw-r--r--source/blender/editors/armature/pose_edit.c280
-rw-r--r--source/blender/editors/armature/pose_group.c98
-rw-r--r--source/blender/editors/armature/pose_lib.c510
-rw-r--r--source/blender/editors/armature/pose_select.c205
-rw-r--r--source/blender/editors/armature/pose_slide.c440
-rw-r--r--source/blender/editors/armature/pose_transform.c251
-rw-r--r--source/blender/editors/armature/pose_utils.c83
-rw-r--r--source/blender/editors/curve/curve_intern.h4
-rw-r--r--source/blender/editors/curve/curve_ops.c30
-rw-r--r--source/blender/editors/curve/editcurve.c270
-rw-r--r--source/blender/editors/curve/editcurve_add.c4
-rw-r--r--source/blender/editors/curve/editcurve_paint.c26
-rw-r--r--source/blender/editors/curve/editcurve_select.c122
-rw-r--r--source/blender/editors/curve/editfont.c141
-rw-r--r--source/blender/editors/datafiles/CMakeLists.txt30
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c67
-rw-r--r--source/blender/editors/gpencil/editaction_gpencil.c152
-rw-r--r--source/blender/editors/gpencil/gpencil_brush.c479
-rw-r--r--source/blender/editors/gpencil/gpencil_convert.c349
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c179
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c581
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h7
-rw-r--r--source/blender/editors/gpencil/gpencil_interpolate.c304
-rw-r--r--source/blender/editors/gpencil/gpencil_ops.c196
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c578
-rw-r--r--source/blender/editors/gpencil/gpencil_select.c324
-rw-r--r--source/blender/editors/gpencil/gpencil_undo.c54
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c161
-rw-r--r--source/blender/editors/include/BIF_gl.h1
-rw-r--r--source/blender/editors/include/ED_anim_api.h117
-rw-r--r--source/blender/editors/include/ED_armature.h17
-rw-r--r--source/blender/editors/include/ED_curve.h15
-rw-r--r--source/blender/editors/include/ED_datafiles.h5
-rw-r--r--source/blender/editors/include/ED_fileselect.h16
-rw-r--r--source/blender/editors/include/ED_gpencil.h2
-rw-r--r--source/blender/editors/include/ED_image.h11
-rw-r--r--source/blender/editors/include/ED_keyframes_draw.h14
-rw-r--r--source/blender/editors/include/ED_keyframes_edit.h16
-rw-r--r--source/blender/editors/include/ED_keyframing.h44
-rw-r--r--source/blender/editors/include/ED_manipulator_library.h23
-rw-r--r--source/blender/editors/include/ED_markers.h6
-rw-r--r--source/blender/editors/include/ED_mball.h4
-rw-r--r--source/blender/editors/include/ED_mesh.h18
-rw-r--r--source/blender/editors/include/ED_node.h9
-rw-r--r--source/blender/editors/include/ED_object.h51
-rw-r--r--source/blender/editors/include/ED_outliner.h7
-rw-r--r--source/blender/editors/include/ED_particle.h1
-rw-r--r--source/blender/editors/include/ED_physics.h1
-rw-r--r--source/blender/editors/include/ED_screen.h88
-rw-r--r--source/blender/editors/include/ED_screen_types.h6
-rw-r--r--source/blender/editors/include/ED_sculpt.h2
-rw-r--r--source/blender/editors/include/ED_sound.h5
-rw-r--r--source/blender/editors/include/ED_space_api.h9
-rw-r--r--source/blender/editors/include/ED_text.h4
-rw-r--r--source/blender/editors/include/ED_transform.h2
-rw-r--r--source/blender/editors/include/ED_transform_snap_object_context.h12
-rw-r--r--source/blender/editors/include/ED_types.h4
-rw-r--r--source/blender/editors/include/ED_undo.h11
-rw-r--r--source/blender/editors/include/ED_util.h5
-rw-r--r--source/blender/editors/include/ED_uvedit.h10
-rw-r--r--source/blender/editors/include/ED_view3d.h80
-rw-r--r--source/blender/editors/include/UI_icons.h58
-rw-r--r--source/blender/editors/include/UI_interface.h74
-rw-r--r--source/blender/editors/include/UI_interface_icons.h4
-rw-r--r--source/blender/editors/include/UI_resources.h49
-rw-r--r--source/blender/editors/include/UI_view2d.h14
-rw-r--r--source/blender/editors/interface/CMakeLists.txt5
-rw-r--r--source/blender/editors/interface/interface.c306
-rw-r--r--source/blender/editors/interface/interface_align.c27
-rw-r--r--source/blender/editors/interface/interface_anim.c130
-rw-r--r--source/blender/editors/interface/interface_context_menu.c787
-rw-r--r--source/blender/editors/interface/interface_draw.c327
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c1
-rw-r--r--source/blender/editors/interface/interface_eyedropper_color.c4
-rw-r--r--source/blender/editors/interface/interface_eyedropper_depth.c5
-rw-r--r--source/blender/editors/interface/interface_handlers.c1297
-rw-r--r--source/blender/editors/interface/interface_icons.c265
-rw-r--r--source/blender/editors/interface/interface_intern.h67
-rw-r--r--source/blender/editors/interface/interface_layout.c946
-rw-r--r--source/blender/editors/interface/interface_ops.c37
-rw-r--r--source/blender/editors/interface/interface_panel.c467
-rw-r--r--source/blender/editors/interface/interface_query.c125
-rw-r--r--source/blender/editors/interface/interface_region_color_picker.c2
-rw-r--r--source/blender/editors/interface/interface_region_hud.c339
-rw-r--r--source/blender/editors/interface/interface_region_menu_pie.c12
-rw-r--r--source/blender/editors/interface/interface_region_menu_popup.c15
-rw-r--r--source/blender/editors/interface/interface_region_popover.c139
-rw-r--r--source/blender/editors/interface/interface_region_popup.c37
-rw-r--r--source/blender/editors/interface/interface_region_search.c37
-rw-r--r--source/blender/editors/interface/interface_region_tooltip.c6
-rw-r--r--source/blender/editors/interface/interface_regions.c4
-rw-r--r--source/blender/editors/interface/interface_style.c57
-rw-r--r--source/blender/editors/interface/interface_templates.c327
-rw-r--r--source/blender/editors/interface/interface_utils.c10
-rw-r--r--source/blender/editors/interface/interface_widgets.c1215
-rw-r--r--source/blender/editors/interface/resources.c1601
-rw-r--r--source/blender/editors/interface/view2d.c515
-rw-r--r--source/blender/editors/interface/view2d_ops.c488
-rw-r--r--source/blender/editors/io/io_alembic.c14
-rw-r--r--source/blender/editors/io/io_cache.c4
-rw-r--r--source/blender/editors/io/io_collada.c37
-rw-r--r--source/blender/editors/io/io_collada.h4
-rw-r--r--source/blender/editors/io/io_ops.c6
-rw-r--r--source/blender/editors/io/io_ops.h4
-rw-r--r--source/blender/editors/lattice/editlattice_select.c80
-rw-r--r--source/blender/editors/lattice/lattice_ops.c4
-rw-r--r--source/blender/editors/manipulator_library/manipulator_draw_utils.c5
-rw-r--r--source/blender/editors/manipulator_library/manipulator_library_intern.h1
-rw-r--r--source/blender/editors/manipulator_library/manipulator_library_presets.c1
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/arrow2d_manipulator.c11
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c60
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c111
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/cage2d_manipulator.c41
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/cage3d_manipulator.c27
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c19
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/grab3d_manipulator.c15
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/primitive3d_manipulator.c9
-rw-r--r--source/blender/editors/mask/mask_draw.c33
-rw-r--r--source/blender/editors/mask/mask_edit.c6
-rw-r--r--source/blender/editors/mask/mask_editaction.c11
-rw-r--r--source/blender/editors/mask/mask_select.c21
-rw-r--r--source/blender/editors/mesh/editface.c68
-rw-r--r--source/blender/editors/mesh/editmesh_add.c4
-rw-r--r--source/blender/editors/mesh/editmesh_add_manipulator.c6
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c131
-rw-r--r--source/blender/editors/mesh/editmesh_bisect.c9
-rw-r--r--source/blender/editors/mesh/editmesh_extrude.c261
-rw-r--r--source/blender/editors/mesh/editmesh_inset.c4
-rw-r--r--source/blender/editors/mesh/editmesh_intersect.c466
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c47
-rw-r--r--source/blender/editors/mesh/editmesh_knife_project.c27
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c60
-rw-r--r--source/blender/editors/mesh/editmesh_path.c113
-rw-r--r--source/blender/editors/mesh/editmesh_select.c334
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c596
-rw-r--r--source/blender/editors/mesh/editmesh_undo.c6
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c11
-rw-r--r--source/blender/editors/mesh/mesh_data.c43
-rw-r--r--source/blender/editors/mesh/mesh_intern.h2
-rw-r--r--source/blender/editors/mesh/mesh_mirror.c36
-rw-r--r--source/blender/editors/mesh/mesh_ops.c90
-rw-r--r--source/blender/editors/mesh/meshtools.c224
-rw-r--r--source/blender/editors/metaball/mball_edit.c44
-rw-r--r--source/blender/editors/metaball/mball_intern.h5
-rw-r--r--source/blender/editors/metaball/mball_ops.c19
-rw-r--r--source/blender/editors/object/object_add.c168
-rw-r--r--source/blender/editors/object/object_bake.c8
-rw-r--r--source/blender/editors/object/object_bake_api.c13
-rw-r--r--source/blender/editors/object/object_constraint.c476
-rw-r--r--source/blender/editors/object/object_data_transfer.c24
-rw-r--r--source/blender/editors/object/object_edit.c743
-rw-r--r--source/blender/editors/object/object_group.c325
-rw-r--r--source/blender/editors/object/object_hook.c192
-rw-r--r--source/blender/editors/object/object_intern.h33
-rw-r--r--source/blender/editors/object/object_modes.c18
-rw-r--r--source/blender/editors/object/object_modifier.c338
-rw-r--r--source/blender/editors/object/object_ops.c127
-rw-r--r--source/blender/editors/object/object_relations.c253
-rw-r--r--source/blender/editors/object/object_select.c312
-rw-r--r--source/blender/editors/object/object_shapekey.c20
-rw-r--r--source/blender/editors/object/object_transform.c106
-rw-r--r--source/blender/editors/object/object_vgroup.c126
-rw-r--r--source/blender/editors/physics/dynamicpaint_ops.c28
-rw-r--r--source/blender/editors/physics/particle_boids.c45
-rw-r--r--source/blender/editors/physics/particle_edit.c1117
-rw-r--r--source/blender/editors/physics/particle_edit_undo.c4
-rw-r--r--source/blender/editors/physics/particle_object.c308
-rw-r--r--source/blender/editors/physics/physics_fluid.c277
-rw-r--r--source/blender/editors/physics/physics_intern.h3
-rw-r--r--source/blender/editors/physics/physics_ops.c16
-rw-r--r--source/blender/editors/physics/physics_pointcache.c29
-rw-r--r--source/blender/editors/physics/rigidbody_constraint.c15
-rw-r--r--source/blender/editors/physics/rigidbody_object.c14
-rw-r--r--source/blender/editors/physics/rigidbody_world.c13
-rw-r--r--source/blender/editors/render/render_intern.h5
-rw-r--r--source/blender/editors/render/render_internal.c59
-rw-r--r--source/blender/editors/render/render_opengl.c28
-rw-r--r--source/blender/editors/render/render_ops.c5
-rw-r--r--source/blender/editors/render/render_preview.c158
-rw-r--r--source/blender/editors/render/render_shading.c88
-rw-r--r--source/blender/editors/render/render_update.c18
-rw-r--r--source/blender/editors/render/render_view.c17
-rw-r--r--source/blender/editors/scene/scene_edit.c5
-rw-r--r--source/blender/editors/screen/CMakeLists.txt2
-rw-r--r--source/blender/editors/screen/area.c718
-rw-r--r--source/blender/editors/screen/glutil.c23
-rw-r--r--source/blender/editors/screen/screen_context.c51
-rw-r--r--source/blender/editors/screen/screen_draw.c31
-rw-r--r--source/blender/editors/screen/screen_edit.c716
-rw-r--r--source/blender/editors/screen/screen_geometry.c462
-rw-r--r--source/blender/editors/screen/screen_intern.h32
-rw-r--r--source/blender/editors/screen/screen_ops.c1328
-rw-r--r--source/blender/editors/screen/screen_user_menu.c196
-rw-r--r--source/blender/editors/screen/screendump.c286
-rw-r--r--source/blender/editors/screen/workspace_edit.c26
-rw-r--r--source/blender/editors/screen/workspace_layout_edit.c14
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c43
-rw-r--r--source/blender/editors/sculpt_paint/paint_curve.c10
-rw-r--r--source/blender/editors/sculpt_paint/paint_hide.c25
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c103
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c8
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c488
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h4
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c1
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c72
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c57
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c73
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c80
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_color_ops.c1
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_proj.c40
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c56
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c132
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c37
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_uv.c20
-rw-r--r--source/blender/editors/sound/sound_intern.h5
-rw-r--r--source/blender/editors/sound/sound_ops.c12
-rw-r--r--source/blender/editors/space_action/action_buttons.c18
-rw-r--r--source/blender/editors/space_action/action_data.c212
-rw-r--r--source/blender/editors/space_action/action_draw.c97
-rw-r--r--source/blender/editors/space_action/action_edit.c535
-rw-r--r--source/blender/editors/space_action/action_intern.h13
-rw-r--r--source/blender/editors/space_action/action_ops.c84
-rw-r--r--source/blender/editors/space_action/action_select.c470
-rw-r--r--source/blender/editors/space_action/space_action.c265
-rw-r--r--source/blender/editors/space_api/spacetypes.c41
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c62
-rw-r--r--source/blender/editors/space_buttons/buttons_intern.h20
-rw-r--r--source/blender/editors/space_buttons/buttons_ops.c31
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c16
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c211
-rw-r--r--source/blender/editors/space_clip/clip_buttons.c2
-rw-r--r--source/blender/editors/space_clip/clip_dopesheet_draw.c13
-rw-r--r--source/blender/editors/space_clip/clip_dopesheet_ops.c2
-rw-r--r--source/blender/editors/space_clip/clip_draw.c51
-rw-r--r--source/blender/editors/space_clip/clip_editor.c2
-rw-r--r--source/blender/editors/space_clip/clip_graph_draw.c15
-rw-r--r--source/blender/editors/space_clip/clip_graph_ops.c2
-rw-r--r--source/blender/editors/space_clip/clip_intern.h2
-rw-r--r--source/blender/editors/space_clip/clip_ops.c6
-rw-r--r--source/blender/editors/space_clip/clip_toolbar.c4
-rw-r--r--source/blender/editors/space_clip/clip_utils.c11
-rw-r--r--source/blender/editors/space_clip/space_clip.c27
-rw-r--r--source/blender/editors/space_clip/tracking_ops.c8
-rw-r--r--source/blender/editors/space_clip/tracking_ops_intern.h2
-rw-r--r--source/blender/editors/space_clip/tracking_ops_orient.c27
-rw-r--r--source/blender/editors/space_clip/tracking_ops_stabilize.c1
-rw-r--r--source/blender/editors/space_console/console_draw.c12
-rw-r--r--source/blender/editors/space_console/console_intern.h2
-rw-r--r--source/blender/editors/space_console/console_ops.c105
-rw-r--r--source/blender/editors/space_console/space_console.c85
-rw-r--r--source/blender/editors/space_file/file_draw.c41
-rw-r--r--source/blender/editors/space_file/file_intern.h11
-rw-r--r--source/blender/editors/space_file/file_ops.c220
-rw-r--r--source/blender/editors/space_file/file_panels.c5
-rw-r--r--source/blender/editors/space_file/filelist.c72
-rw-r--r--source/blender/editors/space_file/filelist.h1
-rw-r--r--source/blender/editors/space_file/filesel.c50
-rw-r--r--source/blender/editors/space_file/fsmenu.c28
-rw-r--r--source/blender/editors/space_file/fsmenu.h5
-rw-r--r--source/blender/editors/space_file/space_file.c62
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c575
-rw-r--r--source/blender/editors/space_graph/graph_draw.c299
-rw-r--r--source/blender/editors/space_graph/graph_edit.c871
-rw-r--r--source/blender/editors/space_graph/graph_intern.h10
-rw-r--r--source/blender/editors/space_graph/graph_ops.c215
-rw-r--r--source/blender/editors/space_graph/graph_select.c506
-rw-r--r--source/blender/editors/space_graph/graph_utils.c115
-rw-r--r--source/blender/editors/space_graph/space_graph.c283
-rw-r--r--source/blender/editors/space_image/image_buttons.c97
-rw-r--r--source/blender/editors/space_image/image_draw.c51
-rw-r--r--source/blender/editors/space_image/image_edit.c23
-rw-r--r--source/blender/editors/space_image/image_intern.h8
-rw-r--r--source/blender/editors/space_image/image_ops.c370
-rw-r--r--source/blender/editors/space_image/space_image.c145
-rw-r--r--source/blender/editors/space_info/info_draw.c9
-rw-r--r--source/blender/editors/space_info/info_intern.h4
-rw-r--r--source/blender/editors/space_info/info_ops.c118
-rw-r--r--source/blender/editors/space_info/info_stats.c105
-rw-r--r--source/blender/editors/space_info/space_info.c63
-rw-r--r--source/blender/editors/space_info/textview.c19
-rw-r--r--source/blender/editors/space_info/textview.h2
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c132
-rw-r--r--source/blender/editors/space_nla/nla_channels.c214
-rw-r--r--source/blender/editors/space_nla/nla_draw.c185
-rw-r--r--source/blender/editors/space_nla/nla_edit.c914
-rw-r--r--source/blender/editors/space_nla/nla_intern.h5
-rw-r--r--source/blender/editors/space_nla/nla_ops.c138
-rw-r--r--source/blender/editors/space_nla/nla_select.c204
-rw-r--r--source/blender/editors/space_nla/space_nla.c185
-rw-r--r--source/blender/editors/space_node/drawnode.c372
-rw-r--r--source/blender/editors/space_node/node_add.c103
-rw-r--r--source/blender/editors/space_node/node_buttons.c42
-rw-r--r--source/blender/editors/space_node/node_draw.c296
-rw-r--r--source/blender/editors/space_node/node_edit.c388
-rw-r--r--source/blender/editors/space_node/node_group.c322
-rw-r--r--source/blender/editors/space_node/node_intern.h9
-rw-r--r--source/blender/editors/space_node/node_manipulators.c13
-rw-r--r--source/blender/editors/space_node/node_ops.c79
-rw-r--r--source/blender/editors/space_node/node_relationships.c124
-rw-r--r--source/blender/editors/space_node/node_select.c206
-rw-r--r--source/blender/editors/space_node/node_templates.c68
-rw-r--r--source/blender/editors/space_node/node_toolbar.c10
-rw-r--r--source/blender/editors/space_node/node_view.c41
-rw-r--r--source/blender/editors/space_node/space_node.c109
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c1081
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c992
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c559
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h74
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c141
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c345
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c671
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c728
-rw-r--r--source/blender/editors/space_outliner/outliner_utils.c31
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c75
-rw-r--r--source/blender/editors/space_script/script_intern.h5
-rw-r--r--source/blender/editors/space_script/space_script.c62
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c109
-rw-r--r--source/blender/editors/space_sequencer/sequencer_buttons.c9
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c191
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c351
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h9
-rw-r--r--source/blender/editors/space_sequencer/sequencer_modifier.c1
-rw-r--r--source/blender/editors/space_sequencer/sequencer_ops.c8
-rw-r--r--source/blender/editors/space_sequencer/sequencer_preview.c24
-rw-r--r--source/blender/editors/space_sequencer/sequencer_scopes.c26
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c139
-rw-r--r--source/blender/editors/space_sequencer/sequencer_view.c7
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c56
-rw-r--r--source/blender/editors/space_statusbar/CMakeLists.txt45
-rw-r--r--source/blender/editors/space_statusbar/space_statusbar.c187
-rw-r--r--source/blender/editors/space_text/space_text.c98
-rw-r--r--source/blender/editors/space_text/text_autocomplete.c13
-rw-r--r--source/blender/editors/space_text/text_draw.c65
-rw-r--r--source/blender/editors/space_text/text_format.c2
-rw-r--r--source/blender/editors/space_text/text_format.h4
-rw-r--r--source/blender/editors/space_text/text_format_lua.c12
-rw-r--r--source/blender/editors/space_text/text_format_osl.c2
-rw-r--r--source/blender/editors/space_text/text_header.c29
-rw-r--r--source/blender/editors/space_text/text_intern.h5
-rw-r--r--source/blender/editors/space_text/text_ops.c214
-rw-r--r--source/blender/editors/space_topbar/space_topbar.c61
-rw-r--r--source/blender/editors/space_userpref/space_userpref.c15
-rw-r--r--source/blender/editors/space_userpref/userpref_intern.h5
-rw-r--r--source/blender/editors/space_userpref/userpref_ops.c6
-rw-r--r--source/blender/editors/space_view3d/drawobject.c44
-rw-r--r--source/blender/editors/space_view3d/drawvolume.c21
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c214
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c21
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c153
-rw-r--r--source/blender/editors/space_view3d/view3d_draw_legacy.c50
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c271
-rw-r--r--source/blender/editors/space_view3d/view3d_fly.c16
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c92
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h14
-rw-r--r--source/blender/editors/space_view3d/view3d_iterators.c13
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_armature.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_camera.c41
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_empty.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_forcefield.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_lamp.c30
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_navigate.c100
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c29
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_ruler.c57
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c133
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c25
-rw-r--r--source/blender/editors/space_view3d/view3d_ruler.c56
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c315
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c238
-rw-r--r--source/blender/editors/space_view3d/view3d_toolbar.c142
-rw-r--r--source/blender/editors/space_view3d/view3d_utils.c62
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c178
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c8
-rw-r--r--source/blender/editors/transform/transform.c147
-rw-r--r--source/blender/editors/transform/transform.h16
-rw-r--r--source/blender/editors/transform/transform_constraints.c34
-rw-r--r--source/blender/editors/transform/transform_conversions.c199
-rw-r--r--source/blender/editors/transform/transform_generics.c43
-rw-r--r--source/blender/editors/transform/transform_input.c13
-rw-r--r--source/blender/editors/transform/transform_manipulator_3d.c279
-rw-r--r--source/blender/editors/transform/transform_ops.c32
-rw-r--r--source/blender/editors/transform/transform_snap.c138
-rw-r--r--source/blender/editors/transform/transform_snap_object.c1758
-rw-r--r--source/blender/editors/undo/ed_undo.c64
-rw-r--r--source/blender/editors/undo/undo_intern.h2
-rw-r--r--source/blender/editors/util/CMakeLists.txt1
-rw-r--r--source/blender/editors/util/ed_util.c22
-rw-r--r--source/blender/editors/uvedit/uvedit_buttons.c13
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c96
-rw-r--r--source/blender/editors/uvedit/uvedit_intern.h4
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c270
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c169
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.h5
-rw-r--r--source/blender/editors/uvedit/uvedit_smart_stitch.c13
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c185
424 files changed, 35263 insertions, 28310 deletions
diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt
index 358f82499c2..2b30382f4a4 100644
--- a/source/blender/editors/CMakeLists.txt
+++ b/source/blender/editors/CMakeLists.txt
@@ -54,6 +54,7 @@ if(WITH_BLENDER)
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)
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index c8d606db229..f0bde9dcdfb 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -65,10 +65,14 @@
#include "BKE_animsys.h"
#include "BKE_curve.h"
#include "BKE_key.h"
+#include "BKE_main.h"
#include "BKE_nla.h"
#include "BKE_context.h"
#include "GPU_immediate.h"
+#include "GPU_state.h"
+
+#include "DEG_depsgraph.h"
#include "UI_interface.h"
#include "UI_interface_icons.h"
@@ -117,10 +121,10 @@ static void acf_generic_root_backdrop(bAnimContext *ac, bAnimListElem *ale, floa
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);
-
+
/* 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);
@@ -160,7 +164,7 @@ static void acf_generic_dataexpand_backdrop(bAnimContext *ac, bAnimListElem *ale
static bool acf_show_channel_colors(bAnimContext *ac)
{
bool showGroupColors = false;
-
+
if (ac->sl) {
switch (ac->spacetype) {
case SPACE_ACTION:
@@ -179,7 +183,7 @@ static bool acf_show_channel_colors(bAnimContext *ac)
}
}
}
-
+
return showGroupColors;
}
@@ -190,19 +194,19 @@ static void acf_generic_channel_color(bAnimContext *ac, bAnimListElem *ale, floa
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
+
+ /* 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);
}
@@ -212,7 +216,7 @@ static void acf_generic_channel_color(bAnimContext *ac, bAnimListElem *ale, floa
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);
}
@@ -232,13 +236,13 @@ static void acf_generic_channel_backdrop(bAnimContext *ac, bAnimListElem *ale, f
float color[3];
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
-
+
/* set backdrop drawing color */
acf->get_backdrop_color(ac, ale, 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);
@@ -267,16 +271,16 @@ static short acf_generic_indention_2(bAnimContext *ac, bAnimListElem *ale)
static short acf_generic_indention_flexible(bAnimContext *UNUSED(ac), bAnimListElem *ale)
{
short indent = 0;
-
+
/* 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++;
}
-
+
/* no indention */
return indent;
}
@@ -285,7 +289,7 @@ static short acf_generic_indention_flexible(bAnimContext *UNUSED(ac), bAnimListE
static short acf_generic_basic_offset(bAnimContext *ac, bAnimListElem *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
@@ -298,21 +302,21 @@ 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)
+ /* 1 additional level (i.e. is indented one level in from material,
+ * so shift all right by one step)
*/
- return INDENT_STEP_SIZE;
-
+ return INDENT_STEP_SIZE;
+
case NTREE_COMPOSIT:
/* no additional levels needed */
- return 0;
-
+ return 0;
+
case NTREE_TEXTURE:
/* 2 additional levels */
return INDENT_STEP_SIZE * 2;
}
}
-
+
/* unknown */
return 0;
}
@@ -321,7 +325,7 @@ static short acf_nodetree_rootType_offset(bNodeTree *ntree)
static short acf_generic_group_offset(bAnimContext *ac, bAnimListElem *ale)
{
short offset = acf_generic_basic_offset(ac, ale);
-
+
if (ale->id) {
/* texture animdata */
if (GS(ale->id->name) == ID_TE) {
@@ -330,17 +334,17 @@ static short acf_generic_group_offset(bAnimContext *ac, bAnimListElem *ale)
/* 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);
-
+
/* 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;
}
@@ -351,7 +355,7 @@ static short acf_generic_group_offset(bAnimContext *ac, bAnimListElem *ale)
static void acf_generic_idblock_name(bAnimListElem *ale, char *name)
{
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);
@@ -362,7 +366,7 @@ static bool acf_generic_idblock_name_prop(bAnimListElem *ale, PointerRNA *ptr, P
{
RNA_id_pointer_create(ale->data, ptr);
*prop = RNA_struct_name_property(ptr->type);
-
+
return (*prop != NULL);
}
@@ -373,7 +377,7 @@ static bool acf_generic_idfill_name_prop(bAnimListElem *ale, PointerRNA *ptr, Pr
/* 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);
}
@@ -394,11 +398,11 @@ static bool acf_generic_dataexpand_setting_valid(bAnimContext *ac, bAnimListElem
/* 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));
-
+
/* select is ok for most "ds*" channels (e.g. dsmat) */
case ACHANNEL_SETTING_SELECT:
return true;
@@ -430,13 +434,13 @@ static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float ymi
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);
-
- /* rounded corners on LHS only
- * - top and bottom
- * - special hack: make the top a bit higher, since we are first...
+
+ /* 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);
@@ -481,14 +485,14 @@ static int acf_summary_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setti
static void *acf_summary_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
bAnimContext *ac = (bAnimContext *)ale->data;
-
- /* if data is valid, return pointer to active dopesheet's relevant flag
+
+ /* 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);
}
@@ -500,7 +504,7 @@ static void *acf_summary_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings s
}
/* all animation summary (DopeSheet only) type define */
-static bAnimChannelType ACF_SUMMARY =
+static bAnimChannelType ACF_SUMMARY =
{
"Summary", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
@@ -532,13 +536,13 @@ static bool acf_scene_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale)
{
switch (setting) {
/* muted only in NLA */
- case ACHANNEL_SETTING_MUTE:
+ case ACHANNEL_SETTING_MUTE:
return ((ac) && (ac->spacetype == SPACE_NLA));
-
+
/* visible only in Graph Editor */
- case ACHANNEL_SETTING_VISIBLE:
+ case ACHANNEL_SETTING_VISIBLE:
return ((ac) && (ac->spacetype == SPACE_IPO));
-
+
/* only select and expand supported otherwise */
case ACHANNEL_SETTING_SELECT:
case ACHANNEL_SETTING_EXPAND:
@@ -557,18 +561,18 @@ static int acf_scene_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setting
{
/* clear extra return data first */
*neg = false;
-
+
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_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;
@@ -582,30 +586,30 @@ static int acf_scene_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setting
static void *acf_scene_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
Scene *scene = (Scene *)ale->data;
-
+
/* clear extra return data first */
*type = 0;
-
+
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_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;
}
}
/* scene type define */
-static bAnimChannelType ACF_SCENE =
+static bAnimChannelType ACF_SCENE =
{
"Scene", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
@@ -630,20 +634,20 @@ 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_LAMP;
- case OB_MESH:
+ case OB_MESH:
return ICON_OUTLINER_OB_MESH;
- case OB_CAMERA:
+ case OB_CAMERA:
return ICON_OUTLINER_OB_CAMERA;
- case OB_CURVE:
+ case OB_CURVE:
return ICON_OUTLINER_OB_CURVE;
- case OB_MBALL:
+ case OB_MBALL:
return ICON_OUTLINER_OB_META;
- case OB_LATTICE:
+ case OB_LATTICE:
return ICON_OUTLINER_OB_LATTICE;
case OB_SPEAKER:
return ICON_OUTLINER_OB_SPEAKER;
@@ -651,11 +655,11 @@ static int acf_object_icon(bAnimListElem *ale)
return ICON_OUTLINER_OB_LIGHTPROBE;
case OB_ARMATURE:
return ICON_OUTLINER_OB_ARMATURE;
- case OB_FONT:
+ case OB_FONT:
return ICON_OUTLINER_OB_FONT;
- case OB_SURF:
+ case OB_SURF:
return ICON_OUTLINER_OB_SURFACE;
- case OB_EMPTY:
+ case OB_EMPTY:
return ICON_OUTLINER_OB_EMPTY;
default:
return ICON_OBJECT_DATA;
@@ -667,7 +671,7 @@ static void acf_object_name(bAnimListElem *ale, char *name)
{
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);
@@ -678,7 +682,7 @@ static bool acf_object_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRN
{
RNA_id_pointer_create(ale->id, ptr);
*prop = RNA_struct_name_property(ptr->type);
-
+
return (*prop != NULL);
}
@@ -687,16 +691,16 @@ static bool acf_object_setting_valid(bAnimContext *ac, bAnimListElem *ale, eAnim
{
Base *base = (Base *)ale->data;
Object *ob = base->object;
-
+
switch (setting) {
/* muted only in NLA */
- case ACHANNEL_SETTING_MUTE:
+ case ACHANNEL_SETTING_MUTE:
return ((ac) && (ac->spacetype == SPACE_NLA));
-
+
/* visible only in Graph Editor */
- case ACHANNEL_SETTING_VISIBLE:
+ case ACHANNEL_SETTING_VISIBLE:
return ((ac) && (ac->spacetype == SPACE_IPO) && (ob->adt));
-
+
/* only select and expand supported otherwise */
case ACHANNEL_SETTING_SELECT:
case ACHANNEL_SETTING_EXPAND:
@@ -715,18 +719,18 @@ static int acf_object_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settin
{
/* clear extra return data first */
*neg = false;
-
+
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
return SELECT;
-
+
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_VISIBLE: /* visible (only in Graph Editor) */
*neg = true;
return ADT_CURVES_NOT_VISIBLE;
@@ -744,17 +748,17 @@ static void *acf_object_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings se
{
Base *base = (Base *)ale->data;
Object *ob = base->object;
-
+
/* clear extra return data first */
*type = 0;
-
+
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
return GET_ACF_FLAG_PTR(ob->flag, type);
-
+
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:
@@ -768,11 +772,11 @@ static void *acf_object_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings se
}
/* object type define */
-static bAnimChannelType ACF_OBJECT =
+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 */
@@ -794,16 +798,16 @@ static void acf_group_color(bAnimContext *ac, bAnimListElem *ale, float r_color[
{
bActionGroup *agrp = (bActionGroup *)ale->data;
bool showGroupColors = acf_show_channel_colors(ac);
-
+
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);
-
+
/* copy the colors over, transforming from bytes to floats */
rgb_uchar_to_float(r_color, cp);
}
@@ -824,10 +828,10 @@ static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc
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);
-
+
/* 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);
@@ -837,7 +841,7 @@ static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc
static void acf_group_name(bAnimListElem *ale, char *name)
{
bActionGroup *agrp = (bActionGroup *)ale->data;
-
+
/* just copy the name... */
if (agrp && name)
BLI_strncpy(name, agrp->name, ANIM_CHAN_NAME_SIZE);
@@ -848,7 +852,7 @@ static bool acf_group_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA
{
RNA_pointer_create(ale->id, &RNA_ActionGroup, ale->data, ptr);
*prop = RNA_struct_name_property(ptr->type);
-
+
return (*prop != NULL);
}
@@ -860,7 +864,7 @@ static bool acf_group_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale)
/* 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_IPO);
@@ -878,22 +882,22 @@ static int acf_group_setting_flag(bAnimContext *ac, eAnimChannel_Settings settin
{
/* clear extra return data first */
*neg = false;
-
+
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_IPO) ?
+ return (ac->spacetype == SPACE_IPO) ?
AGRP_EXPANDED_G : /* Graph Editor case */
AGRP_EXPANDED; /* DopeSheet and elsewhere */
}
-
+
case ACHANNEL_SETTING_MUTE: /* muted */
return AGRP_MUTED;
@@ -903,7 +907,7 @@ static int acf_group_setting_flag(bAnimContext *ac, eAnimChannel_Settings settin
case ACHANNEL_SETTING_PROTECT: /* protected */
return AGRP_PROTECTED;
-
+
case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */
*neg = 1;
return AGRP_NOTVISIBLE;
@@ -921,17 +925,17 @@ static int acf_group_setting_flag(bAnimContext *ac, eAnimChannel_Settings settin
static void *acf_group_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
{
bActionGroup *agrp = (bActionGroup *)ale->data;
-
+
/* all flags are just in agrp->flag for now... */
return GET_ACF_FLAG_PTR(agrp->flag, type);
}
/* group type define */
-static bAnimChannelType ACF_GROUP =
+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 */
@@ -958,9 +962,9 @@ static void acf_fcurve_name(bAnimListElem *ale, char *name)
static bool acf_fcurve_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
FCurve *fcu = (FCurve *)ale->data;
-
- /* Ctrl-Click Usability Convenience Hack:
- * For disabled F-Curves, allow access to the RNA Path
+
+ /* 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) {
@@ -971,7 +975,7 @@ static bool acf_fcurve_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRN
/* for "normal" F-Curves - no editable name, but *prop may not be set properly yet... */
*prop = NULL;
}
-
+
return (*prop != NULL);
}
@@ -979,21 +983,21 @@ static bool acf_fcurve_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRN
static bool acf_fcurve_setting_valid(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting)
{
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;
-
+
/* 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_IPO);
@@ -1011,20 +1015,20 @@ static int acf_fcurve_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settin
{
/* clear extra return data first */
*neg = false;
-
+
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
return FCURVE_SELECTED;
-
+
case ACHANNEL_SETTING_MUTE: /* muted */
return FCURVE_MUTED;
-
+
case ACHANNEL_SETTING_PROTECT: /* protected */
return FCURVE_PROTECTED;
-
+
case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */
return FCURVE_VISIBLE;
-
+
case ACHANNEL_SETTING_MOD_OFF:
*neg = 1;
return FCURVE_MOD_OFF;
@@ -1038,17 +1042,17 @@ static int acf_fcurve_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settin
static void *acf_fcurve_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
{
FCurve *fcu = (FCurve *)ale->data;
-
+
/* all flags are just in agrp->flag for now... */
return GET_ACF_FLAG_PTR(fcu->flag, type);
}
/* fcurve type define */
-static bAnimChannelType ACF_FCURVE =
+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?
@@ -1080,11 +1084,11 @@ static void acf_nla_controls_backdrop(bAnimContext *ac, bAnimListElem *ale, floa
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);
-
- /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
+
+ /* 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);
}
@@ -1103,9 +1107,9 @@ static bool acf_nla_controls_setting_valid(bAnimContext *UNUSED(ac), bAnimListEl
/* supported */
case ACHANNEL_SETTING_EXPAND:
return true;
-
+
// TOOD: selected?
-
+
default: /* unsupported */
return false;
}
@@ -1116,12 +1120,12 @@ static int acf_nla_controls_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_
{
/* clear extra return data first */
*neg = false;
-
+
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
*neg = true;
return ADT_NLA_SKEYS_COLLAPSED;
-
+
default:
/* this shouldn't happen */
return 0;
@@ -1132,7 +1136,7 @@ static int acf_nla_controls_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_
static void *acf_nla_controls_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
{
AnimData *adt = (AnimData *)ale->data;
-
+
/* all flags are just in adt->flag for now... */
return GET_ACF_FLAG_PTR(adt->flag, type);
}
@@ -1143,11 +1147,11 @@ static int acf_nla_controls_icon(bAnimListElem *UNUSED(ale))
}
/* NLA Control FCurves Expander type define */
-static bAnimChannelType ACF_NLACONTROLS =
+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 */
@@ -1171,7 +1175,7 @@ static void acf_nla_curve_name(bAnimListElem *ale, char *name)
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) {
@@ -1186,11 +1190,11 @@ static void acf_nla_curve_name(bAnimListElem *ale, char *name)
/* NLA Control F-Curve type define */
-static bAnimChannelType ACF_NLACURVE =
+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 */
@@ -1221,7 +1225,7 @@ static bool acf_fillactd_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *
case ACHANNEL_SETTING_SELECT:
case ACHANNEL_SETTING_EXPAND:
return true;
-
+
default:
return false;
}
@@ -1232,15 +1236,15 @@ static int acf_fillactd_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Sett
{
/* clear extra return data first */
*neg = false;
-
+
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
-
+
case ACHANNEL_SETTING_EXPAND: /* expanded */
*neg = true;
return ACT_COLLAPSED;
-
+
default: /* unsupported */
return 0;
}
@@ -1251,10 +1255,10 @@ static void *acf_fillactd_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings
{
bAction *act = (bAction *)ale->data;
AnimData *adt = ale->adt;
-
+
/* clear extra return data first */
*type = 0;
-
+
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
if (adt) {
@@ -1264,18 +1268,18 @@ static void *acf_fillactd_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings
case ACHANNEL_SETTING_EXPAND: /* expanded */
return GET_ACF_FLAG_PTR(act->flag, type);
-
+
default: /* unsupported */
return NULL;
}
}
/* object action expander type define */
-static bAnimChannelType ACF_FILLACTD =
+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 */
@@ -1311,7 +1315,7 @@ static bool acf_filldrivers_setting_valid(bAnimContext *UNUSED(ac), bAnimListEle
/* only expand supported */
case ACHANNEL_SETTING_EXPAND:
return true;
-
+
default:
return false;
}
@@ -1322,12 +1326,12 @@ static int acf_filldrivers_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_S
{
/* clear extra return data first */
*neg = false;
-
+
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
*neg = true;
return ADT_DRIVERS_COLLAPSED;
-
+
default: /* unsupported */
return 0;
}
@@ -1337,25 +1341,25 @@ static int acf_filldrivers_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_S
static void *acf_filldrivers_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
AnimData *adt = (AnimData *)ale->data;
-
+
/* clear extra return data first */
*type = 0;
-
+
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
return GET_ACF_FLAG_PTR(adt->flag, type);
-
+
default: /* unsupported */
return NULL;
}
}
/* drivers expander type define */
-static bAnimChannelType ACF_FILLDRIVERS =
+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 */
@@ -1384,21 +1388,21 @@ static int acf_dsmat_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setting
{
/* clear extra return data first */
*neg = false;
-
+
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_VISIBLE: /* visible (only in Graph Editor) */
*neg = true;
return ADT_CURVES_NOT_VISIBLE;
-
+
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
-
+
default: /* unsupported */
return 0;
}
@@ -1408,14 +1412,14 @@ static int acf_dsmat_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setting
static void *acf_dsmat_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
Material *ma = (Material *)ale->data;
-
+
/* clear extra return data first */
*type = 0;
-
+
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) */
@@ -1433,7 +1437,7 @@ 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 */
@@ -1461,21 +1465,21 @@ static int acf_dslam_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setting
{
/* clear extra return data first */
*neg = false;
-
+
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_VISIBLE: /* visible (only in Graph Editor) */
*neg = true;
return ADT_CURVES_NOT_VISIBLE;
-
+
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
-
+
default: /* unsupported */
return 0;
}
@@ -1485,21 +1489,21 @@ static int acf_dslam_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setting
static void *acf_dslam_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
Lamp *la = (Lamp *)ale->data;
-
+
/* clear extra return data first */
*type = 0;
-
+
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;
-
+
default: /* unsupported */
return NULL;
}
@@ -1510,7 +1514,7 @@ static bAnimChannelType ACF_DSLAM =
{
"Lamp Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
-
+
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
acf_generic_indention_1, /* indent level */
@@ -1545,21 +1549,21 @@ static int acf_dstex_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setting
{
/* clear extra return data first */
*neg = false;
-
+
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_VISIBLE: /* visible (only in Graph Editor) */
*neg = true;
return ADT_CURVES_NOT_VISIBLE;
-
+
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
-
+
default: /* unsupported */
return 0;
}
@@ -1569,21 +1573,21 @@ static int acf_dstex_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setting
static void *acf_dstex_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
Tex *tex = (Tex *)ale->data;
-
+
/* clear extra return data first */
*type = 0;
-
+
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;
-
+
default: /* unsupported */
return NULL;
}
@@ -1594,7 +1598,7 @@ 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 */
@@ -1704,18 +1708,18 @@ static int acf_dscam_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setting
{
/* clear extra return data first */
*neg = false;
-
+
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_VISIBLE: /* visible (only in Graph Editor) */
*neg = true;
return ADT_CURVES_NOT_VISIBLE;
-
+
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
@@ -1731,14 +1735,14 @@ static int acf_dscam_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setting
static void *acf_dscam_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
Camera *ca = (Camera *)ale->data;
-
+
/* clear extra return data first */
*type = 0;
-
+
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) */
@@ -1746,7 +1750,7 @@ static void *acf_dscam_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings set
if (ca->adt)
return GET_ACF_FLAG_PTR(ca->adt->flag, type);
return NULL;
-
+
default: /* unsupported */
return NULL;
}
@@ -1757,7 +1761,7 @@ 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 */
@@ -1779,7 +1783,7 @@ static int acf_dscur_icon(bAnimListElem *ale)
{
Curve *cu = (Curve *)ale->data;
short obtype = BKE_curve_type_get(cu);
-
+
switch (obtype) {
case OB_FONT:
return ICON_FONT_DATA;
@@ -1795,21 +1799,21 @@ static int acf_dscur_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setting
{
/* clear extra return data first */
*neg = false;
-
+
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_VISIBLE: /* visible (only in Graph Editor) */
*neg = true;
return ADT_CURVES_NOT_VISIBLE;
-
+
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
-
+
default: /* unsupported */
return 0;
}
@@ -1819,21 +1823,21 @@ static int acf_dscur_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setting
static void *acf_dscur_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
Curve *cu = (Curve *)ale->data;
-
+
/* clear extra return data first */
*type = 0;
-
+
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;
-
+
default: /* unsupported */
return NULL;
}
@@ -1844,7 +1848,7 @@ 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 */
@@ -1872,21 +1876,21 @@ static int acf_dsskey_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settin
{
/* clear extra return data first */
*neg = false;
-
+
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_VISIBLE: /* visible (only in Graph Editor) */
*neg = true;
return ADT_CURVES_NOT_VISIBLE;
-
+
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
-
+
default: /* unsupported */
return 0;
}
@@ -1896,21 +1900,21 @@ static int acf_dsskey_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settin
static void *acf_dsskey_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
Key *key = (Key *)ale->data;
-
+
/* clear extra return data first */
*type = 0;
-
+
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;
-
+
default: /* unsupported */
return NULL;
}
@@ -1921,7 +1925,7 @@ 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 */
@@ -1949,21 +1953,21 @@ static int acf_dswor_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setting
{
/* clear extra return data first */
*neg = false;
-
+
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_VISIBLE: /* visible (only in Graph Editor) */
*neg = true;
return ADT_CURVES_NOT_VISIBLE;
-
+
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
-
+
default: /* unsupported */
return 0;
}
@@ -1973,21 +1977,21 @@ static int acf_dswor_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setting
static void *acf_dswor_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
World *wo = (World *)ale->data;
-
+
/* clear extra return data first */
*type = 0;
-
+
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;
-
+
default: /* unsupported */
return NULL;
}
@@ -1998,7 +2002,7 @@ 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 */
@@ -2026,21 +2030,21 @@ static int acf_dspart_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settin
{
/* clear extra return data first */
*neg = false;
-
+
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
return 0;
-
+
case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
return ADT_NLA_EVAL_OFF;
-
+
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
*neg = true;
return ADT_CURVES_NOT_VISIBLE;
-
+
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
-
+
default: /* unsupported */
return 0;
}
@@ -2051,16 +2055,16 @@ static void *acf_dspart_setting_ptr(bAnimListElem *UNUSED(ale), eAnimChannel_Set
{
/* clear extra return data first */
*type = 0;
-
+
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
return NULL;
-
+
case ACHANNEL_SETTING_SELECT: /* selected */
case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
return NULL;
-
+
default: /* unsupported */
return NULL;
}
@@ -2071,7 +2075,7 @@ 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 */
@@ -2099,21 +2103,21 @@ static int acf_dsmball_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setti
{
/* clear extra return data first */
*neg = false;
-
+
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_VISIBLE: /* visible (only in Graph Editor) */
*neg = true;
return ADT_CURVES_NOT_VISIBLE;
-
+
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
-
+
default: /* unsupported */
return 0;
}
@@ -2123,21 +2127,21 @@ static int acf_dsmball_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setti
static void *acf_dsmball_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
MetaBall *mb = (MetaBall *)ale->data;
-
+
/* clear extra return data first */
*type = 0;
-
+
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;
-
+
default: /* unsupported */
return NULL;
}
@@ -2148,7 +2152,7 @@ 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 */
@@ -2176,21 +2180,21 @@ static int acf_dsarm_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setting
{
/* clear extra return data first */
*neg = false;
-
+
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_VISIBLE: /* visible (only in Graph Editor) */
*neg = true;
return ADT_CURVES_NOT_VISIBLE;
-
+
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
-
+
default: /* unsupported */
return 0;
}
@@ -2200,21 +2204,21 @@ static int acf_dsarm_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setting
static void *acf_dsarm_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
bArmature *arm = (bArmature *)ale->data;
-
+
/* clear extra return data first */
*type = 0;
-
+
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;
-
+
default: /* unsupported */
return NULL;
}
@@ -2225,7 +2229,7 @@ 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 */
@@ -2253,9 +2257,9 @@ static short acf_dsntree_offset(bAnimContext *ac, bAnimListElem *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;
}
@@ -2264,21 +2268,21 @@ static int acf_dsntree_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setti
{
/* clear extra return data first */
*neg = false;
-
+
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_VISIBLE: /* visible (only in Graph Editor) */
*neg = true;
return ADT_CURVES_NOT_VISIBLE;
-
+
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
-
+
default: /* unsupported */
return 0;
}
@@ -2288,21 +2292,21 @@ static int acf_dsntree_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setti
static void *acf_dsntree_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
bNodeTree *ntree = (bNodeTree *)ale->data;
-
+
/* clear extra return data first */
*type = 0;
-
+
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;
-
+
default: /* unsupported */
return NULL;
}
@@ -2313,7 +2317,7 @@ 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 */
@@ -2341,21 +2345,21 @@ static int acf_dslinestyle_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_S
{
/* clear extra return data first */
*neg = false;
-
+
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_VISIBLE: /* visible (only in Graph Editor) */
*neg = true;
return ADT_CURVES_NOT_VISIBLE;
-
+
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
-
+
default: /* unsupported */
return 0;
}
@@ -2365,21 +2369,21 @@ static int acf_dslinestyle_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_S
static void *acf_dslinestyle_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ale->data;
-
+
/* clear extra return data first */
*type = 0;
-
+
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;
-
+
default: /* unsupported */
return NULL;
}
@@ -2390,16 +2394,16 @@ 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 */
@@ -2418,21 +2422,21 @@ static int acf_dsmesh_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settin
{
/* clear extra return data first */
*neg = false;
-
+
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_VISIBLE: /* visible (only in Graph Editor) */
*neg = true;
return ADT_CURVES_NOT_VISIBLE;
-
+
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
-
+
default: /* unsupported */
return 0;
}
@@ -2442,21 +2446,21 @@ static int acf_dsmesh_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settin
static void *acf_dsmesh_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
Mesh *me = (Mesh *)ale->data;
-
+
/* clear extra return data first */
*type = 0;
-
+
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;
-
+
default: /* unsupported */
return NULL;
}
@@ -2467,7 +2471,7 @@ 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
@@ -2495,21 +2499,21 @@ static int acf_dslat_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setting
{
/* clear extra return data first */
*neg = false;
-
+
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_VISIBLE: /* visible (only in Graph Editor) */
*neg = true;
return ADT_CURVES_NOT_VISIBLE;
-
+
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
-
+
default: /* unsupported */
return 0;
}
@@ -2519,21 +2523,21 @@ static int acf_dslat_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setting
static void *acf_dslat_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
Lattice *lt = (Lattice *)ale->data;
-
+
/* clear extra return data first */
*type = 0;
-
+
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;
-
+
default: /* unsupported */
return NULL;
}
@@ -2544,7 +2548,7 @@ 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
@@ -2572,21 +2576,21 @@ static int acf_dsspk_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setting
{
/* clear extra return data first */
*neg = false;
-
+
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_VISIBLE: /* visible (only in Graph Editor) */
*neg = true;
return ADT_CURVES_NOT_VISIBLE;
-
+
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
-
+
default: /* unsupported */
return 0;
}
@@ -2596,21 +2600,21 @@ static int acf_dsspk_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setting
static void *acf_dsspk_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
Speaker *spk = (Speaker *)ale->data;
-
+
/* clear extra return data first */
*type = 0;
-
+
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;
-
+
default: /* unsupported */
return NULL;
}
@@ -2621,7 +2625,7 @@ 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 */
@@ -2649,21 +2653,21 @@ static int acf_dsgpencil_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Set
{
/* clear extra return data first */
*neg = false;
-
+
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_VISIBLE: /* visible (only in Graph Editor) */
*neg = true;
return ADT_CURVES_NOT_VISIBLE;
-
+
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
-
+
default: /* unsupported */
return 0;
}
@@ -2673,21 +2677,21 @@ static int acf_dsgpencil_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Set
static void *acf_dsgpencil_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
bGPdata *gpd = (bGPdata *)ale->data;
-
+
/* clear extra return data first */
*type = 0;
-
+
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;
-
+
default: /* unsupported */
return NULL;
}
@@ -2698,7 +2702,7 @@ 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 */
@@ -2797,7 +2801,7 @@ static bAnimChannelType ACF_DSMCLIP =
static void acf_shapekey_name(bAnimListElem *ale, char *name)
{
KeyBlock *kb = (KeyBlock *)ale->data;
-
+
/* just copy the name... */
if (kb && name) {
/* if the KeyBlock had a name, use it, otherwise use the index */
@@ -2812,15 +2816,15 @@ static void acf_shapekey_name(bAnimListElem *ale, char *name)
static bool acf_shapekey_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
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);
-
+
return (*prop != NULL);
}
-
+
return false;
}
@@ -2832,7 +2836,7 @@ static bool acf_shapekey_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *
case ACHANNEL_SETTING_MUTE: /* muted */
case ACHANNEL_SETTING_PROTECT: /* protected */
return true;
-
+
/* nothing else is supported */
default:
return false;
@@ -2844,17 +2848,17 @@ static int acf_shapekey_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Sett
{
/* clear extra return data first */
*neg = false;
-
+
switch (setting) {
case ACHANNEL_SETTING_MUTE: /* mute */
return KEYBLOCK_MUTE;
-
+
case ACHANNEL_SETTING_SELECT: /* selected */
return KEYBLOCK_SEL;
-
+
case ACHANNEL_SETTING_PROTECT: /* locked */
return KEYBLOCK_LOCKED;
-
+
default: /* unsupported */
return 0;
}
@@ -2864,16 +2868,16 @@ static int acf_shapekey_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Sett
static void *acf_shapekey_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
KeyBlock *kb = (KeyBlock *)ale->data;
-
+
/* 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);
-
+
default: /* unsupported */
return NULL;
}
@@ -2884,7 +2888,7 @@ 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 */
@@ -2922,7 +2926,7 @@ static bool acf_gpd_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSE
case ACHANNEL_SETTING_SELECT:
case ACHANNEL_SETTING_EXPAND:
return true;
-
+
default:
return false;
}
@@ -2933,14 +2937,14 @@ static int acf_gpd_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings
{
/* clear extra return data first */
*neg = false;
-
+
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
return AGRP_SELECTED;
-
+
case ACHANNEL_SETTING_EXPAND: /* expanded */
return GP_DATA_EXPAND;
-
+
default:
/* these shouldn't happen */
return 0;
@@ -2951,17 +2955,17 @@ static int acf_gpd_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings
static void *acf_gpd_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
{
bGPdata *gpd = (bGPdata *)ale->data;
-
+
/* 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 =
+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 */
@@ -2982,7 +2986,7 @@ static bAnimChannelType ACF_GPD =
static void acf_gpl_name(bAnimListElem *ale, char *name)
{
bGPDlayer *gpl = (bGPDlayer *)ale->data;
-
+
if (gpl && name)
BLI_strncpy(name, gpl->info, ANIM_CHAN_NAME_SIZE);
}
@@ -2993,10 +2997,10 @@ static bool acf_gpl_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA *
if (ale->data) {
RNA_pointer_create(ale->id, &RNA_GPencilLayer, ale->data, ptr);
*prop = RNA_struct_name_property(ptr->type);
-
+
return (*prop != NULL);
}
-
+
return false;
}
@@ -3008,7 +3012,7 @@ static bool acf_gpl_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSE
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;
@@ -3020,21 +3024,21 @@ static int acf_gpl_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings
{
/* clear extra return data first */
*neg = false;
-
+
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_VISIBLE: /* visiblity of the layers (NOT muting) */
*neg = true;
return GP_LAYER_HIDE;
-
+
case ACHANNEL_SETTING_PROTECT: /* protected */
return GP_LAYER_LOCKED;
-
+
default: /* unsupported */
return 0;
}
@@ -3044,26 +3048,26 @@ static int acf_gpl_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings
static void *acf_gpl_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
{
bGPDlayer *gpl = (bGPDlayer *)ale->data;
-
+
/* 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 =
+static bAnimChannelType ACF_GPL =
{
"GPencil 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_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 */
@@ -3093,7 +3097,7 @@ static bool acf_mask_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUS
case ACHANNEL_SETTING_SELECT:
case ACHANNEL_SETTING_EXPAND:
return true;
-
+
default:
return false;
}
@@ -3104,15 +3108,15 @@ static int acf_mask_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings
{
/* clear extra return data first */
*neg = false;
-
+
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
return AGRP_SELECTED;
-
+
case ACHANNEL_SETTING_EXPAND: /* expanded */
return MASK_ANIMF_EXPAND;
-
- default:
+
+ default:
/* this shouldn't happen */
return 0;
}
@@ -3122,7 +3126,7 @@ static int acf_mask_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings
static void *acf_mask_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
{
Mask *mask = (Mask *)ale->data;
-
+
/* all flags are just in mask->flag for now... */
return GET_ACF_FLAG_PTR(mask->flag, type);
}
@@ -3132,16 +3136,16 @@ 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 */
@@ -3153,7 +3157,7 @@ static bAnimChannelType ACF_MASKDATA =
static void acf_masklay_name(bAnimListElem *ale, char *name)
{
MaskLayer *masklay = (MaskLayer *)ale->data;
-
+
if (masklay && name)
BLI_strncpy(name, masklay->name, ANIM_CHAN_NAME_SIZE);
}
@@ -3164,7 +3168,7 @@ static bool acf_masklay_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyR
if (ale->data) {
RNA_pointer_create(ale->id, &RNA_MaskLayer, ale->data, ptr);
*prop = RNA_struct_name_property(ptr->type);
-
+
return (*prop != NULL);
}
@@ -3180,7 +3184,7 @@ static bool acf_masklay_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *U
case ACHANNEL_SETTING_VISIBLE: /* graph editor only */
case ACHANNEL_SETTING_SOLO: /* nla editor only */
return false;
-
+
/* always available */
default:
return true;
@@ -3192,14 +3196,14 @@ static int acf_masklay_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setti
{
/* clear extra return data first */
*neg = false;
-
+
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
return MASK_LAYERFLAG_SELECT;
-
+
case ACHANNEL_SETTING_PROTECT: /* protected */
return MASK_LAYERFLAG_LOCKED;
-
+
default: /* unsupported */
return 0;
}
@@ -3209,7 +3213,7 @@ static int acf_masklay_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setti
static void *acf_masklay_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
{
MaskLayer *masklay = (MaskLayer *)ale->data;
-
+
/* all flags are just in masklay->flag for now... */
return GET_ACF_FLAG_PTR(masklay->flag, type);
}
@@ -3219,16 +3223,16 @@ 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 */
@@ -3242,7 +3246,7 @@ static void acf_nlatrack_color(bAnimContext *UNUSED(ac), bAnimListElem *ale, flo
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) {
@@ -3250,7 +3254,7 @@ static void acf_nlatrack_color(bAnimContext *UNUSED(ac), bAnimListElem *ale, flo
nonSolo = true;
}
}
-
+
/* set color for nla track */
UI_GetThemeColorShade3fv(TH_HEADER, ((nonSolo == false) ? 20 : -20), r_color);
}
@@ -3259,7 +3263,7 @@ static void acf_nlatrack_color(bAnimContext *UNUSED(ac), bAnimListElem *ale, flo
static void acf_nlatrack_name(bAnimListElem *ale, char *name)
{
NlaTrack *nlt = (NlaTrack *)ale->data;
-
+
if (nlt && name)
BLI_strncpy(name, nlt->name, ANIM_CHAN_NAME_SIZE);
}
@@ -3270,10 +3274,10 @@ static bool acf_nlatrack_name_prop(bAnimListElem *ale, PointerRNA *ptr, Property
if (ale->data) {
RNA_pointer_create(ale->id, &RNA_NlaTrack, ale->data, ptr);
*prop = RNA_struct_name_property(ptr->type);
-
+
return (*prop != NULL);
}
-
+
return false;
}
@@ -3282,14 +3286,14 @@ static bool acf_nlatrack_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *
{
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:
@@ -3306,8 +3310,8 @@ static bool acf_nlatrack_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *
return false;
}
}
-
-
+
+
/* ok - no tracks are solo'd, and this isn't being tweaked */
return true;
}
@@ -3315,7 +3319,7 @@ static bool acf_nlatrack_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *
/* unsupported - this track is being tweaked */
return false;
}
-
+
/* unsupported */
default:
return false;
@@ -3327,20 +3331,20 @@ static int acf_nlatrack_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Sett
{
/* clear extra return data first */
*neg = false;
-
+
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
return NLATRACK_SELECTED;
-
+
case ACHANNEL_SETTING_MUTE: /* muted */
return NLATRACK_MUTED;
-
+
case ACHANNEL_SETTING_PROTECT: /* protected */
return NLATRACK_PROTECTED;
-
+
case ACHANNEL_SETTING_SOLO: /* solo */
return NLATRACK_SOLO;
-
+
default: /* unsupported */
return 0;
}
@@ -3354,20 +3358,20 @@ static void *acf_nlatrack_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings
}
/* nla track type define */
-static bAnimChannelType ACF_NLATRACK =
+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 */
@@ -3379,7 +3383,7 @@ static bAnimChannelType ACF_NLATRACK =
static int acf_nlaaction_icon(bAnimListElem *ale)
{
AnimData *adt = ale->adt;
-
+
/* indicate tweaking-action state by changing the icon... */
if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
return ICON_ACTION_TWEAK;
@@ -3389,28 +3393,28 @@ static int acf_nlaaction_icon(bAnimListElem *ale)
}
}
-/* Backdrop color for nla action channel
+/* Backdrop color for nla action channel
* Although this can't be used directly for NLA Action drawing,
* it is still needed for use behind the RHS toggles
*/
static void acf_nlaaction_color(bAnimContext *UNUSED(ac), bAnimListElem *ale, float r_color[3])
{
float color[4];
-
+
/* Action Line
- * The alpha values action_get_color returns are only useful for drawing
+ * 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);
}
-
+
/* backdrop for nla action channel */
static void acf_nlaaction_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
{
@@ -3419,14 +3423,14 @@ static void acf_nlaaction_backdrop(bAnimContext *ac, bAnimListElem *ale, float y
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
+ * 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
@@ -3447,7 +3451,7 @@ static void acf_nlaaction_backdrop(bAnimContext *ac, bAnimListElem *ale, float y
static void acf_nlaaction_name(bAnimListElem *ale, char *name)
{
bAction *act = (bAction *)ale->data;
-
+
if (name) {
if (act) {
// TODO: add special decoration when doing this in tweaking mode?
@@ -3465,10 +3469,10 @@ static bool acf_nlaaction_name_prop(bAnimListElem *ale, PointerRNA *ptr, Propert
if (ale->data) {
RNA_pointer_create(ale->id, &RNA_Action, ale->data, ptr);
*prop = RNA_struct_name_property(ptr->type);
-
+
return (*prop != NULL);
}
-
+
return false;
}
@@ -3476,7 +3480,7 @@ static bool acf_nlaaction_name_prop(bAnimListElem *ale, PointerRNA *ptr, Propert
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 */
@@ -3488,7 +3492,7 @@ static bool acf_nlaaction_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem
else {
return false;
}
-
+
/* unsupported */
default:
return false;
@@ -3500,12 +3504,12 @@ static int acf_nlaaction_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Set
{
/* clear extra return data first */
*neg = false;
-
+
switch (setting) {
case ACHANNEL_SETTING_PINNED: /* pinned - map/unmap */
*neg = true; // XXX
return ADT_NLA_EDIT_NOMAP;
-
+
default: /* unsupported */
return 0;
}
@@ -3519,20 +3523,20 @@ static void *acf_nlaaction_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings
}
/* nla action type define */
-static bAnimChannelType ACF_NLAACTION =
+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 */
@@ -3550,31 +3554,31 @@ static short ACF_INIT = 1; /* when non-zero, the list needs to be updated */
static void ANIM_init_channel_typeinfo_data(void)
{
int type = 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 */
-
+
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_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_DSMAT; /* Material Channel */
animchannelTypeInfo[type++] = &ACF_DSLAM; /* Lamp Channel */
animchannelTypeInfo[type++] = &ACF_DSCAM; /* Camera Channel */
@@ -3593,19 +3597,19 @@ static void ANIM_init_channel_typeinfo_data(void)
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_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_NLATRACK; /* NLA Track */
animchannelTypeInfo[type++] = &ACF_NLAACTION; /* NLA Action */
}
-}
+}
/* Get type info from given channel type */
const bAnimChannelType *ANIM_channel_get_typeinfo(bAnimListElem *ale)
@@ -3613,10 +3617,10 @@ const bAnimChannelType *ANIM_channel_get_typeinfo(bAnimListElem *ale)
/* santiy checks */
if (ale == NULL)
return NULL;
-
+
/* 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];
@@ -3630,21 +3634,21 @@ const bAnimChannelType *ANIM_channel_get_typeinfo(bAnimListElem *ale)
void ANIM_channel_debug_print_info(bAnimListElem *ale, short indent_level)
{
const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
-
+
/* print indents */
for (; indent_level > 0; indent_level--)
printf(" ");
-
+
/* 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));
-
+
/* print type name + ui name */
printf("ChanType: <%s> Name: \"%s\"\n", acf->channel_type_name, name);
}
@@ -3656,13 +3660,13 @@ void ANIM_channel_debug_print_info(bAnimListElem *ale, short indent_level)
/* --------------------------- */
-/* Check if some setting for a channel is enabled
+/* Check if some setting for a channel is enabled
* Returns: 1 = On, 0 = Off, -1 = Invalid
*/
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 */
@@ -3670,17 +3674,17 @@ short ANIM_channel_setting_get(bAnimContext *ac, bAnimListElem *ale, eAnimChanne
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
@@ -3689,7 +3693,7 @@ short ANIM_channel_setting_get(bAnimContext *ac, bAnimListElem *ale, eAnimChanne
case sizeof(short): /* short pointer for setting */
{
const short *val = (short *)ptr;
-
+
if (negflag)
return ((*val) & flag) == 0;
else
@@ -3698,7 +3702,7 @@ short ANIM_channel_setting_get(bAnimContext *ac, bAnimListElem *ale, eAnimChanne
case sizeof(char): /* char pointer for setting */
{
const char *val = (char *)ptr;
-
+
if (negflag)
return ((*val) & flag) == 0;
else
@@ -3707,10 +3711,10 @@ short ANIM_channel_setting_get(bAnimContext *ac, bAnimListElem *ale, eAnimChanne
}
}
}
-
+
/* not found... */
return -1;
-}
+}
/* quick macro for use in ANIM_channel_setting_set - set flag for setting according the mode given */
@@ -3728,14 +3732,14 @@ short ANIM_channel_setting_get(bAnimContext *ac, bAnimListElem *ale, eAnimChanne
} \
} (void)0
-/* Change value of some setting for a channel
+/* 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 */
@@ -3743,10 +3747,10 @@ void ANIM_channel_setting_set(bAnimContext *ac, bAnimListElem *ale, eAnimChannel
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) {
@@ -3792,7 +3796,7 @@ static bool achannel_is_being_renamed(const bAnimContext *ac, const bAnimChannel
return true;
}
}
-
+
/* not being renamed */
return false;
}
@@ -3805,52 +3809,52 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
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 */
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
-
+ 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;
+ offset += ICON_WIDTH;
}
-
+
/* step 3) draw icon ............................................... */
if (acf->icon) {
UI_icon_draw(offset, ymid, acf->icon(ale));
- offset += ICON_WIDTH;
+ offset += ICON_WIDTH;
}
-
+
/* turn off blending, since not needed anymore... */
- glDisable(GL_BLEND);
-
+ 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...
@@ -3867,12 +3871,12 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_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
+
+ /* 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);
@@ -3889,7 +3893,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
}
else if ((ac->spacetype == SPACE_NLA) && acf->has_setting(ac, ale, ACHANNEL_SETTING_SOLO)) {
/* just skip - drawn as widget now */
- offset += ICON_WIDTH;
+ offset += ICON_WIDTH;
}
else if (ale->type == ANIMTYPE_GPLAYER) {
/* just skip - drawn as a widget */
@@ -3898,7 +3902,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
}
/* step 5) draw name ............................................... */
- /* Don't draw this if renaming... */
+ /* 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! */
@@ -3914,10 +3918,10 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
/* 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)) {
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -3927,7 +3931,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
/* FIXME: replace hardcoded color here, and check on extents! */
immUniformColor3f(1.0f, 0.0f, 0.0f);
- glLineWidth(2.0f);
+ GPU_line_width(2.0f);
immBegin(GWN_PRIM_LINES, 2);
immVertex2f(pos, (float)offset, yminc);
@@ -3951,11 +3955,11 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_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_IPO)) {
switch (ac->spacetype) {
@@ -3979,24 +3983,24 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
/* 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)
@@ -4006,10 +4010,10 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
/* adjust offset */
offset += SLIDER_WIDTH;
}
-
-
+
+
/* finally draw a backdrop rect behind these
- * - starts from the point where the first toggle/slider starts,
+ * - 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);
@@ -4035,7 +4039,7 @@ static void achannel_setting_flush_widget_cb(bContext *C, void *ale_npoin, void
int filter;
int setting = GET_INT_FROM_POINTER(setting_wrap);
short on = 0;
-
+
/* send notifiers before doing anything else... */
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
@@ -4046,11 +4050,20 @@ static void achannel_setting_flush_widget_cb(bContext *C, void *ale_npoin, void
if (ale_setting->type == ANIMTYPE_GPLAYER)
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL);
-
+
+ /* tag copy-on-write flushing (so that the settings will have an effect) */
+ if (ale_setting->id) {
+ DEG_id_tag_update(ale_setting->id, DEG_TAG_COPY_ON_WRITE);
+ }
+ 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, DEG_TAG_COPY_ON_WRITE);
+ }
+
/* 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);
@@ -4058,14 +4071,14 @@ static void achannel_setting_flush_widget_cb(bContext *C, void *ale_npoin, void
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);
-
+
/* 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);
}
@@ -4075,7 +4088,7 @@ static void achannel_nlatrack_solo_widget_cb(bContext *C, void *adt_poin, void *
{
AnimData *adt = adt_poin;
NlaTrack *nlt = nlt_poin;
-
+
/* 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
@@ -4085,7 +4098,7 @@ static void achannel_nlatrack_solo_widget_cb(bContext *C, void *adt_poin, void *
*/
nlt->flag ^= NLATRACK_SOLO;
BKE_nlatrack_solo_toggle(adt, nlt);
-
+
/* send notifiers */
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_RENAME, NULL);
}
@@ -4096,7 +4109,8 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi
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;
@@ -4105,25 +4119,25 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi
short flag = 0;
bool done = false;
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 flags for keyframing */
flag = ANIM_get_keyframing_flags(scene, 1);
-
+
/* get RNA pointer, and resolve the path */
RNA_id_pointer_create(id, &id_ptr);
-
+
/* 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(reports, ptr, prop, fcu, cfra, ts->keyframe_type, flag);
-
+ done = insert_keyframe_direct(depsgraph, reports, ptr, prop, fcu, cfra, ts->keyframe_type, flag);
+
if (done)
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
}
@@ -4132,10 +4146,12 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi
/* 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);
-
+
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
ReportList *reports = CTX_wm_reports(C);
Scene *scene = CTX_data_scene(C);
ToolSettings *ts = scene->toolsettings;
@@ -4144,34 +4160,34 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi
short flag = 0;
bool done = false;
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 flags for keyframing */
flag = ANIM_get_keyframing_flags(scene, 1);
-
+
/* get RNA pointer, and resolve the path */
RNA_id_pointer_create((ID *)key, &id_ptr);
-
+
/* 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((ID *)key, 1);
+ bAction *act = verify_adt_action(bmain, (ID *)key, 1);
FCurve *fcu = verify_fcurve(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;
-
+
/* insert a keyframe for this F-Curve */
- done = insert_keyframe_direct(reports, ptr, prop, fcu, cfra, ts->keyframe_type, flag);
-
+ done = insert_keyframe_direct(depsgraph, reports, ptr, prop, fcu, cfra, ts->keyframe_type, flag);
+
if (done)
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
}
-
+
/* free the path */
if (rna_path)
MEM_freeN(rna_path);
@@ -4182,35 +4198,36 @@ static void achannel_setting_slider_nla_curve_cb(bContext *C, void *UNUSED(id_po
{
/* ID *id = (ID *)id_poin; */
FCurve *fcu = (FCurve *)fcu_poin;
-
+
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;
-
+
/* get current frame - *no* NLA mapping should be done */
cfra = (float)CFRA;
-
+
/* 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);
-
+
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(reports, ptr, prop, fcu, cfra, ts->keyframe_type, flag);
-
+ done = insert_keyframe_direct(depsgraph, reports, ptr, prop, fcu, cfra, ts->keyframe_type, flag);
+
if (done)
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
}
@@ -4227,18 +4244,18 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, const bAni
void *ptr;
const char *tooltip;
uiBut *but = NULL;
-
+
/* 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); */ /* UNUSED */
-
+
/* 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)
@@ -4263,30 +4280,30 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, const bAni
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_MUTE_IPO_ON : ICON_MUTE_IPO_OFF);
icon = ICON_MUTE_IPO_OFF;
-
+
if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
tooltip = TIP_("Does F-Curve contribute to result");
}
@@ -4300,11 +4317,11 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, const bAni
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)");
}
@@ -4313,13 +4330,13 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, const bAni
tooltip = NULL;
}
break;
-
+
default:
tooltip = NULL;
icon = 0;
break;
}
-
+
/* type of button */
if (usetoggle) {
if (negflag)
@@ -4337,21 +4354,21 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, const bAni
if (ptr && flag) {
switch (ptrsize) {
case sizeof(int): /* integer pointer for setting */
- but = uiDefIconButBitI(block, butType, flag, 0, icon,
+ 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,
+ 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,
+ 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) {
@@ -4364,12 +4381,12 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, const bAni
case ACHANNEL_SETTING_ALWAYS_VISIBLE:
UI_but_funcN_set(but, achannel_setting_flush_widget_cb, MEM_dupallocN(ale), SET_INT_IN_POINTER(setting));
break;
-
+
/* settings needing special attention */
case ACHANNEL_SETTING_SOLO: /* NLA Tracks - Solo toggle */
UI_but_func_set(but, achannel_nlatrack_solo_widget_cb, ale->adt, ale->data);
break;
-
+
/* no flushing */
case ACHANNEL_SETTING_EXPAND: /* expanding - cannot flush, otherwise all would open/close at once */
default:
@@ -4388,37 +4405,37 @@ void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListEle
float y, ymid /*, ytext*/;
short offset;
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 */
if (acf->get_offset)
offset = acf->get_offset(ac, ale);
else
offset = 0;
-
- /* calculate appropriate y-coordinates for icon buttons
+
+ /* calculate appropriate y-coordinates for icon buttons
*/
y = (ymaxc - yminc) / 2 + yminc;
ymid = y - 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;
+ offset += ICON_WIDTH;
}
-
+
/* step 2) draw icon ............................................... */
if (acf->icon) {
/* icon is not drawn here (not a widget) */
- offset += ICON_WIDTH;
+ 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...
@@ -4443,7 +4460,7 @@ void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListEle
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;
+ offset += ICON_WIDTH;
}
else if (ale->type == ANIMTYPE_GPLAYER) {
#if 0
@@ -4452,18 +4469,18 @@ void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListEle
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,
+ 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,
+ 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);
@@ -4472,14 +4489,14 @@ void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListEle
#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
+
+ /* 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)) {
@@ -4487,21 +4504,21 @@ void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListEle
const short channel_height = round_fl_to_int(ymaxc - yminc);
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, yminc,
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 {
@@ -4512,15 +4529,15 @@ void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListEle
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 = 0;
-
+
// 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_IPO)) {
switch (ac->spacetype) {
@@ -4538,12 +4555,12 @@ void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListEle
}
}
}
-
+
/* 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;
+ offset += ICON_WIDTH;
draw_setting_widget(ac, ale, acf, block, (int)v2d->cur.xmax - offset, ymid, ACHANNEL_SETTING_PROTECT);
}
/* mute... */
@@ -4556,43 +4573,43 @@ void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListEle
offset += ICON_WIDTH;
draw_setting_widget(ac, ale, acf, block, (int)v2d->cur.xmax - offset, ymid, ACHANNEL_SETTING_VISIBLE);
}
-
+
/* modifiers disable */
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MOD_OFF)) {
offset += ICON_WIDTH * 1.2f; /* hack: extra spacing, to avoid touching the mute toggle */
draw_setting_widget(ac, ale, acf, block, (int)v2d->cur.xmax - 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, (int)v2d->cur.xmax - 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,
+ but = uiDefIconButO(block, UI_BTYPE_BUT, "NLA_OT_action_pushdown", WM_OP_INVOKE_DEFAULT, ICON_NLA_PUSHDOWN,
(int)v2d->cur.xmax - 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,
+ * - 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
@@ -4601,25 +4618,25 @@ void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListEle
/* 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, (int)v2d->cur.xmax - offset, ymid, SLIDER_WIDTH, (int)ymaxc - yminc);
UI_but_func_set(but, achannel_setting_slider_nla_curve_cb, ale->id, ale->data);
@@ -4632,41 +4649,41 @@ void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListEle
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, (int)v2d->cur.xmax - offset, ymid, SLIDER_WIDTH, (int)ymaxc - yminc);
-
+
/* 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);
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 36402b82cbf..57a3d52731d 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -30,7 +30,7 @@
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -82,24 +82,24 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat
{
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;
}
@@ -107,14 +107,14 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat
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;
}
@@ -146,13 +146,13 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat
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) {
@@ -201,26 +201,26 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat
}
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);
}
@@ -252,7 +252,7 @@ static void select_pchan_for_action_group(bAnimContext *ac, bActionGroup *agrp,
}
}
-/* Deselect all animation channels
+/* Deselect all animation channels
* - data: pointer to datatype, as contained in bAnimContext
* - datatype: the type of data that 'data' represents (eAnimCont_Types)
* - test: check if deselecting instead of selecting
@@ -263,18 +263,18 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d
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)
+ if (sel == 0)
break;
-
+
switch (ale->type) {
case ANIMTYPE_SCENE:
if (ale->flag & SCE_DS_SELECTED)
@@ -303,7 +303,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d
if (ale->flag & NLATRACK_SELECTED)
sel = ACHANNEL_SETFLAG_CLEAR;
break;
-
+
case ANIMTYPE_FILLACTD: /* Action Expander */
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
case ANIMTYPE_DSLAM:
@@ -339,16 +339,16 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d
}
}
}
-
+
/* 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);
}
@@ -381,7 +381,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d
case ANIMTYPE_NLACURVE:
{
FCurve *fcu = (FCurve *)ale->data;
-
+
ACHANNEL_SET_FLAG(fcu, sel, FCURVE_SELECTED);
fcu->flag &= ~FCURVE_ACTIVE;
break;
@@ -389,14 +389,14 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d
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;
@@ -431,40 +431,40 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d
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 ------------------------------------- */
-/* Flush visibility (for Graph Editor) changes up/down hierarchy for changes in the given setting
+/* 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
* -> filtered using ANIMFILTER_CHANNELS only, since if we took VISIBLE too,
* then the channels under closed expanders get ignored...
* - ale_setting: the anim channel (not in the anim_data list directly, though occurring there)
- * with the new state of the setting that we want flushed up/down the hierarchy
+ * with the new state of the setting that we want flushed up/down the hierarchy
* - setting: type of setting to set
- * - on: whether the visibility setting has been enabled or disabled
+ * - 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;
@@ -491,23 +491,23 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAn
}
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?
+
+ /* flush up?
*
* For Visibility:
- * - only flush up if the current state is now enabled (positive 'on' state is default)
+ * - 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:
@@ -521,25 +521,25 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAn
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
+
+ /* 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,
+ * 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;
}
@@ -551,31 +551,31 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAn
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
+ * 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
+
+ /* 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,
+
+ /* if the level is 'greater than' (i.e. less important) the channel that was changed,
* flush the new status...
*/
if (level > matchLevel)
@@ -586,7 +586,7 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAn
*/
else
break;
-
+
/* store this level as the 'old' level now */
// prevLevel = level; // XXX: prevLevel is unused
}
@@ -598,13 +598,13 @@ 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
+ /* - 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
@@ -617,15 +617,15 @@ void ANIM_fcurve_delete_from_animdata(bAnimContext *ac, AnimData *adt, FCurve *f
}
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,
+
+ /* if group has no more channels, remove it too,
* otherwise can have many dangling groups [#33541]
*/
if (BLI_listbase_is_empty(&agrp->channels)) {
@@ -635,7 +635,7 @@ void ANIM_fcurve_delete_from_animdata(bAnimContext *ac, AnimData *adt, FCurve *f
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.
*
@@ -648,7 +648,7 @@ void ANIM_fcurve_delete_from_animdata(bAnimContext *ac, AnimData *adt, FCurve *f
adt->action = NULL;
}
}
-
+
/* free the F-Curve itself */
free_fcurve(fcu);
}
@@ -662,7 +662,7 @@ void ANIM_fcurve_delete_from_animdata(bAnimContext *ac, AnimData *adt, FCurve *f
static int animedit_poll_channels_active(bContext *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)))
@@ -687,13 +687,13 @@ static int animedit_poll_channels_nla_tweakmode_off(bContext *C)
/* animation editor test */
if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA) == 0)
return 0;
-
+
/* NLA TweakMode test */
if (sa->spacetype == SPACE_NLA) {
if ((scene == NULL) || (scene->flag & SCE_NLA_EDIT_ON))
return 0;
}
-
+
return 1;
}
@@ -722,7 +722,7 @@ static const EnumPropertyItem prop_animchannel_rearrange_types[] = {
/* Island definition - just a listbase container */
typedef struct tReorderChannelIsland {
struct tReorderChannelIsland *next, *prev;
-
+
ListBase channels; /* channels within this region with the same state */
int flag; /* eReorderIslandFlag */
} tReorderChannelIsland;
@@ -743,7 +743,7 @@ static bool rearrange_island_ok(tReorderChannelIsland *island)
/* 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);
}
@@ -755,13 +755,13 @@ static bool rearrange_island_top(ListBase *list, tReorderChannelIsland *island)
if (rearrange_island_ok(island)) {
/* remove from current position */
BLI_remlink(list, island);
-
+
/* make it first element */
BLI_insertlinkbefore(list, list->first, island);
-
+
return 1;
}
-
+
return 0;
}
@@ -779,14 +779,14 @@ static bool rearrange_island_up(ListBase *list, tReorderChannelIsland *island)
if (prev) {
/* remove from current position */
BLI_remlink(list, island);
-
+
/* push it up */
BLI_insertlinkbefore(list, prev, island);
-
+
return 1;
}
}
-
+
return 0;
}
@@ -806,16 +806,16 @@ static bool rearrange_island_down(ListBase *list, tReorderChannelIsland *island)
if ((next->flag & REORDER_ISLAND_UNTOUCHABLE) == 0) {
/* remove from current position */
BLI_remlink(list, 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 false;
}
@@ -823,10 +823,10 @@ static bool rearrange_island_bottom(ListBase *list, tReorderChannelIsland *islan
{
if (rearrange_island_ok(island)) {
tReorderChannelIsland *last = list->last;
-
+
/* 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 */
@@ -835,12 +835,12 @@ static bool rearrange_island_bottom(ListBase *list, tReorderChannelIsland *islan
else {
/* can at most go just before it, since last cannot be moved */
BLI_insertlinkbefore(list, last, island);
-
+
}
-
+
return true;
}
-
+
return false;
}
@@ -881,13 +881,13 @@ static void rearrange_animchannel_add_to_islands(ListBase *islands, ListBase *sr
{
tReorderChannelIsland *island = islands->last; /* always try to add to last island if possible */
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;
@@ -896,21 +896,21 @@ static void rearrange_animchannel_add_to_islands(ListBase *islands, ListBase *sr
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;
}
@@ -918,7 +918,7 @@ static void rearrange_animchannel_add_to_islands(ListBase *islands, ListBase *sr
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) ||
@@ -933,7 +933,7 @@ static void rearrange_animchannel_add_to_islands(ListBase *islands, ListBase *sr
/* 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)
@@ -951,14 +951,14 @@ static void rearrange_animchannel_add_to_islands(ListBase *islands, ListBase *sr
static void rearrange_animchannel_flatten_islands(ListBase *islands, ListBase *srcList)
{
tReorderChannelIsland *island, *isn = NULL;
-
+
/* 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;
-
+
/* merge island channels back to main list, then delete the island */
BLI_movelisttolist(srcList, &island->channels);
BLI_freelinkN(islands, island);
@@ -973,19 +973,19 @@ static void rearrange_animchannels_filter_visible(ListBase *anim_data_visible, b
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);
-
+
/* 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);
}
}
-
+
/* return cleaned up list */
*anim_data_visible = anim_data;
}
@@ -998,11 +998,11 @@ static bool rearrange_animchannel_islands(ListBase *list, AnimChanRearrangeFp re
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! */
@@ -1010,18 +1010,18 @@ static bool rearrange_animchannel_islands(ListBase *list, AnimChanRearrangeFp re
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
+
+ /* 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;
@@ -1029,10 +1029,10 @@ static bool rearrange_animchannel_islands(ListBase *list, AnimChanRearrangeFp re
}
}
}
-
+
/* ungroup islands */
rearrange_animchannel_flatten_islands(&islands, list);
-
+
/* did we do anything? */
return done;
}
@@ -1041,27 +1041,27 @@ static bool rearrange_animchannel_islands(ListBase *list, AnimChanRearrangeFp re
/* Change the order NLA Tracks within NLA Stack
* ! NLA tracks are displayed in opposite order, so directions need care
- * mode: REARRANGE_ANIMCHAN_*
+ * mode: REARRANGE_ANIMCHAN_*
*/
static void rearrange_nla_channels(bAnimContext *ac, AnimData *adt, eRearrangeAnimChan_Mode mode)
{
AnimChanRearrangeFp rearrange_func;
ListBase anim_data_visible = {NULL, NULL};
-
+
/* 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;
-
+
/* 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);
-
+
/* free temp data */
BLI_freelistN(&anim_data_visible);
}
@@ -1069,27 +1069,27 @@ static void rearrange_nla_channels(bAnimContext *ac, AnimData *adt, eRearrangeAn
/* Drivers Specific Stuff ------------------------------------------------- */
/* Change the order drivers within AnimData block
- * mode: REARRANGE_ANIMCHAN_*
+ * mode: REARRANGE_ANIMCHAN_*
*/
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};
-
+
if (rearrange_func == NULL)
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);
-
+
/* 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);
}
@@ -1101,29 +1101,29 @@ 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 */
@@ -1131,21 +1131,21 @@ static void split_groups_action_temp(bAction *act, bActionGroup *tgrp)
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
+
+ /* 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);
}
@@ -1154,72 +1154,72 @@ static void split_groups_action_temp(bAction *act, bActionGroup *tgrp)
static void join_groups_action_temp(bAction *act)
{
bActionGroup *agrp;
-
+
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;
-
+
/* 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;
-
+
for (fcu = agrp->channels.first; fcu; fcu = fcu->next) {
fcu->grp = NULL;
}
-
+
BLI_remlink(&act->groups, agrp);
break;
}
}
}
-/* Change the order of anim-channels within action
- * mode: REARRANGE_ANIMCHAN_*
+/* Change the order of anim-channels within action
+ * mode: REARRANGE_ANIMCHAN_*
*/
static void rearrange_action_channels(bAnimContext *ac, bAction *act, eRearrangeAnimChan_Mode mode)
{
bActionGroup tgrp;
ListBase anim_data_visible = {NULL, NULL};
bool do_channels;
-
+
/* get rearranging function */
AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode);
-
+
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);
-
+
/* Filter visible data. */
rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_GROUP);
-
- /* rearrange groups first
+
+ /* 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);
-
+
if (do_channels) {
bActionGroup *agrp;
-
+
/* 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)) {
@@ -1227,11 +1227,11 @@ static void rearrange_action_channels(bAnimContext *ac, bAction *act, eRearrange
&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);
}
@@ -1241,23 +1241,23 @@ static void rearrange_action_channels(bAnimContext *ac, bAction *act, eRearrange
static void rearrange_nla_control_channels(bAnimContext *ac, AnimData *adt, eRearrangeAnimChan_Mode mode)
{
ListBase anim_data_visible = {NULL, NULL};
-
+
NlaTrack *nlt;
NlaStrip *strip;
-
+
/* get rearranging function */
AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode);
-
+
if (rearrange_func == NULL)
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);
-
+
/* 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) {
@@ -1265,7 +1265,7 @@ static void rearrange_nla_control_channels(bAnimContext *ac, AnimData *adt, eRea
&anim_data_visible);
}
}
-
+
/* free temp data */
BLI_freelistN(&anim_data_visible);
}
@@ -1277,36 +1277,36 @@ static void rearrange_gpencil_channels(bAnimContext *ac, eRearrangeAnimChan_Mode
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
-
+
/* get rearranging function */
AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode);
-
+
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);
-
+
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;
-
+
/* 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);
-
+
/* free visible layers data */
BLI_freelistN(&anim_data_visible);
}
-
+
/* free GPD channel data */
ANIM_animdata_freelist(&anim_data);
}
@@ -1317,14 +1317,14 @@ 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 */
@@ -1342,23 +1342,23 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
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);
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...
{
@@ -1368,13 +1368,13 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
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);
@@ -1384,14 +1384,14 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
}
}
}
-
+
/* 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;
}
@@ -1401,14 +1401,14 @@ static void ANIM_OT_channels_move(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* props */
ot->prop = RNA_def_enum(ot->srna, "direction", prop_animchannel_rearrange_types, REARRANGE_ANIMCHAN_DOWN, "Direction", "");
}
@@ -1424,16 +1424,16 @@ static int animchannels_grouping_poll(bContext *C)
/* 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);
-
+
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;
@@ -1443,7 +1443,7 @@ static int animchannels_grouping_poll(bContext *C)
case SPACE_IPO:
{
SpaceIpo *sipo = (SpaceIpo *)sl;
-
+
/* drivers can't have groups... */
if (sipo->mode != SIPO_MODE_ANIMATION)
return 0;
@@ -1454,50 +1454,50 @@ static int animchannels_grouping_poll(bContext *C)
default:
return 0;
}
-
+
return 1;
}
/* ----------------------------------------------------------- */
static void animchannels_group_channels(bAnimContext *ac, bAnimListElem *adt_ref, const char name[])
-{
+{
AnimData *adt = adt_ref->adt;
bAction *act = adt->action;
-
+
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);
-
+
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);
-
+
/* 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);
-
+
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);
}
}
-
+
/* cleanup */
ANIM_animdata_freelist(&anim_data);
}
@@ -1507,35 +1507,35 @@ static int animchannels_group_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
char name[MAX_NAME];
-
+
/* 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);
-
+
/* 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);
-
+
for (ale = anim_data.first; ale; ale = ale->next) {
animchannels_group_channels(&ac, ale, name);
}
-
+
/* free temp data */
ANIM_animdata_freelist(&anim_data);
-
+
/* updatss */
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
}
-
+
return OPERATOR_FINISHED;
}
@@ -1545,18 +1545,18 @@ static void ANIM_OT_channels_group(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* props */
- ot->prop = RNA_def_string(ot->srna, "name", "New Group",
- sizeof(((bActionGroup *)NULL)->name),
+ ot->prop = RNA_def_string(ot->srna, "name", "New Group",
+ sizeof(((bActionGroup *)NULL)->name),
"Name", "Name of newly created group");
/* RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); */ /* XXX: still not too sure about this - keeping same text is confusing... */
}
@@ -1566,33 +1566,33 @@ static void ANIM_OT_channels_group(wmOperatorType *ot)
static int animchannels_ungroup_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;
-
+
/* 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;
-
+
/* only proceed to remove if F-Curve is in a group... */
- if (fcu->grp) {
+ 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);
-
+
/* delete group if it is now empty */
if (BLI_listbase_is_empty(&agrp->channels)) {
BLI_freelinkN(&act->groups, agrp);
@@ -1600,13 +1600,13 @@ static int animchannels_ungroup_exec(bContext *C, wmOperator *UNUSED(op))
}
}
}
-
+
/* cleanup */
ANIM_animdata_freelist(&anim_data);
-
+
/* updates */
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -1616,11 +1616,11 @@ static void ANIM_OT_channels_ungroup(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1633,22 +1633,22 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
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)
+ 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 */
@@ -1656,20 +1656,20 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
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);
@@ -1677,24 +1677,24 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
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:
+ 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);
break;
@@ -1704,7 +1704,7 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
/* 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;
}
@@ -1714,7 +1714,7 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
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);
@@ -1725,7 +1725,7 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
/* 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_free_frames(gpl);
BLI_freelinkN(&gpd->layers, gpl);
@@ -1736,35 +1736,35 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
/* 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";
-
+
/* api callbacks */
ot->exec = animchannels_delete_exec;
ot->poll = animedit_poll_channels_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1791,7 +1791,7 @@ static const EnumPropertyItem prop_animchannel_settings_types[] = {
/* ------------------- */
-/* Set/clear a particular flag (setting) for all selected + visible channels
+/* Set/clear a particular flag (setting) for all selected + visible channels
* setting: the setting to modify
* mode: eAnimChannels_SetFlag
* onlysel: only selected channels get the flag set
@@ -1803,20 +1803,20 @@ static void setflag_anim_channels(bAnimContext *ac, eAnimChannel_Settings settin
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
+ /* 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
+
+ /* 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",
+ * 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]
@@ -1831,12 +1831,12 @@ static void setflag_anim_channels(bAnimContext *ac, eAnimChannel_Settings settin
}
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) */
@@ -1846,21 +1846,21 @@ static void setflag_anim_channels(bAnimContext *ac, eAnimChannel_Settings settin
}
}
}
-
+
/* 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);
}
@@ -1873,27 +1873,27 @@ static int animchannels_setflag_exec(bContext *C, wmOperator *op)
eAnimChannel_Settings setting;
eAnimChannels_SetFlag mode;
bool flush = true;
-
+
/* 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");
-
+
/* check if setting is flushable */
if (setting == ACHANNEL_SETTING_EXPAND)
flush = false;
-
- /* modify setting
+
+ /* 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);
-
+
return OPERATOR_FINISHED;
}
@@ -1901,20 +1901,20 @@ static int animchannels_setflag_exec(bContext *C, wmOperator *op)
static void ANIM_OT_channels_setting_enable(wmOperatorType *ot)
{
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";
-
+
/* 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;
-
+
/* props */
/* flag-setting mode */
prop = RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_ADD, "Mode", "");
@@ -1926,20 +1926,20 @@ static void ANIM_OT_channels_setting_enable(wmOperatorType *ot)
static void ANIM_OT_channels_setting_disable(wmOperatorType *ot)
{
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";
-
+
/* 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;
-
+
/* props */
/* flag-setting mode */
prop = RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_CLEAR, "Mode", "");
@@ -1951,20 +1951,20 @@ static void ANIM_OT_channels_setting_disable(wmOperatorType *ot)
static void ANIM_OT_channels_setting_toggle(wmOperatorType *ot)
{
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";
-
+
/* 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;
-
+
/* props */
/* flag-setting mode */
prop = RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_TOGGLE, "Mode", "");
@@ -1976,19 +1976,19 @@ static void ANIM_OT_channels_setting_toggle(wmOperatorType *ot)
static void ANIM_OT_channels_editable_toggle(wmOperatorType *ot)
{
PropertyRNA *prop;
-
+
/* 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;
-
+
/* 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", "");
@@ -2003,21 +2003,21 @@ static int animchannels_expand_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
bool onlysel = true;
-
+
/* 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;
-
+
/* 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);
-
+
return OPERATOR_FINISHED;
}
@@ -2027,14 +2027,14 @@ static void ANIM_OT_channels_expand(wmOperatorType *ot)
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;
-
+
/* 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)");
}
@@ -2045,21 +2045,21 @@ static int animchannels_collapse_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
bool onlysel = true;
-
+
/* 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;
-
+
/* 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);
-
+
return OPERATOR_FINISHED;
}
@@ -2069,14 +2069,14 @@ static void ANIM_OT_channels_collapse(wmOperatorType *ot)
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;
-
+
/* 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)");
}
@@ -2092,37 +2092,37 @@ static void ANIM_OT_channels_collapse(wmOperatorType *ot)
* or are no longer wanted
* 3) No drivers
*/
-
+
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;
@@ -2130,18 +2130,18 @@ static int animchannels_clean_empty_exec(bContext *C, wmOperator *UNUSED(op))
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
+ /* 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;
@@ -2153,23 +2153,23 @@ static int animchannels_clean_empty_exec(bContext *C, wmOperator *UNUSED(op))
}
}
}
-
+
/* 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;
}
@@ -2179,11 +2179,11 @@ static void ANIM_OT_channels_clean_empty(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -2193,56 +2193,56 @@ static void ANIM_OT_channels_clean_empty(wmOperatorType *ot)
static int animchannels_enable_poll(bContext *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 - Action/Dopesheet/etc. and Graph only */
if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_IPO) == 0)
return 0;
-
+
return 1;
}
static int animchannels_enable_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;
-
+
/* 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;
-
+
/* 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;
-
+
/* 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);
-
+
/* send notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -2252,11 +2252,11 @@ static void ANIM_OT_channels_fcurves_enable(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -2267,10 +2267,10 @@ static void ANIM_OT_channels_fcurves_enable(wmOperatorType *ot)
static int animchannels_find_poll(bContext *C)
{
ScrArea *sa = CTX_wm_area(C);
-
+
if (sa == NULL)
return 0;
-
+
/* animation editor with dopesheet */
return ELEM(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA);
}
@@ -2279,14 +2279,14 @@ static int animchannels_find_poll(bContext *C)
static int animchannels_find_invoke(bContext *C, wmOperator *op, const wmEvent *evt)
{
bAnimContext ac;
-
+
/* 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);
-
+
/* defer to popup */
return WM_operator_props_popup(C, op, evt);
}
@@ -2295,26 +2295,17 @@ static int animchannels_find_invoke(bContext *C, wmOperator *op, const wmEvent *
static int animchannels_find_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
-
+
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
- /* update filter text, and ensure that filter is enabled if there's something there
- * NOTE: we turn the filter off if there's nothing (this is a quick shortcut for dismissing)
- */
+
+ /* update filter text */
RNA_string_get(op->ptr, "query", ac.ads->searchstr);
-
- if (ac.ads->searchstr[0]) {
- ac.ads->filterflag |= ADS_FILTER_BY_FCU_NAME;
- }
- else {
- ac.ads->filterflag &= ~ADS_FILTER_BY_FCU_NAME;
- }
-
+
/* redraw */
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -2324,15 +2315,15 @@ static void ANIM_OT_channels_find(wmOperatorType *ot)
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;
-
+
/* 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");
}
@@ -2342,37 +2333,37 @@ static void ANIM_OT_channels_find(wmOperatorType *ot)
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 */
if (RNA_boolean_get(op->ptr, "invert"))
ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, false, ACHANNEL_SETFLAG_INVERT);
else
ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, true, ACHANNEL_SETFLAG_ADD);
-
+
/* 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_toggle(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Select All";
ot->idname = "ANIM_OT_channels_select_all_toggle";
ot->description = "Toggle selection of all animation channels";
-
+
/* api callbacks */
ot->exec = animchannels_deselectall_exec;
ot->poll = animedit_poll_channels_nla_tweakmode_off;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* props */
ot->prop = RNA_def_boolean(ot->srna, "invert", false, "Invert", "");
}
@@ -2384,12 +2375,12 @@ static void borderselect_anim_channels(bAnimContext *ac, rcti *rect, short selec
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));
@@ -2399,27 +2390,27 @@ static void borderselect_anim_channels(bAnimContext *ac, rcti *rect, short selec
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 border 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:
@@ -2433,20 +2424,20 @@ static void borderselect_anim_channels(bAnimContext *ac, rcti *rect, short selec
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
+
+ /* 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);
}
@@ -2460,11 +2451,11 @@ static int animchannels_borderselect_exec(bContext *C, wmOperator *op)
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 settings from operator */
WM_operator_properties_border_to_rcti(op, &rect);
@@ -2478,15 +2469,15 @@ static int animchannels_borderselect_exec(bContext *C, wmOperator *op)
else {
selectmode = ACHANNEL_SETFLAG_CLEAR;
}
-
+
/* apply borderselect animation channels */
borderselect_anim_channels(&ac, &rect, selectmode);
-
+
/* 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_border(wmOperatorType *ot)
{
@@ -2494,18 +2485,18 @@ static void ANIM_OT_channels_select_border(wmOperatorType *ot)
ot->name = "Border Select";
ot->idname = "ANIM_OT_channels_select_border";
ot->description = "Select all animation channels within the specified region";
-
+
/* api callbacks */
ot->invoke = WM_gesture_border_invoke;
ot->exec = animchannels_borderselect_exec;
ot->modal = WM_gesture_border_modal;
ot->cancel = WM_gesture_border_cancel;
-
+
ot->poll = animedit_poll_channels_nla_tweakmode_off;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* rna */
WM_operator_properties_gesture_border_select(ot);
}
@@ -2520,33 +2511,33 @@ static bool rename_anim_channels(bAnimContext *ac, int channel_index)
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
+ * so here we just store the index of this channel in the
* dopesheet data, which will get utilized when drawing the
* channel...
*
@@ -2558,7 +2549,7 @@ static bool rename_anim_channels(bAnimContext *ac, int channel_index)
}
}
}
-
+
/* free temp data and tag for refresh */
ANIM_animdata_freelist(&anim_data);
ED_region_tag_redraw(ac->ar);
@@ -2571,18 +2562,18 @@ static int animchannels_channel_get(bAnimContext *ac, const int mval[2])
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
+
+ /* 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);
@@ -2619,7 +2610,7 @@ static void ANIM_OT_channels_rename(wmOperatorType *ot)
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;
@@ -2634,19 +2625,19 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
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;
}
@@ -2666,7 +2657,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
{
Scene *sce = (Scene *)ale->data;
AnimData *adt = sce->adt;
-
+
/* set selection status */
if (selectmode == SELECT_INVERT) {
/* swap select */
@@ -2677,7 +2668,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
sce->flag |= SCE_DS_SELECTED;
if (adt) adt->flag |= ADT_UI_SELECTED;
}
-
+
notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
break;
}
@@ -2691,9 +2682,9 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
Base *base = (Base *)ale->data;
Object *ob = base->object;
AnimData *adt = ob->adt;
-
+
/* set selection status */
- if (base->flag & BASE_SELECTABLED) {
+ if (base->flag & BASE_SELECTABLE) {
if (selectmode == SELECT_INVERT) {
/* swap select */
ED_object_base_select(base, BA_INVERT);
@@ -2725,8 +2716,9 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
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 | EM_WAITCURSOR | EM_DO_UNDO);
+ if (ob != CTX_data_edit_object(C)) {
+ ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR);
+ }
notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
}
@@ -2764,28 +2756,28 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
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:
+ 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.
+ * selection.
*
* Only do this if "Only Selected" dopesheet filter is not active, or else it
* becomes too unpredictable/tricky to manage
@@ -2793,7 +2785,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
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
@@ -2802,10 +2794,10 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
* 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 */
@@ -2814,11 +2806,11 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
else if (selectmode == -1) {
/* select all in group (and deselect everthing 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;
@@ -2828,10 +2820,10 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
/* 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);
@@ -2841,7 +2833,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
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;
}
@@ -2849,7 +2841,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
case ANIMTYPE_NLACURVE:
{
FCurve *fcu = (FCurve *)ale->data;
-
+
/* select/deselect */
if (selectmode == SELECT_INVERT) {
/* inverse selection status of this F-Curve only */
@@ -2860,18 +2852,18 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
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:
+ case ANIMTYPE_SHAPEKEY:
{
KeyBlock *kb = (KeyBlock *)ale->data;
-
+
/* select/deselect */
if (selectmode == SELECT_INVERT) {
/* inverse selection status of this ShapeKey only */
@@ -2882,39 +2874,39 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
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
+
+ /* 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:
{
bGPDlayer *gpl = (bGPDlayer *)ale->data;
-
+
/* select/deselect */
if (selectmode == SELECT_INVERT) {
/* invert selection status of this layer only */
@@ -2925,12 +2917,12 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
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);
}
-
+
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); /* Grease Pencil updates */
notifierFlags |= (ND_ANIMCHAN | NA_EDITED); /* Animation Ediotrs updates */
break;
@@ -2938,19 +2930,19 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
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 */
@@ -2961,7 +2953,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
masklay->flag |= MASK_LAYERFLAG_SELECT;
}
-
+
notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
break;
}
@@ -2970,10 +2962,10 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
printf("Error: Invalid channel type in mouse_anim_channels()\n");
break;
}
-
+
/* free channels */
ANIM_animdata_freelist(&anim_data);
-
+
/* return notifier flags */
return notifierFlags;
}
@@ -2990,16 +2982,16 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmE
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;
@@ -3007,45 +2999,45 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmE
selectmode = -1; /* this is a bit of a special case for ActionGroups only... should it be removed or extended to all instead? */
else
selectmode = SELECT_REPLACE;
-
- /* figure out which channel user clicked in
+
+ /* 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;
-
+
/* 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;
-
+
/* flags */
ot->flag = OPTYPE_UNDO;
-
+
/* properties */
/* NOTE: don't save settings, otherwise, can end up with some weird behaviour (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);
}
@@ -3156,13 +3148,13 @@ void ED_operatortypes_animchannels(void)
{
WM_operatortype_append(ANIM_OT_channels_select_all_toggle);
WM_operatortype_append(ANIM_OT_channels_select_border);
-
+
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_setting_enable);
WM_operatortype_append(ANIM_OT_channels_setting_disable);
WM_operatortype_append(ANIM_OT_channels_setting_toggle);
@@ -3171,16 +3163,16 @@ void ED_operatortypes_animchannels(void)
/* 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_expand);
WM_operatortype_append(ANIM_OT_channels_collapse);
-
+
WM_operatortype_append(ANIM_OT_channels_fcurves_enable);
-
+
WM_operatortype_append(ANIM_OT_channels_clean_empty);
-
+
WM_operatortype_append(ANIM_OT_channels_group);
WM_operatortype_append(ANIM_OT_channels_ungroup);
}
@@ -3190,7 +3182,7 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_find(keyconf, "Animation Channels", 0, 0);
wmKeyMapItem *kmi;
-
+
/* click-select */
/* XXX for now, only leftmouse.... */
WM_keymap_add_item(keymap, "ANIM_OT_channels_click", LEFTMOUSE, KM_PRESS, 0, 0);
@@ -3205,31 +3197,33 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf)
/* find (i.e. a shortcut for setting the name filter) */
WM_keymap_add_item(keymap, "ANIM_OT_channels_find", FKEY, KM_PRESS, KM_CTRL, 0);
-
+
/* deselect all */
WM_keymap_add_item(keymap, "ANIM_OT_channels_select_all_toggle", AKEY, KM_PRESS, 0, 0);
RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", true);
-
+
/* borderselect */
WM_keymap_add_item(keymap, "ANIM_OT_channels_select_border", BKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "ANIM_OT_channels_select_border", EVT_TWEAK_L, KM_ANY, 0, 0);
-
+
/* delete */
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "ANIM_OT_channels_delete", XKEY, KM_PRESS, 0, 0);
+#endif
WM_keymap_add_item(keymap, "ANIM_OT_channels_delete", DELKEY, KM_PRESS, 0, 0);
-
+
/* settings */
WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_toggle", WKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_enable", WKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_disable", WKEY, KM_PRESS, KM_ALT, 0);
-
+
/* settings - specialized hotkeys */
WM_keymap_add_item(keymap, "ANIM_OT_channels_editable_toggle", TABKEY, KM_PRESS, 0, 0);
-
+
/* expand/collapse */
WM_keymap_add_item(keymap, "ANIM_OT_channels_expand", PADPLUSKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "ANIM_OT_channels_collapse", PADMINUS, KM_PRESS, 0, 0);
-
+
kmi = WM_keymap_add_item(keymap, "ANIM_OT_channels_expand", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "all", false);
kmi = WM_keymap_add_item(keymap, "ANIM_OT_channels_collapse", PADMINUS, KM_PRESS, KM_CTRL, 0);
@@ -3240,7 +3234,7 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_move", PAGEDOWNKEY, KM_PRESS, 0, 0)->ptr, "direction", REARRANGE_ANIMCHAN_DOWN);
RNA_enum_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_move", PAGEUPKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "direction", REARRANGE_ANIMCHAN_TOP);
RNA_enum_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_move", PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "direction", REARRANGE_ANIMCHAN_BOTTOM);
-
+
/* grouping */
WM_keymap_add_item(keymap, "ANIM_OT_channels_group", GKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "ANIM_OT_channels_ungroup", GKEY, KM_PRESS, KM_ALT, 0);
diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c
index abdc6450abd..adb5a10c19d 100644
--- a/source/blender/editors/animation/anim_deps.c
+++ b/source/blender/editors/animation/anim_deps.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation, Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
@@ -46,10 +46,10 @@
#include "BKE_animsys.h"
#include "BKE_action.h"
+#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_gpencil.h"
-#include "BKE_context.h"
-#include "BKE_global.h"
+#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_sequencer.h"
@@ -62,9 +62,9 @@
/* **************************** depsgraph tagging ******************************** */
/* tags the given anim list element for refreshes (if applicable)
- * due to Animation Editor editing
+ * due to Animation Editor editing
*/
-void ANIM_list_elem_update(Scene *scene, bAnimListElem *ale)
+void ANIM_list_elem_update(Main *bmain, Scene *scene, bAnimListElem *ale)
{
ID *id;
FCurve *fcu;
@@ -73,28 +73,31 @@ void ANIM_list_elem_update(Scene *scene, bAnimListElem *ale)
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) {
adt->recalc |= ADT_RECALC_ANIM;
DEG_id_tag_update(id, OB_RECALC_TIME);
+ if (adt->action != NULL) {
+ DEG_id_tag_update(&adt->action->id, DEG_TAG_COPY_ON_WRITE);
+ }
}
/* 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(G.main, scene, &ptr, prop);
+ RNA_property_update_main(bmain, scene, &ptr, prop);
}
else {
/* in other case we do standard depsgraph update, ideally
@@ -103,17 +106,17 @@ void ANIM_list_elem_update(Scene *scene, bAnimListElem *ale)
}
}
-/* tags the given ID block for refreshes (if applicable) due to
+/* tags the given ID block for refreshes (if applicable) due to
* Animation Editor editing */
void ANIM_id_update(Scene *UNUSED(scene), ID *id)
{
if (id) {
AnimData *adt = BKE_animdata_from_id(id);
-
+
/* tag AnimData for refresh so that other views will update in realtime with these changes */
if (adt)
adt->recalc |= ADT_RECALC_ANIM;
-
+
/* set recalc flags */
DEG_id_tag_update(id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); // XXX or do we want something more restrictive?
}
@@ -122,10 +125,10 @@ void ANIM_id_update(Scene *UNUSED(scene), ID *id)
/* **************************** animation data <-> data syncing ******************************** */
/* This code here is used to synchronize the
* - selection (to find selected data easier)
- * - ... (insert other relevant items here later)
+ * - ... (insert other relevant items here later)
* status in relevant Blender data with the status stored in animation channels.
*
- * This should be called in the refresh() callbacks for various editors in
+ * This should be called in the refresh() callbacks for various editors in
* response to appropriate notifiers.
*/
@@ -134,33 +137,33 @@ static void animchan_sync_group(bAnimContext *ac, bAnimListElem *ale, bActionGro
{
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
+
+ /* 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 */
@@ -177,7 +180,7 @@ static void animchan_sync_group(bAnimContext *ac, bAnimListElem *ale, bActionGro
/* 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) {
@@ -188,33 +191,33 @@ static void animchan_sync_group(bAnimContext *ac, bAnimListElem *ale, bActionGro
}
}
}
-
+
/* perform syncing updates for F-Curves */
static void animchan_sync_fcurve(bAnimContext *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
+
+ /* 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_OB) {
Object *ob = (Object *)owner_id;
-
+
/* only affect if F-Curve involves pose.bones */
if ((fcu->rna_path) && strstr(fcu->rna_path, "pose.bones")) {
bArmature *arm = (bArmature *)ob->data;
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);
-
+
/* F-Curve selection depends on whether the bone is selected */
if ((pchan) && (pchan->bone)) {
/* F-Curve selection */
@@ -222,8 +225,8 @@ static void animchan_sync_fcurve(bAnimContext *ac, bAnimListElem *ale, FCurve **
fcu->flag |= FCURVE_SELECTED;
else
fcu->flag &= ~FCURVE_SELECTED;
-
- /* Active F-Curve - it should be the first one for this bone on the
+
+ /* Active F-Curve - it should be the first one for this bone on the
* active object to be considered as active
*/
if ((ob == ac->obact) && (pchan->bone == arm->act_bone)) {
@@ -246,18 +249,18 @@ static void animchan_sync_fcurve(bAnimContext *ac, bAnimListElem *ale, FCurve **
}
else 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)
@@ -269,17 +272,17 @@ static void animchan_sync_fcurve(bAnimContext *ac, bAnimListElem *ale, FCurve **
}
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 */
@@ -287,7 +290,7 @@ static void animchan_sync_fcurve(bAnimContext *ac, bAnimListElem *ale, FCurve **
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
@@ -314,7 +317,7 @@ static void animchan_sync_fcurve(bAnimContext *ac, bAnimListElem *ale, FCurve **
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
@@ -333,7 +336,7 @@ 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)
{
@@ -341,38 +344,38 @@ void ANIM_sync_animchannels_to_data(const bContext *C)
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
+ /* 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);
}
@@ -393,43 +396,43 @@ void ANIM_animdata_update(bAnimContext *ac, ListBase *anim_data)
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->scene, ale);
+ ANIM_list_elem_update(ac->bmain, ac->scene, ale);
}
}
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->scene, ale);
+ ANIM_list_elem_update(ac->bmain, ac->scene, ale);
}
}
else if (ale->datatype == ALE_NLASTRIP) {
if (ale->update & ANIM_UPDATE_DEPS) {
ale->update &= ~ANIM_UPDATE_DEPS;
- ANIM_list_elem_update(ac->scene, ale);
+ ANIM_list_elem_update(ac->bmain, ac->scene, ale);
}
}
diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c
index 475623b1048..953898a0586 100644
--- a/source/blender/editors/animation/anim_draw.c
+++ b/source/blender/editors/animation/anim_draw.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
@@ -64,6 +64,7 @@
#include "GPU_immediate.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
/* *************************************************** */
/* CURRENT FRAME DRAWING */
@@ -75,7 +76,7 @@ void ANIM_draw_cfra_number(const bContext *C, View2D *v2d, short flag)
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];
@@ -83,13 +84,13 @@ void ANIM_draw_cfra_number(const bContext *C, View2D *v2d, short flag)
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);
gpuPushMatrix();
gpuScale2f(1.0f / xscale, 1.0f);
-
- /* get timecode string
+
+ /* get timecode string
* - padding on str-buf passed so that it doesn't sit on the frame indicator
*/
if (show_time) {
@@ -101,7 +102,7 @@ void ANIM_draw_cfra_number(const bContext *C, View2D *v2d, short flag)
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;
@@ -138,7 +139,7 @@ void ANIM_draw_cfra(const bContext *C, View2D *v2d, short flag)
const float time = scene->r.cfra + scene->r.subframe;
const float x = (float)(time * scene->r.framelen);
- glLineWidth((flag & DRAWCFRA_WIDE) ? 3.0 : 2.0);
+ GPU_line_width((flag & DRAWCFRA_WIDE) ? 3.0 : 2.0);
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -163,11 +164,11 @@ void ANIM_draw_cfra(const bContext *C, View2D *v2d, short flag)
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) {
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -187,7 +188,7 @@ void ANIM_draw_previewrange(const bContext *C, View2D *v2d, int end_frame_width)
immUnbindProgram();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
}
@@ -199,8 +200,8 @@ void ANIM_draw_previewrange(const bContext *C, View2D *v2d, int end_frame_width)
void ANIM_draw_framerange(Scene *scene, View2D *v2d)
{
/* draw darkened area outside of active timeline frame range */
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -216,7 +217,7 @@ void ANIM_draw_framerange(Scene *scene, View2D *v2d)
immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
}
- glDisable(GL_BLEND);
+ GPU_blend(false);
/* thin lines where the actual frames are */
immUniformThemeColorShade(TH_BACK, -60);
@@ -243,10 +244,10 @@ 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,
@@ -259,7 +260,7 @@ AnimData *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale)
return ale->adt;
}
}
-
+
/* cannot handle... */
return NULL;
}
@@ -272,15 +273,15 @@ 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;
-
+
/* 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);
-
+
return 0;
}
@@ -290,41 +291,41 @@ 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;
-
+
/* 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);
-
+
return 0;
}
-/* Apply/Unapply NLA mapping to all keyframes in the nominated F-Curve
- * - restore = whether to map points back to non-mapped time
+/* 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
+
+ /* 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);
}
@@ -503,7 +504,7 @@ float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short flag
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)) {
@@ -517,7 +518,7 @@ float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short flag
return RAD2DEGF(1.0f); /* radians to degrees */
}
}
-
+
/* TODO: other rotation types here as necessary */
}
}
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index b7eaa1a4a5f..c59d24bbdf8 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation, Joshua Leung
* All rights reserved.
*
- *
+ *
* Contributor(s): Joshua Leung (original author)
*
* ***** END GPL LICENSE BLOCK *****
@@ -30,10 +30,10 @@
/* 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
- * they require without all the boiler-plate associated with loops within loops and checking
- * for cases to ignore.
+ * 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
+ * they require without all the boiler-plate associated with loops within loops and checking
+ * for cases to ignore.
*
* While this is primarily used for the Action/Dopesheet Editor (and its accessory modes),
* the Graph Editor also uses this for its channel list and for determining which curves
@@ -42,7 +42,7 @@
*
* Note: much of the original system this was based on was built before the creation of the RNA
* system. In future, it would be interesting to replace some parts of this code with RNA queries,
- * however, RNA does not eliminate some of the boiler-plate reduction benefits presented by this
+ * however, RNA does not eliminate some of the boiler-plate reduction benefits presented by this
* system, so if any such work does occur, it should only be used for the internals used here...
*
* -- Joshua Leung, Dec 2008 (Last revision July 2009)
@@ -84,12 +84,12 @@
#include "BLI_ghash.h"
#include "BLI_string.h"
-#include "BKE_animsys.h"
#include "BKE_action.h"
-#include "BKE_fcurve.h"
+#include "BKE_animsys.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
+#include "BKE_fcurve.h"
#include "BKE_global.h"
-#include "BKE_group.h"
#include "BKE_key.h"
#include "BKE_layer.h"
#include "BKE_main.h"
@@ -113,13 +113,13 @@
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->tact.keyframe_scale_fac;
-
+
/* clamp to avoid problems with uninitialised values... */
if (ac->yscale_fac < 0.1f)
ac->yscale_fac = 1.0f;
@@ -135,22 +135,22 @@ static Key *actedit_get_shapekeys(bAnimContext *ac)
ViewLayer *view_layer = ac->view_layer;
Object *ob;
Key *key;
-
+
ob = OBACT(view_layer);
- if (ob == NULL)
+ if (ob == NULL)
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);
-
+
if (key) {
if (key->type == KEY_RELATIVE)
return key;
}
-
+
return NULL;
}
@@ -159,7 +159,7 @@ 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' */
@@ -170,37 +170,37 @@ static bool actedit_get_context(bAnimContext *ac, SpaceAction *saction)
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;
@@ -213,48 +213,60 @@ static bool actedit_get_context(bAnimContext *ac, SpaceAction *saction)
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;
}
@@ -271,41 +283,41 @@ static bool graphedit_get_context(bAnimContext *ac, SpaceIpo *sipo)
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;
}
@@ -320,21 +332,21 @@ static bool nlaedit_get_context(bAnimContext *ac, SpaceNla *snla)
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;
-
+
ac->datatype = ANIMCONT_NLA;
ac->data = snla->ads;
-
+
return true;
}
/* ----------- Public API --------------- */
-/* Obtain current anim-data context, given that context info from Blender context has already been set
+/* Obtain current anim-data context, given that context info from Blender context has already been set
* - AnimContext to write to is provided as pointer to var on stack so that we don't have
* allocation/freeing costs (which are not that avoidable with channels).
*/
@@ -342,7 +354,7 @@ 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) {
@@ -366,32 +378,35 @@ bool ANIM_animdata_context_getdata(bAnimContext *ac)
}
}
}
-
+
/* check if there's any valid data */
return (ok && ac->data);
}
-/* Obtain current anim-data context from Blender Context info
+/* Obtain current anim-data context from Blender Context info
* - AnimContext to write to is provided as pointer to var on stack so that we don't have
* allocation/freeing costs (which are not that avoidable with channels).
* - Clears data and sets the information from Blender Context which is useful
*/
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;
@@ -399,10 +414,10 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
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);
@@ -417,8 +432,8 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
* cases:
* 1) Graph Edit main area (just data) OR channels visible in Channel List
* 2) If not showing channels, we're only interested in the data (Action Editor's editing)
- * 3) We don't care what data, we just care there is some (so that a collapsed
- * channel can be kept around). No need to clear channels-flag in order to
+ * 3) We don't care what data, we just care there is some (so that a collapsed
+ * channel can be kept around). No need to clear channels-flag in order to
* keep expander channels with no sub-data out, as those cases should get
* dealt with by the recursive detection idiom in place.
*
@@ -460,13 +475,13 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
/* quick macro to test if AnimData is usable for NLA */
#define ANIMDATA_HAS_NLA(id) ((id)->adt && (id)->adt->nla_tracks.first)
-/* Quick macro to test for all three above usability tests, performing the appropriate provided
- * action for each when the AnimData context is appropriate.
+/* Quick macro to test for all three above usability tests, performing the appropriate provided
+ * action for each when the AnimData context is appropriate.
*
* Priority order for this goes (most important, to least): AnimData blocks, NLA, Drivers, Keyframes.
*
* For this to work correctly, a standard set of data needs to be available within the scope that this
- * gets called in:
+ * gets called in:
* - ListBase anim_data;
* - bDopeSheet *ads;
* - bAnimListElem *ale;
@@ -483,7 +498,7 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
* 0) top level: checks for animdata and also that all the F-Curves for the block will be visible
* 1) animdata check: for filtering animdata blocks only
* 2A) nla tracks: include animdata block's data as there are NLA tracks+strips there
- * 2B) actions to convert to nla: include animdata block's data as there is an action that can be
+ * 2B) actions to convert to nla: include animdata block's data as there is an action that can be
* converted to a new NLA strip, and the filtering options allow this
* 2C) allow non-animated datablocks to be included so that datablocks can be added
* 3) drivers: include drivers from animdata block (for Drivers mode in Graph Editor)
@@ -524,7 +539,7 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
/* ............................... */
-/* Add a new animation channel, taking into account the "peek" flag, which is used to just check
+/* Add a new animation channel, taking into account the "peek" flag, which is used to just check
* whether any channels will be added (but without needing them to actually get created).
*
* ! This causes the calling function to return early if we're only "peeking" for channels
@@ -541,12 +556,12 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
ale_statement \
} \
} (void)0
-
+
#define ANIMCHANNEL_NEW_CHANNEL(channel_data, channel_type, owner_id) \
ANIMCHANNEL_NEW_CHANNEL_FULL(channel_data, channel_type, 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) )
@@ -556,8 +571,8 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
(!(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
+
+/* 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
*
* checks here work as follows:
@@ -572,29 +587,29 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
/* ----------- 'Private' Stuff --------------- */
-/* this function allocates memory for a new bAnimListElem struct for the
- * provided animation channel-data.
+/* 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)
{
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);
-
+
/* do specifics */
switch (datatype) {
case ANIMTYPE_SUMMARY:
{
- /* nothing to include for now... this is just a dummy wrappy around all the other channels
+ /* 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;
@@ -604,12 +619,12 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
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;
}
@@ -617,21 +632,21 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
{
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;
@@ -639,9 +654,9 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
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;
@@ -651,12 +666,12 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
{
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;
}
@@ -664,12 +679,12 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
{
Lamp *la = (Lamp *)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;
}
@@ -677,12 +692,12 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
{
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;
}
@@ -703,12 +718,12 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
{
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;
}
@@ -716,12 +731,12 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
{
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;
}
@@ -729,12 +744,12 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
{
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;
}
@@ -742,12 +757,12 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
{
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;
}
@@ -755,12 +770,12 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
{
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;
}
@@ -768,12 +783,12 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
{
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;
}
@@ -781,12 +796,12 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
{
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;
}
@@ -794,12 +809,12 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
{
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;
}
@@ -807,12 +822,12 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
{
FreestyleLineStyle *linestyle = (FreestyleLineStyle *)data;
AnimData *adt = linestyle->adt;
-
- ale->flag = FILTER_LS_SCED(linestyle);
-
+
+ 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;
}
@@ -820,12 +835,12 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
{
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;
}
@@ -833,12 +848,12 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
{
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;
}
@@ -846,14 +861,14 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
{
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;
}
@@ -873,9 +888,9 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
case ANIMTYPE_NLACONTROLS:
{
AnimData *adt = (AnimData *)data;
-
+
ale->flag = adt->flag;
-
+
ale->key_data = NULL;
ale->datatype = ALE_NONE;
break;
@@ -883,9 +898,9 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
case ANIMTYPE_GROUP:
{
bActionGroup *agrp = (bActionGroup *)data;
-
+
ale->flag = agrp->flag;
-
+
ale->key_data = NULL;
ale->datatype = ALE_GROUP;
break;
@@ -894,9 +909,9 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
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;
@@ -905,19 +920,19 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
{
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
*/
@@ -933,9 +948,9 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
case ANIMTYPE_GPLAYER:
{
bGPDlayer *gpl = (bGPDlayer *)data;
-
+
ale->flag = gpl->flag;
-
+
ale->key_data = NULL;
ale->datatype = ALE_GPFRAME;
break;
@@ -943,9 +958,9 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
case ANIMTYPE_MASKLAYER:
{
MaskLayer *masklay = (MaskLayer *)data;
-
+
ale->flag = masklay->flag;
-
+
ale->key_data = NULL;
ale->datatype = ALE_MASKLAY;
break;
@@ -953,9 +968,9 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
case ANIMTYPE_NLATRACK:
{
NlaTrack *nlt = (NlaTrack *)data;
-
+
ale->flag = nlt->flag;
-
+
ale->key_data = &nlt->strips;
ale->datatype = ALE_NLASTRIP;
break;
@@ -969,15 +984,15 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
}
}
}
-
+
/* return created datatype */
return ale;
}
-
+
/* ----------------------------------------- */
/* 'Only Selected' selected data and/or 'Include Hidden' filtering
- * NOTE: when this function returns true, the F-Curve is to be skipped
+ * NOTE: when this function returns true, the F-Curve is to be skipped
*/
static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id, int filter_mode)
{
@@ -986,26 +1001,26 @@ static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id
}
/* 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;
@@ -1013,7 +1028,7 @@ static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id
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)
@@ -1024,20 +1039,20 @@ static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id
}
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)
@@ -1047,17 +1062,17 @@ static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id
}
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)
@@ -1065,7 +1080,7 @@ static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id
}
}
}
-
+
return false;
}
@@ -1076,11 +1091,11 @@ static bool name_matches_dopesheet_filter(bDopeSheet *ads, char *name)
/* 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])) {
@@ -1088,7 +1103,7 @@ static bool name_matches_dopesheet_filter(bDopeSheet *ads, char *name)
break;
}
}
-
+
/* if we have a match somewhere, this returns true */
return found;
}
@@ -1099,33 +1114,33 @@ static bool name_matches_dopesheet_filter(bDopeSheet *ads, char *name)
}
/* (Display-)Name-based F-Curve filtering
- * NOTE: when this function returns true, the F-Curve is to be skipped
+ * 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)
{
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
+
+ /* 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;
}
@@ -1141,19 +1156,19 @@ static bool fcurve_has_errors(FCurve *fcu)
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) {
@@ -1165,7 +1180,7 @@ static bool fcurve_has_errors(FCurve *fcu)
DRIVER_TARGETS_LOOPER_END
}
}
-
+
/* no errors found */
return false;
}
@@ -1175,8 +1190,8 @@ static FCurve *animfilter_fcurve_next(bDopeSheet *ads, FCurve *first, eAnim_Chan
{
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
+
+ /* 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) {
@@ -1196,7 +1211,7 @@ static FCurve *animfilter_fcurve_next(bDopeSheet *ads, FCurve *first, eAnim_Chan
}
}
}
-
+
/* 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 */
@@ -1206,18 +1221,18 @@ static FCurve *animfilter_fcurve_next(bDopeSheet *ads, FCurve *first, eAnim_Chan
/* only include if this curve is active */
if (!(filter_mode & ANIMFILTER_ACTIVE) || (fcu->flag & FCURVE_ACTIVE)) {
/* name based filtering... */
- if ( ((ads) && (ads->filterflag & ADS_FILTER_BY_FCU_NAME)) && (owner_id) ) {
+ 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;
}
@@ -1225,7 +1240,7 @@ static FCurve *animfilter_fcurve_next(bDopeSheet *ads, FCurve *first, eAnim_Chan
}
}
}
-
+
/* no (more) F-Curves from the list are suitable... */
return NULL;
}
@@ -1237,14 +1252,14 @@ static size_t animfilter_fcurves(ListBase *anim_data, bDopeSheet *ads,
{
FCurve *fcu;
size_t items = 0;
-
- /* loop over every F-Curve able to be included
- * - this for-loop works like this:
+
+ /* 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
+ * 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
+ * 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) {
@@ -1260,7 +1275,7 @@ static size_t animfilter_fcurves(ListBase *anim_data, bDopeSheet *ads,
ANIMCHANNEL_NEW_CHANNEL(fcu, ANIMTYPE_FCURVE, owner_id);
}
}
-
+
/* return the number of items added to the list */
return items;
}
@@ -1271,8 +1286,8 @@ static size_t animfilter_act_group(bAnimContext *ac, ListBase *anim_data, bDopeS
size_t tmp_items = 0;
size_t items = 0;
//int ofilter = filter_mode;
-
- /* if we care about the selection status of the channels,
+
+ /* 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
@@ -1284,7 +1299,7 @@ static size_t animfilter_act_group(bAnimContext *ac, ListBase *anim_data, bDopeS
/* 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)
*
@@ -1295,14 +1310,14 @@ static size_t animfilter_act_group(bAnimContext *ac, ListBase *anim_data, bDopeS
*/
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
+ * 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)) {
@@ -1310,7 +1325,7 @@ static size_t animfilter_act_group(bAnimContext *ac, ListBase *anim_data, bDopeS
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);
}
@@ -1318,26 +1333,26 @@ static size_t animfilter_act_group(bAnimContext *ac, ListBase *anim_data, bDopeS
}
}
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);
}
}
-
+
/* 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;
}
@@ -1347,30 +1362,30 @@ static size_t animfilter_action(bAnimContext *ac, ListBase *anim_data, bDopeShee
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)
+ 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);
}
-
+
/* return the number of items added to the list */
return items;
}
@@ -1378,7 +1393,7 @@ static size_t animfilter_action(bAnimContext *ac, ListBase *anim_data, bDopeShee
/* Include NLA-Data for NLA-Editor:
* - when ANIMFILTER_LIST_CHANNELS is used, that means we should be filtering the list for display
* Although the evaluation order is from the first track to the last and then apply the Action on top,
- * we present this in the UI as the Active Action followed by the last track to the first so that we
+ * we present this in the UI as the Active Action followed by the last track to the first so that we
* get the evaluation order presented as per a stack.
* - 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.
@@ -1388,10 +1403,10 @@ static size_t animfilter_nla(bAnimContext *UNUSED(ac), ListBase *anim_data, bDop
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,
+ /* 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)) {
@@ -1401,13 +1416,13 @@ static size_t animfilter_nla(bAnimContext *UNUSED(ac), ListBase *anim_data, bDop
* - 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,
+ ANIMCHANNEL_NEW_CHANNEL_FULL((void *)(&adt->action), ANIMTYPE_NLAACTION, owner_id,
{
- ale->data = adt->action ? adt->action : 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;
}
@@ -1415,22 +1430,22 @@ static size_t animfilter_nla(bAnimContext *UNUSED(ac), ListBase *anim_data, bDop
/* 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)
+ 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
+
+ /* 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 */
@@ -1438,12 +1453,12 @@ static size_t animfilter_nla(bAnimContext *UNUSED(ac), ListBase *anim_data, bDop
/* only include if this track is active */
if (!(filter_mode & ANIMFILTER_ACTIVE) || (nlt->flag & NLATRACK_ACTIVE)) {
/* name based filtering... */
- if (((ads) && (ads->filterflag & ADS_FILTER_BY_FCU_NAME)) && (owner_id)) {
+ 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) {
@@ -1453,20 +1468,20 @@ static size_t animfilter_nla(bAnimContext *UNUSED(ac), ListBase *anim_data, bDop
}
}
}
-
+
/* 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);
}
}
}
}
-
+
/* return the number of items added to the list */
return items;
}
@@ -1479,14 +1494,14 @@ static size_t animfilter_nla_controls(ListBase *anim_data, bDopeSheet *ads, Anim
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) {
@@ -1496,7 +1511,7 @@ static size_t animfilter_nla_controls(ListBase *anim_data, bDopeSheet *ads, Anim
}
}
END_ANIMFILTER_SUBCHANNELS;
-
+
/* did we find anything? */
if (tmp_items) {
/* add the expander as a channel first */
@@ -1506,13 +1521,13 @@ static size_t animfilter_nla_controls(ListBase *anim_data, bDopeSheet *ads, Anim
ANIMCHANNEL_NEW_CHANNEL(adt, ANIMTYPE_NLACONTROLS, owner_id);
}
}
-
+
/* 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 numebr of items added to the list */
return items;
}
@@ -1522,11 +1537,11 @@ static size_t animfilter_block_data(bAnimContext *ac, ListBase *anim_data, bDope
{
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.
@@ -1552,7 +1567,7 @@ static size_t animfilter_block_data(bAnimContext *ac, ListBase *anim_data, bDope
}
);
}
-
+
return items;
}
@@ -1562,22 +1577,22 @@ static size_t animfilter_block_data(bAnimContext *ac, ListBase *anim_data, bDope
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);
}
@@ -1598,7 +1613,7 @@ static size_t animdata_filter_shapekey(bAnimContext *ac, ListBase *anim_data, Ke
}
}
}
-
+
/* return the number of items added to the list */
return items;
}
@@ -1608,7 +1623,7 @@ static size_t animdata_filter_gpencil_layers_data(ListBase *anim_data, bDopeShee
{
bGPDlayer *gpl;
size_t items = 0;
-
+
/* loop over layers as the conditions are acceptable */
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
/* only if selected */
@@ -1618,19 +1633,19 @@ static size_t animdata_filter_gpencil_layers_data(ListBase *anim_data, bDopeShee
/* 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->filterflag & ADS_FILTER_BY_FCU_NAME)) {
+ 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);
}
}
}
}
-
+
return items;
}
@@ -1638,7 +1653,7 @@ static size_t animdata_filter_gpencil_layers_data(ListBase *anim_data, bDopeShee
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...
@@ -1650,14 +1665,14 @@ static size_t animdata_filter_gpencil_data(ListBase *anim_data, bDopeSheet *ads,
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 */
@@ -1665,14 +1680,14 @@ static size_t animdata_filter_gpencil_data(ListBase *anim_data, bDopeSheet *ads,
/* add gpd as channel too (if for drawing, and it has layers) */
ANIMCHANNEL_NEW_CHANNEL(gpd, ANIMTYPE_GPDATABLOCK, 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;
}
@@ -1682,7 +1697,7 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, voi
{
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;
@@ -1692,45 +1707,45 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, voi
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->gpd) {
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
+ * - 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_VISIBLED) == 0) continue;
-
+ 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
+
+ /* 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->filterflag & ADS_FILTER_ONLYOBGROUP) {
- if (BKE_group_object_exists(ads->filter_grp, ob) == 0)
+ 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->gpd, filter_mode);
@@ -1739,18 +1754,18 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, voi
}
else {
bGPdata *gpd;
-
+
/* Grab all Grease Pencil datablocks directly from main, but only those that seem to be useful somewhere */
- for (gpd = G.main->gpencil.first; gpd; gpd = gpd->id.next) {
+ for (gpd = ac->bmain->gpencil.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;
}
@@ -1761,19 +1776,19 @@ static size_t animdata_filter_ds_gpencil(bAnimContext *ac, ListBase *anim_data,
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 */
@@ -1784,13 +1799,13 @@ static size_t animdata_filter_ds_gpencil(bAnimContext *ac, ListBase *anim_data,
ANIMCHANNEL_NEW_CHANNEL(gpd, ANIMTYPE_DSGPENCIL, gpd);
}
}
-
+
/* 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;
}
@@ -1857,28 +1872,28 @@ static size_t animdata_filter_mask_data(ListBase *anim_data, Mask *mask, const i
}
/* Grab all mask data */
-static size_t animdata_filter_mask(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 = G.main->mask.first; mask; mask = mask->id.next) {
+ for (mask = bmain->mask.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 */
@@ -1886,14 +1901,14 @@ static size_t animdata_filter_mask(ListBase *anim_data, void *UNUSED(data), int
/* add gpd as channel too (if for drawing, and it has layers) */
ANIMCHANNEL_NEW_CHANNEL(mask, ANIMTYPE_MASKDATABLOCK, 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;
}
@@ -1904,7 +1919,7 @@ static size_t animdata_filter_ds_nodetree_group(bAnimContext *ac, ListBase *anim
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))
{
@@ -1912,7 +1927,7 @@ static size_t animdata_filter_ds_nodetree_group(bAnimContext *ac, ListBase *anim
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 */
@@ -1922,13 +1937,13 @@ static size_t animdata_filter_ds_nodetree_group(bAnimContext *ac, ListBase *anim
ANIMCHANNEL_NEW_CHANNEL(ntree, ANIMTYPE_DSNTREE, owner_id);
}
}
-
+
/* 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;
}
@@ -1937,9 +1952,9 @@ static size_t animdata_filter_ds_nodetree(bAnimContext *ac, ListBase *anim_data,
{
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) {
@@ -1960,7 +1975,7 @@ static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data
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) {
@@ -1968,7 +1983,7 @@ static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data
}
}
}
-
+
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) {
@@ -1987,7 +2002,7 @@ static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data
continue;
}
linestyle->id.tag &= ~LIB_TAG_DOIT;
-
+
/* add scene-level animation channels */
BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_LS_SCED(linestyle))
{
@@ -1995,7 +2010,7 @@ static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data
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 */
@@ -2005,7 +2020,7 @@ static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data
ANIMCHANNEL_NEW_CHANNEL(linestyle, ANIMTYPE_DSLINESTYLE, sce);
}
}
-
+
/* now add the list of collected channels */
BLI_movelisttolist(anim_data, &tmp_data);
BLI_assert(BLI_listbase_is_empty(&tmp_data));
@@ -2013,24 +2028,24 @@ static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data
}
}
}
-
+
/* 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,
+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))
+ 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 */
@@ -2040,7 +2055,7 @@ static size_t animdata_filter_ds_texture(bAnimContext *ac, ListBase *anim_data,
}
}
END_ANIMFILTER_SUBCHANNELS;
-
+
/* did we find anything? */
if (tmp_items) {
/* include texture-expand widget? */
@@ -2050,13 +2065,13 @@ static size_t animdata_filter_ds_texture(bAnimContext *ac, ListBase *anim_data,
ANIMCHANNEL_NEW_CHANNEL(tex, ANIMTYPE_DSTEX, owner_id);
}
}
-
+
/* 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;
}
@@ -2069,11 +2084,11 @@ static size_t animdata_filter_ds_textures(bAnimContext *ac, ListBase *anim_data,
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:
{
@@ -2081,7 +2096,7 @@ static size_t animdata_filter_ds_textures(bAnimContext *ac, ListBase *anim_data,
mtex = (MTex **)(&part->mtex);
break;
}
- default:
+ default:
{
/* invalid/unsupported option */
if (G.debug & G_DEBUG)
@@ -2089,19 +2104,19 @@ static size_t animdata_filter_ds_textures(bAnimContext *ac, ListBase *anim_data,
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)
+ 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;
}
@@ -2112,19 +2127,19 @@ static size_t animdata_filter_ds_material(bAnimContext *ac, ListBase *anim_data,
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))
+ 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 */
@@ -2134,13 +2149,13 @@ static size_t animdata_filter_ds_material(bAnimContext *ac, ListBase *anim_data,
ANIMCHANNEL_NEW_CHANNEL(ma, ANIMTYPE_DSMAT, ma);
}
}
-
+
/* 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;
}
@@ -2149,23 +2164,23 @@ static size_t animdata_filter_ds_materials(bAnimContext *ac, ListBase *anim_data
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
@@ -2175,7 +2190,7 @@ static size_t animdata_filter_ds_materials(bAnimContext *ac, ListBase *anim_data
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
@@ -2186,7 +2201,7 @@ static size_t animdata_filter_ds_materials(bAnimContext *ac, ListBase *anim_data
}
}
}
-
+
/* return the number of items added to the list */
return items;
}
@@ -2198,10 +2213,10 @@ static size_t animdata_filter_ds_materials(bAnimContext *ac, ListBase *anim_data
typedef struct tAnimFilterModifiersContext {
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 */
-
+
int filter_mode; /* flags for stuff we want to filter */
} tAnimFilterModifiersContext;
@@ -2212,31 +2227,31 @@ static void animfilter_modifier_idpoin_cb(void *afm_ptr, Object *ob, ID **idpoin
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*,
+
+ /* 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)) {
+ 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
+/* animation linked to data used by modifiers
* NOTE: strictly speaking, modifier animation is already included under Object level
* but for some modifiers (e.g. Displace), there can be linked data that has settings
* which would be nice to animate (i.e. texture parameters) but which are not actually
@@ -2247,8 +2262,8 @@ static size_t animdata_filter_ds_modifiers(bAnimContext *ac, ListBase *anim_data
{
tAnimFilterModifiersContext afm = {NULL};
size_t items = 0;
-
- /* 1) create a temporary "context" containing all the info we have here to pass to the callback
+
+ /* 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
@@ -2256,10 +2271,10 @@ static size_t animdata_filter_ds_modifiers(bAnimContext *ac, ListBase *anim_data
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 */
@@ -2267,7 +2282,7 @@ static size_t animdata_filter_ds_modifiers(bAnimContext *ac, ListBase *anim_data
BLI_assert(BLI_listbase_is_empty(&afm.tmp_data));
items += afm.items;
}
-
+
return items;
}
@@ -2282,23 +2297,23 @@ static size_t animdata_filter_ds_particles(bAnimContext *ac, ListBase *anim_data
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 */
@@ -2308,14 +2323,14 @@ static size_t animdata_filter_ds_particles(bAnimContext *ac, ListBase *anim_data
ANIMCHANNEL_NEW_CHANNEL(psys->part, ANIMTYPE_DSPART, psys->part);
}
}
-
+
/* 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;
}
@@ -2326,19 +2341,19 @@ static size_t animdata_filter_ds_obdata(bAnimContext *ac, ListBase *anim_data, b
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;
@@ -2346,10 +2361,10 @@ static size_t animdata_filter_ds_obdata(bAnimContext *ac, ListBase *anim_data, b
case OB_LAMP: /* ---------- Lamp ----------- */
{
Lamp *la = (Lamp *)ob->data;
-
+
if (ads->filterflag & ADS_FILTER_NOLAM)
return 0;
-
+
type = ANIMTYPE_DSLAM;
expanded = FILTER_LAM_OBJD(la);
break;
@@ -2359,10 +2374,10 @@ static size_t animdata_filter_ds_obdata(bAnimContext *ac, ListBase *anim_data, b
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;
@@ -2370,10 +2385,10 @@ static size_t animdata_filter_ds_obdata(bAnimContext *ac, ListBase *anim_data, b
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;
@@ -2381,10 +2396,10 @@ static size_t animdata_filter_ds_obdata(bAnimContext *ac, ListBase *anim_data, b
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;
@@ -2392,10 +2407,10 @@ static size_t animdata_filter_ds_obdata(bAnimContext *ac, ListBase *anim_data, b
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;
@@ -2403,10 +2418,10 @@ static size_t animdata_filter_ds_obdata(bAnimContext *ac, ListBase *anim_data, b
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;
@@ -2414,26 +2429,26 @@ static size_t animdata_filter_ds_obdata(bAnimContext *ac, ListBase *anim_data, b
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: /* lamp - textures + nodetree */
{
Lamp *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);
@@ -2442,7 +2457,7 @@ static size_t animdata_filter_ds_obdata(bAnimContext *ac, ListBase *anim_data, b
}
}
END_ANIMFILTER_SUBCHANNELS;
-
+
/* did we find anything? */
if (tmp_items) {
/* include data-expand widget first */
@@ -2452,13 +2467,13 @@ static size_t animdata_filter_ds_obdata(bAnimContext *ac, ListBase *anim_data, b
ANIMCHANNEL_NEW_CHANNEL(iat, type, iat);
}
}
-
+
/* 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;
}
@@ -2469,7 +2484,7 @@ static size_t animdata_filter_ds_keyanim(bAnimContext *ac, ListBase *anim_data,
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))
{
@@ -2477,7 +2492,7 @@ static size_t animdata_filter_ds_keyanim(bAnimContext *ac, ListBase *anim_data,
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 */
@@ -2486,13 +2501,13 @@ static size_t animdata_filter_ds_keyanim(bAnimContext *ac, ListBase *anim_data,
ANIMCHANNEL_NEW_CHANNEL(key, ANIMTYPE_DSSKEY, ob);
}
}
-
+
/* 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;
}
@@ -2504,7 +2519,7 @@ static size_t animdata_filter_ds_obanim(bAnimContext *ac, ListBase *anim_data, b
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;
@@ -2525,7 +2540,7 @@ static size_t animdata_filter_ds_obanim(bAnimContext *ac, ListBase *anim_data, b
cdata = adt->action;
expanded = EXPANDED_ACTC(adt->action);
});
-
+
/* add object-level animation channels */
BEGIN_ANIMFILTER_SUBCHANNELS(expanded)
{
@@ -2533,7 +2548,7 @@ static size_t animdata_filter_ds_obanim(bAnimContext *ac, ListBase *anim_data, b
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 */
@@ -2543,13 +2558,13 @@ static size_t animdata_filter_ds_obanim(bAnimContext *ac, ListBase *anim_data, b
ANIMCHANNEL_NEW_CHANNEL(cdata, type, ob);
}
}
-
+
/* 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;
}
@@ -2561,50 +2576,50 @@ static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data
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->gpd) && !(ads->filterflag & ADS_FILTER_NOGPENCIL)) {
tmp_items += animdata_filter_ds_gpencil(ac, &tmp_data, ads, ob->gpd, 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 */
@@ -2618,13 +2633,13 @@ static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data
}
}
}
-
+
/* 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;
}
@@ -2634,19 +2649,19 @@ static size_t animdata_filter_ds_world(bAnimContext *ac, ListBase *anim_data, bD
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))
+ 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 */
@@ -2656,13 +2671,13 @@ static size_t animdata_filter_ds_world(bAnimContext *ac, ListBase *anim_data, bD
ANIMCHANNEL_NEW_CHANNEL(wo, ANIMTYPE_DSWOR, sce);
}
}
-
+
/* 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;
}
@@ -2672,11 +2687,11 @@ static size_t animdata_filter_ds_scene(bAnimContext *ac, ListBase *anim_data, bD
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,
@@ -2693,7 +2708,7 @@ static size_t animdata_filter_ds_scene(bAnimContext *ac, ListBase *anim_data, bD
cdata = adt->action;
expanded = EXPANDED_ACTC(adt->action);
});
-
+
/* add scene-level animation channels */
BEGIN_ANIMFILTER_SUBCHANNELS(expanded)
{
@@ -2701,7 +2716,7 @@ static size_t animdata_filter_ds_scene(bAnimContext *ac, ListBase *anim_data, bD
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 */
@@ -2711,13 +2726,13 @@ static size_t animdata_filter_ds_scene(bAnimContext *ac, ListBase *anim_data, bD
ANIMCHANNEL_NEW_CHANNEL(cdata, type, sce);
}
}
-
+
/* 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;
}
@@ -2727,39 +2742,39 @@ static size_t animdata_filter_dopesheet_scene(bAnimContext *ac, ListBase *anim_d
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;
@@ -2774,13 +2789,13 @@ static size_t animdata_filter_dopesheet_scene(bAnimContext *ac, ListBase *anim_d
ANIMCHANNEL_NEW_CHANNEL(sce, ANIMTYPE_SCENE, sce);
}
}
-
+
/* 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;
}
@@ -2819,7 +2834,7 @@ static size_t animdata_filter_dopesheet_movieclips(bAnimContext *ac, ListBase *a
{
size_t items = 0;
MovieClip *clip;
- for (clip = G.main->movieclip.first; clip != NULL; clip = clip->id.next) {
+ for (clip = ac->bmain->movieclip.first; clip != NULL; clip = clip->id.next) {
/* only show if gpd is used by something... */
if (ID_REAL_USERS(clip) < 1) {
continue;
@@ -2834,31 +2849,31 @@ static size_t animdata_filter_dopesheet_movieclips(bAnimContext *ac, ListBase *a
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
+ * - 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_VISIBLED) == 0)
+ 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 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))
@@ -2888,16 +2903,16 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Base *base, int filter_m
/* only selected should be shown */
return false;
}
-
- /* check if object belongs to the filtering group if option to filter
+
+ /* 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->filterflag & ADS_FILTER_ONLYOBGROUP) {
- if (BKE_group_object_exists(ads->filter_grp, ob) == 0)
+ 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;
}
@@ -2907,7 +2922,7 @@ 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);
-
+
return strcmp(b1->object->id.name + 2, b2->object->id.name + 2);
}
@@ -2917,17 +2932,17 @@ static Base **animdata_filter_ds_sorted_bases(bDopeSheet *ads, ViewLayer *view_l
/* 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;
@@ -2948,17 +2963,17 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, b
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
+
+ /* 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). */
- CacheFile *cache_file = G.main->cachefiles.first;
+ 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);
}
@@ -2983,16 +2998,16 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, b
// 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);
}
@@ -3008,20 +3023,20 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, b
}
}
}
-
+
/* return the number of items in the list */
return items;
}
-/* Summary track for DopeSheet/Action Editor
+/* 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)
{
bDopeSheet *ads = NULL;
-
- /* get the DopeSheet information to use
- * - we should only need to deal with the DopeSheet/Action Editor,
+
+ /* 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.
*/
@@ -3033,9 +3048,9 @@ static short animdata_filter_dopesheet_summary(bAnimContext *ac, ListBase *anim_
/* 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
+
+ /* 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)) {
@@ -3044,17 +3059,17 @@ static short animdata_filter_dopesheet_summary(bAnimContext *ac, ListBase *anim_
BLI_addtail(anim_data, ale);
(*items)++;
}
-
- /* if summary is collapsed, don't show other channels beneath this
+
+ /* 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;
-}
+}
/* ......................... */
@@ -3062,18 +3077,18 @@ static short animdata_filter_dopesheet_summary(bAnimContext *ac, ListBase *anim_
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;
@@ -3085,12 +3100,12 @@ static size_t animdata_filter_animchan(bAnimContext *ac, ListBase *anim_data, bD
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;
}
@@ -3101,17 +3116,17 @@ static size_t animdata_filter_remove_invalid(ListBase *anim_data)
{
bAnimListElem *ale, *next;
size_t items = 0;
-
+
/* 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++;
}
-
+
return items;
}
@@ -3121,18 +3136,18 @@ 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
+
+ /* 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
+
+ /* 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)) {
@@ -3144,10 +3159,10 @@ static size_t animdata_filter_remove_duplis(ListBase *anim_data)
BLI_freelinkN(anim_data, ale);
}
}
-
+
/* free the hash... */
BLI_gset_free(gs, NULL);
-
+
/* return the number of items still in the list */
return items;
}
@@ -3155,8 +3170,8 @@ static size_t animdata_filter_remove_duplis(ListBase *anim_data)
/* ----------- Public API --------------- */
/* This function filters the active data source to leave only animation channels suitable for
- * usage by the caller. It will return the length of the list
- *
+ * usage by the caller. It will return the length of the list
+ *
* *anim_data: is a pointer to a ListBase, to which the filtered animation channels
* will be placed for use.
* filter_mode: how should the data be filtered - bitmapping accessed flags
@@ -3164,7 +3179,7 @@ static size_t animdata_filter_remove_duplis(ListBase *anim_data)
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 */
@@ -3175,7 +3190,7 @@ size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, eAnimFilter_F
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 */
@@ -3188,13 +3203,13 @@ size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, eAnimFilter_F
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 */
@@ -3207,11 +3222,11 @@ size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, eAnimFilter_F
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:
{
@@ -3222,11 +3237,11 @@ size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, eAnimFilter_F
case ANIMCONT_MASK:
{
if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
- items = animdata_filter_mask(anim_data, data, filter_mode);
+ items = animdata_filter_mask(ac->bmain, anim_data, data, filter_mode);
break;
}
-
-
+
+
/* DopeSheet Based Modes */
case ANIMCONT_DOPESHEET: /* 'DopeSheet Editor' */
{
@@ -3243,8 +3258,8 @@ size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, eAnimFilter_F
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:
{
@@ -3253,17 +3268,17 @@ size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, eAnimFilter_F
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:
{
@@ -3274,12 +3289,12 @@ size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, eAnimFilter_F
/* 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 c571da1ba74..de91ce06c8b 100644
--- a/source/blender/editors/animation/anim_intern.h
+++ b/source/blender/editors/animation/anim_intern.h
@@ -27,7 +27,7 @@
* \ingroup edanimation
*/
-
+
#ifndef __ANIM_INTERN_H__
#define __ANIM_INTERN_H__
@@ -38,15 +38,15 @@ extern ListBase builtin_keyingsets;
/* Operator Define Prototypes ------------------- */
-/* Main Keyframe Management operators:
+/* Main Keyframe Management operators:
* These handle keyframes management from various spaces. They only make use of
* Keying Sets.
*/
void ANIM_OT_keyframe_insert(struct wmOperatorType *ot);
void ANIM_OT_keyframe_delete(struct wmOperatorType *ot);
-/* Main Keyframe Management operators:
- * These handle keyframes management from various spaces. They will handle the menus
+/* Main Keyframe Management operators:
+ * These handle keyframes management from various spaces. They will handle the menus
* required for each space.
*/
void ANIM_OT_keyframe_insert_menu(struct wmOperatorType *ot);
@@ -79,6 +79,7 @@ void ANIM_OT_keying_set_active_set(struct wmOperatorType *ot);
/* Driver management operators for UI buttons (RMB menu) */
void ANIM_OT_driver_button_add(struct wmOperatorType *ot);
void ANIM_OT_driver_button_remove(struct wmOperatorType *ot);
+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);
diff --git a/source/blender/editors/animation/anim_ipo_utils.c b/source/blender/editors/animation/anim_ipo_utils.c
index fc6f4036d02..4e0993152f7 100644
--- a/source/blender/editors/animation/anim_ipo_utils.c
+++ b/source/blender/editors/animation/anim_ipo_utils.c
@@ -53,13 +53,13 @@
/* ----------------------- Getter functions ----------------------- */
/* Write into "name" buffer, the name of the property (retrieved using RNA from the curve's settings),
- * and return the icon used for the struct that this property refers to
+ * and return the icon used for the struct that this property refers to
* WARNING: name buffer we're writing to cannot exceed 256 chars (check anim_channels_defines.c for details)
*/
int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
{
int icon = 0;
-
+
/* sanity checks */
if (name == NULL)
return icon;
@@ -74,17 +74,17 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
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>
@@ -93,12 +93,12 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
* 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
+ * 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
+ * - 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
@@ -108,11 +108,11 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
/* 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);
@@ -127,25 +127,25 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
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 */
@@ -153,17 +153,17 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
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]
*/
@@ -172,16 +172,16 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
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;
}
@@ -197,7 +197,7 @@ 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
@@ -206,24 +206,24 @@ void getcolor_fcurve_rainbow(int cur, int tot, float out[3])
*/
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
+
+ /* '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
+ * 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 091346921dc..de133663ee6 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -61,6 +61,7 @@
#include "GPU_immediate.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "UI_interface.h"
#include "UI_interface_icons.h"
@@ -76,6 +77,8 @@
#include "ED_transform.h"
#include "ED_types.h"
+#include "DEG_depsgraph.h"
+
/* ************* Marker API **************** */
/* helper function for getting the list of markers to work on */
@@ -85,8 +88,8 @@ static ListBase *context_get_markers(Scene *scene, ScrArea *sa)
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
+
+ /* 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)) {
@@ -96,7 +99,7 @@ static ListBase *context_get_markers(Scene *scene, ScrArea *sa)
}
}
}
-
+
/* default to using the scene's markers */
return &scene->markers;
}
@@ -135,7 +138,7 @@ int ED_markers_post_apply_transform(ListBase *markers, Scene *scene, int mode, f
TimeMarker *marker;
float cfra = (float)CFRA;
int changed_tot = 0;
-
+
/* sanity check - no markers, or locked markers */
if ((scene->toolsettings->lock_markers) ||
(markers == NULL))
@@ -170,7 +173,7 @@ int ED_markers_post_apply_transform(ListBase *markers, Scene *scene, int mode, f
}
}
}
-
+
return changed_tot;
}
@@ -182,18 +185,18 @@ TimeMarker *ED_markers_find_nearest_marker(ListBase *markers, float x)
{
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 (dist < min_dist) {
min_dist = dist;
nearest = marker;
}
}
}
-
+
return nearest;
}
@@ -209,7 +212,7 @@ void ED_markers_get_minmax(ListBase *markers, short sel, float *first, float *la
{
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)) {
@@ -228,7 +231,7 @@ void ED_markers_get_minmax(ListBase *markers, short sel, float *first, float *la
max = (float)marker->frame;
}
}
-
+
/* set the min/max values */
*first = min;
*last = max;
@@ -240,16 +243,16 @@ void ED_markers_get_minmax(ListBase *markers, short sel, float *first, float *la
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)
+ if (marker->flag & SELECT)
ce->sel = marker->flag;
return;
}
@@ -257,7 +260,7 @@ static void add_marker_to_cfra_elem(ListBase *lb, TimeMarker *marker, short only
break;
}
}
-
+
cen = MEM_callocN(sizeof(CfraElem), "add_to_cfra_elem");
if (ce) BLI_insertlinkbefore(lb, ce, cen);
else BLI_addtail(lb, cen);
@@ -273,7 +276,7 @@ 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
@@ -284,11 +287,11 @@ void ED_markers_make_cfra_list(ListBase *markers, ListBase *lb, short only_sel)
else {
return;
}
-
+
if (markers == NULL) {
return;
}
-
+
for (marker = markers->first; marker; marker = marker->next)
add_marker_to_cfra_elem(lb, marker, only_sel);
}
@@ -299,37 +302,37 @@ void ED_markers_make_cfra_list(ListBase *markers, ListBase *lb, short only_sel)
TimeMarker *ED_markers_get_first_selected(ListBase *markers)
{
TimeMarker *marker;
-
+
if (markers) {
for (marker = markers->first; marker; marker = marker->next) {
if (marker->flag & SELECT)
return marker;
}
}
-
+
return NULL;
}
/* --------------------------------- */
-/* Print debugging prints of list of markers
+/* Print debugging prints of list of markers
* BSI's: do NOT make static or put in if-defs as "unused code". That's too much trouble when we need to use for quick debugging!
*/
void debug_markers_print_list(ListBase *markers)
{
TimeMarker *marker;
-
+
if (markers == NULL) {
printf("No markers list to print debug for\n");
return;
}
-
+
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);
}
-
+
printf("End of list ------------------\n");
}
@@ -344,7 +347,7 @@ static void draw_marker_name(
/* 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;
@@ -387,8 +390,8 @@ static void draw_marker(
#endif
int icon_id;
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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 */
#ifdef DURIAN_CAMERA_SWITCH
@@ -403,7 +406,7 @@ static void draw_marker(
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
if (marker->flag & SELECT) {
@@ -422,7 +425,7 @@ static void draw_marker(
immUnbindProgram();
}
-
+
/* 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 :
@@ -439,11 +442,11 @@ static void draw_marker(
icon_id = (marker->flag & SELECT) ? ICON_MARKER_HLT :
ICON_MARKER;
}
-
+
UI_icon_draw(xpos - 0.45f * UI_DPI_ICON_SIZE, yoffs + UI_DPI_ICON_SIZE, icon_id);
-
- glDisable(GL_BLEND);
-
+
+ GPU_blend(false);
+
/* and the marker name too, shifted slightly to the top-right */
#ifdef DURIAN_CAMERA_SWITCH
if (marker->camera) {
@@ -489,12 +492,12 @@ void ED_markers_draw(const bContext *C, int flag)
const unsigned char shade[4] = {0, 0, 0, 16};
immUniformColor4ubv(shade);
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
immRectf(pos, v2d->cur.xmin, 0, v2d->cur.xmax, UI_MARKER_MARGIN_Y);
- glDisable(GL_BLEND);
+ GPU_blend(false);
immUnbindProgram();
}
@@ -530,8 +533,8 @@ void ED_markers_draw(const bContext *C, int flag)
}
/* ************************ Marker Wrappers API ********************* */
-/* These wrappers allow marker operators to function within the confines
- * of standard animation editors, such that they can coexist with the
+/* These wrappers allow marker operators to function within the confines
+ * of standard animation editors, such that they can coexist with the
* primary operations of those editors.
*/
@@ -541,11 +544,11 @@ void ED_markers_draw(const bContext *C, int flag)
static int ed_markers_poll_selected_markers(bContext *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;
-
+
/* check if some marker is selected */
return ED_markers_get_first_selected(markers) != NULL;
}
@@ -572,19 +575,19 @@ static int ed_markers_poll_markers_exist(bContext *C)
{
ListBase *markers = ED_context_get_markers(C);
ToolSettings *ts = CTX_data_tool_settings(C);
-
+
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;
-
+
/* list of markers must exist, as well as some markers in it! */
return (markers && markers->first);
}
-
-/* ------------------------ */
+
+/* ------------------------ */
/**
* Second-tier invoke() callback that performs context validation before running the
@@ -637,30 +640,30 @@ 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)
+ 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;
}
@@ -670,39 +673,39 @@ static void MARKER_OT_add(wmOperatorType *ot)
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 *************************** */
-/* operator state vars used:
+/* operator state vars used:
* frs: delta movement
- *
+ *
* functions:
- *
+ *
* init() check selection, add customdata with old values and some lookups
- *
+ *
* apply() do the actual movement
- *
+ *
* exit() cleanup, send notifier
- *
+ *
* cancel() to escape from modal
- *
+ *
* callbacks:
- *
- * exec() calls init, apply, exit
- *
+ *
+ * exec() calls init, apply, exit
+ *
* invoke() calls init, adds modal handler
- *
+ *
* modal() accept modal events while doing it, ends with apply and exit, or cancel
- *
+ *
*/
typedef struct MarkerMove {
@@ -767,7 +770,7 @@ static void ed_marker_move_update_header(bContext *C, wmOperator *op)
BLI_snprintf(str, sizeof(str), IFACE_("Marker offset %s"), str_offs);
}
- ED_area_headerprint(CTX_wm_area(C), str);
+ ED_area_status_text(CTX_wm_area(C), str);
}
/* copy selection to temp buffer */
@@ -820,28 +823,28 @@ static bool ed_marker_move_init(bContext *C, wmOperator *op)
static void ed_marker_move_exit(bContext *C, wmOperator *op)
{
MarkerMove *mm = op->customdata;
-
+
/* free data */
MEM_freeN(mm->oldframe);
MEM_freeN(op->customdata);
op->customdata = NULL;
-
+
/* clear custom header prints */
- ED_area_headerprint(CTX_wm_area(C), NULL);
+ 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;
-
+
mm->evtx = event->x;
mm->firstx = event->x;
mm->event_type = event->type;
-
+
/* add temp handler */
WM_event_add_modal_handler(C, op);
-
+
/* reset frs delta */
RNA_int_set(op->ptr, "frames", 0);
@@ -849,7 +852,7 @@ static int ed_marker_move_invoke(bContext *C, wmOperator *op, const wmEvent *eve
return OPERATOR_RUNNING_MODAL;
}
-
+
return OPERATOR_CANCELLED;
}
@@ -869,7 +872,7 @@ static void ed_marker_move_apply(bContext *C, wmOperator *op)
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) {
@@ -880,7 +883,7 @@ static void ed_marker_move_apply(bContext *C, wmOperator *op)
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);
@@ -1002,17 +1005,17 @@ static void MARKER_OT_move(wmOperatorType *ot)
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);
}
@@ -1040,8 +1043,8 @@ static void ed_marker_duplicate_apply(bContext *C)
{
ListBase *markers = ED_context_get_markers(C);
TimeMarker *marker, *newmarker;
-
- if (markers == NULL)
+
+ if (markers == NULL)
return;
/* go through the list of markers, duplicate selected markers and add duplicated copies
@@ -1051,13 +1054,13 @@ static void ed_marker_duplicate_apply(bContext *C)
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;
#endif
@@ -1073,9 +1076,9 @@ 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;
-
+
}
static int ed_marker_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
@@ -1095,17 +1098,17 @@ static void MARKER_OT_duplicate(wmOperatorType *ot)
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);
}
@@ -1152,18 +1155,18 @@ static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool
View2D *v2d = UI_view2d_fromcontext(C);
float viewx;
int x, cfra;
-
+
if (markers == NULL)
return OPERATOR_PASS_THROUGH;
x = event->x - ar->winrct.xmin;
-
+
viewx = UI_view2d_region_to_view_x(v2d, x);
-
+
cfra = ED_markers_find_nearest_marker_time(markers, viewx);
-
+
select_timeline_marker_frame(markers, cfra, extend);
-
+
#ifdef DURIAN_CAMERA_SWITCH
if (camera) {
@@ -1172,17 +1175,17 @@ static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool
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) {
@@ -1195,7 +1198,8 @@ static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool
}
}
}
-
+
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
#else
@@ -1232,11 +1236,11 @@ static void MARKER_OT_select(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1250,7 +1254,7 @@ static void MARKER_OT_select(wmOperatorType *ot)
/* *************************** border select markers **************** */
-/* operator state vars used: (added by default WM callbacks)
+/* operator state vars used: (added by default WM callbacks)
* xmin, ymin
* xmax, ymax
*
@@ -1277,13 +1281,13 @@ static int ed_marker_border_select_exec(bContext *C, wmOperator *op)
bool select = !RNA_boolean_get(op->ptr, "deselect");
bool extend = RNA_boolean_get(op->ptr, "extend");
rctf rect;
-
+
WM_operator_properties_border_to_rctf(op, &rect);
UI_view2d_region_to_view_rctf(v2d, &rect, &rect);
-
+
if (markers == NULL)
return 0;
-
+
/* XXX marker context */
for (marker = markers->first; marker; marker = marker->next) {
if (BLI_rctf_isect_x(&rect, marker->frame)) {
@@ -1298,7 +1302,7 @@ static int ed_marker_border_select_exec(bContext *C, wmOperator *op)
marker->flag &= ~SELECT;
}
}
-
+
WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
@@ -1316,18 +1320,18 @@ static void MARKER_OT_select_border(wmOperatorType *ot)
ot->name = "Marker Border Select";
ot->description = "Select all time markers using border selection";
ot->idname = "MARKER_OT_select_border";
-
+
/* api callbacks */
ot->exec = ed_marker_border_select_exec;
ot->invoke = ed_marker_select_border_invoke_wrapper;
ot->modal = WM_gesture_border_modal;
ot->cancel = WM_gesture_border_cancel;
-
+
ot->poll = ed_markers_poll_markers_exist;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* rna */
WM_operator_properties_gesture_border_select(ot);
}
@@ -1346,7 +1350,7 @@ static int ed_marker_select_all_exec(bContext *C, wmOperator *op)
if (action == SEL_TOGGLE) {
action = (ED_markers_get_first_selected(markers) != NULL) ? SEL_DESELECT : SEL_SELECT;
}
-
+
for (marker = markers->first; marker; marker = marker->next) {
switch (action) {
case SEL_SELECT:
@@ -1360,7 +1364,7 @@ static int ed_marker_select_all_exec(bContext *C, wmOperator *op)
break;
}
}
-
+
WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
@@ -1373,15 +1377,15 @@ static void MARKER_OT_select_all(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* rna */
WM_operator_properties_select_all(ot);
}
@@ -1394,10 +1398,10 @@ 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) {
@@ -1405,12 +1409,12 @@ static int ed_marker_delete_exec(bContext *C, wmOperator *UNUSED(op))
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;
}
@@ -1426,12 +1430,12 @@ static void MARKER_OT_delete(wmOperatorType *ot)
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;
}
@@ -1446,10 +1450,10 @@ static int ed_marker_rename_exec(bContext *C, wmOperator *op)
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);
-
+
return OPERATOR_FINISHED;
}
else {
@@ -1463,7 +1467,7 @@ static int ed_marker_rename_invoke_wrapper(bContext *C, wmOperator *op, const wm
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);
}
@@ -1474,15 +1478,15 @@ static void MARKER_OT_rename(wmOperatorType *ot)
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");
@@ -1516,7 +1520,7 @@ static int ed_marker_make_links_scene_exec(bContext *C, wmOperator *op)
if (marker->flag & SELECT) {
marker_new = MEM_dupallocN(marker);
marker_new->prev = marker_new->next = NULL;
-
+
BLI_addtail(&scene_to->markers, marker_new);
}
}
@@ -1645,7 +1649,7 @@ void ED_keymap_marker(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_find(keyconf, "Markers", 0, 0);
wmKeyMapItem *kmi;
-
+
WM_keymap_verify_item(keymap, "MARKER_OT_add", MKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "MARKER_OT_move", EVT_TWEAK_S, KM_ANY, 0, 0);
WM_keymap_verify_item(keymap, "MARKER_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0);
@@ -1664,13 +1668,15 @@ void ED_keymap_marker(wmKeyConfig *keyconf)
#else
(void)kmi;
#endif
-
+
WM_keymap_verify_item(keymap, "MARKER_OT_select_border", BKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "MARKER_OT_select_all", AKEY, KM_PRESS, 0, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "MARKER_OT_delete", XKEY, KM_PRESS, 0, 0);
+#endif
WM_keymap_add_item(keymap, "MARKER_OT_delete", DELKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "MARKER_OT_rename", MKEY, KM_PRESS, KM_CTRL, 0);
-
+
WM_keymap_add_item(keymap, "MARKER_OT_move", GKEY, KM_PRESS, 0, 0);
#ifdef DURIAN_CAMERA_SWITCH
WM_keymap_add_item(keymap, "MARKER_OT_camera_bind", BKEY, KM_PRESS, KM_CTRL, 0);
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index eace5af4701..4402ca78976 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation, Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
@@ -67,10 +67,10 @@
static int 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
*/
@@ -85,7 +85,7 @@ static int change_frame_poll(bContext *C)
return false;
}
}
-
+
CTX_wm_operator_poll_msg_set(C, "Expected an animation area to be active");
return false;
}
@@ -139,12 +139,12 @@ static float frame_from_event(bContext *C, const wmEvent *event)
/* 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);
}
-
+
return frame;
}
@@ -195,7 +195,7 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event
change_frame_seq_preview_begin(C, event);
change_frame_apply(C, op);
-
+
/* add temp handler */
WM_event_add_modal_handler(C, op);
@@ -221,11 +221,11 @@ static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
RNA_float_set(op->ptr, "frame", frame_from_event(C, event));
change_frame_apply(C, op);
break;
-
- case LEFTMOUSE:
+
+ case LEFTMOUSE:
case RIGHTMOUSE:
case MIDDLEMOUSE:
- /* we check for either mouse-button to end, as checking for ACTIONMOUSE (which is used to init
+ /* we check for either mouse-button to end, as checking for ACTIONMOUSE (which is used to init
* the modal op) doesn't work for some reason
*/
if (event->val == KM_RELEASE)
@@ -258,17 +258,17 @@ static void ANIM_OT_change_frame(wmOperatorType *ot)
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";
+ ot->undo_group = "Frame Change";
/* rna */
ot->prop = RNA_def_float(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
@@ -282,10 +282,10 @@ static void ANIM_OT_change_frame(wmOperatorType *ot)
static int 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
*/
@@ -294,7 +294,7 @@ static int anim_set_end_frames_poll(bContext *C)
return true;
}
}
-
+
CTX_wm_operator_poll_msg_set(C, "Expected an animation area to be active");
return false;
}
@@ -314,16 +314,16 @@ static int anim_set_sfra_exec(bContext *C, wmOperator *UNUSED(op))
scene->r.psfra = frame;
else
scene->r.sfra = 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);
-
+
return OPERATOR_FINISHED;
}
@@ -332,15 +332,15 @@ 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 start frame";
-
+ 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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
+}
static int anim_set_efra_exec(bContext *C, wmOperator *UNUSED(op))
@@ -365,9 +365,9 @@ static int anim_set_efra_exec(bContext *C, wmOperator *UNUSED(op))
else
scene->r.sfra = frame;
}
-
+
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
-
+
return OPERATOR_FINISHED;
}
@@ -376,12 +376,12 @@ 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 end frame";
-
+ 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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -394,31 +394,31 @@ static int previewrange_define_exec(bContext *C, wmOperator *op)
ARegion *ar = CTX_wm_region(C);
float sfra, efra;
rcti rect;
-
+
/* get min/max values from border 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
+
+ /* 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)
{
@@ -426,18 +426,18 @@ static void ANIM_OT_previewrange_set(wmOperatorType *ot)
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_border_invoke;
ot->exec = previewrange_define_exec;
ot->modal = WM_gesture_border_modal;
ot->cancel = WM_gesture_border_cancel;
-
+
ot->poll = ED_operator_animview_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* rna */
/* used to define frame range.
*
@@ -452,23 +452,23 @@ static int previewrange_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
ScrArea *curarea = CTX_wm_area(C);
-
+
/* 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;
-
+
ED_area_tag_redraw(curarea);
-
+
/* send notifiers */
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
-
+
return OPERATOR_FINISHED;
-}
+}
static void ANIM_OT_previewrange_clear(wmOperatorType *ot)
{
@@ -476,12 +476,12 @@ static void ANIM_OT_previewrange_clear(wmOperatorType *ot)
ot->name = "Clear Preview Range";
ot->idname = "ANIM_OT_previewrange_clear";
ot->description = "Clear Preview Range";
-
+
/* api callbacks */
ot->exec = previewrange_clear_exec;
-
+
ot->poll = ED_operator_animview_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -492,13 +492,13 @@ 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);
@@ -508,22 +508,23 @@ void ED_operatortypes_anim(void)
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_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);
}
@@ -531,14 +532,14 @@ void ED_keymap_anim(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_find(keyconf, "Animation", 0, 0);
wmKeyMapItem *kmi;
-
+
/* frame management */
/* NOTE: 'ACTIONMOUSE' not 'LEFTMOUSE', as user may have swapped mouse-buttons */
WM_keymap_add_item(keymap, "ANIM_OT_change_frame", ACTIONMOUSE, KM_PRESS, 0, 0);
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", TKEY, KM_PRESS, KM_CTRL, 0);
RNA_string_set(kmi->ptr, "data_path", "space_data.show_seconds");
-
+
/* preview range */
WM_keymap_verify_item(keymap, "ANIM_OT_previewrange_set", PKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "ANIM_OT_previewrange_clear", PKEY, KM_PRESS, KM_ALT, 0);
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index 2d04f73c4ac..f303be0dd76 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -29,7 +29,7 @@
* \ingroup edanimation
*/
-
+
#include <stdio.h>
#include <string.h>
@@ -41,6 +41,7 @@
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
+#include "DNA_space_types.h"
#include "DNA_texture_types.h"
#include "BKE_animsys.h"
@@ -67,10 +68,10 @@
/* ************************************************** */
/* Animation Data Validation */
-/* Get (or add relevant data to be able to do so) F-Curve from the driver stack,
+/* Get (or add relevant data to be able to do so) F-Curve from the driver stack,
* for the given Animation Data block. This assumes that all the destinations are valid.
- *
- * - add: 0 - don't add anything if not found,
+ *
+ * - add: 0 - don't add anything if not found,
* 1 - add new Driver FCurve (with keyframes for visual tweaking),
* 2 - add new Driver FCurve (with generator, for script backwards compatibility)
* -1 - add new Driver FCurve without driver stuff (for pasting)
@@ -79,11 +80,11 @@ FCurve *verify_driver_fcurve(ID *id, const char rna_path[], const int array_inde
{
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))
@@ -92,33 +93,32 @@ FCurve *verify_driver_fcurve(ID *id, const char rna_path[], const int array_inde
/* 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
+
+ /* 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");
- fcu->driver->flag |= DRIVER_FLAG_SHOWDEBUG;
-
+
/* F-Modifier or Keyframes? */
// FIXME: replace these magic numbers with defines
if (add == 2) {
@@ -129,27 +129,27 @@ FCurve *verify_driver_fcurve(ID *id, const char rna_path[], const int array_inde
add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR, fcu);
}
else {
- /* add 2 keyframes so that user has something to work with
+ /* 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;
}
@@ -169,17 +169,17 @@ static int add_driver_with_target(
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
@@ -187,7 +187,7 @@ static int add_driver_with_target(
* 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) &&
+ 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
@@ -207,7 +207,7 @@ static int add_driver_with_target(
/* 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...)
@@ -216,25 +216,25 @@ static int add_driver_with_target(
* 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) &&
+
+ 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)
@@ -267,11 +267,11 @@ static int add_driver_with_target(
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);
@@ -281,7 +281,7 @@ static int add_driver_with_target(
}
}
}
-
+
/* set the done status */
return (fcu != NULL);
}
@@ -298,35 +298,35 @@ static int add_driver_with_target(
* - mapping_type: eCreateDriver_MappingTypes
*/
int ANIM_add_driver_with_target(
- ReportList *reports,
+ 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,
+ 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) ||
+ 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 */
@@ -334,35 +334,35 @@ int ANIM_add_driver_with_target(
/* 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;
}
@@ -373,22 +373,22 @@ int ANIM_add_driver_with_target(
* 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)
-{
+{
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,
+ 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);
@@ -396,56 +396,67 @@ int ANIM_add_driver(ReportList *reports, ID *id, const char rna_path[], int arra
}
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
+
+ /* 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_strncpy(expression, (val) ? "True" : "False", maxlen);
+
+ 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, "%d", val);
+
+ 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, "%.3f", fval);
+
+ 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
+
+ /* 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) {
@@ -456,11 +467,11 @@ int ANIM_add_driver(ReportList *reports, ID *id, const char rna_path[], int arra
driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN);
}
}
-
+
/* set the done status */
done_tot += (fcu != NULL);
}
-
+
/* done */
return done_tot;
}
@@ -473,29 +484,29 @@ bool ANIM_remove_driver(ReportList *UNUSED(reports), ID *id, const char rna_path
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
+ /* 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
*/
@@ -503,7 +514,7 @@ bool ANIM_remove_driver(ReportList *UNUSED(reports), ID *id, const char rna_path
if (fcu) {
BLI_remlink(&adt->drivers, fcu);
free_fcurve(fcu);
-
+
success = true;
}
}
@@ -543,7 +554,7 @@ bool ANIM_copy_driver(ReportList *reports, ID *id, const char rna_path[], int ar
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) {
@@ -552,13 +563,13 @@ bool ANIM_copy_driver(ReportList *reports, ID *id, const char rna_path[], int ar
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
@@ -566,31 +577,31 @@ bool ANIM_copy_driver(ReportList *reports, ID *id, const char rna_path[], int ar
*/
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
+ * 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))
-{
+{
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) {
@@ -599,35 +610,35 @@ bool ANIM_paste_driver(ReportList *reports, ID *id, const char rna_path[], int a
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
+ /* 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);
}
@@ -644,14 +655,14 @@ 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);
}
@@ -671,18 +682,18 @@ bool ANIM_driver_vars_copy(ReportList *reports, FCurve *fcu)
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;
}
-
+
/* clear buffer */
ANIM_driver_vars_copybuf_free();
-
+
/* copy over the variables */
driver_variables_copy(&driver_vars_copybuf, &fcu->driver->variables);
-
+
return (BLI_listbase_is_empty(&driver_vars_copybuf) == false);
}
@@ -691,55 +702,55 @@ 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;
}
-
+
#ifdef WITH_PYTHON
/* since driver variables are cached, the expression needs re-compiling too */
if (driver->type == DRIVER_TYPE_PYTHON)
driver->flag |= DRIVER_FLAG_RENAMEVAR;
#endif
-
+
return true;
}
@@ -756,10 +767,10 @@ EnumPropertyItem prop_driver_create_mapping_types[] = {
"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)",
@@ -772,21 +783,21 @@ static const EnumPropertyItem *driver_mapping_type_itemsf(bContext *C, PointerRN
{
EnumPropertyItem *input = prop_driver_create_mapping_types;
EnumPropertyItem *item = NULL;
-
+
PointerRNA ptr = {{NULL}};
PropertyRNA *prop = NULL;
int index;
-
+
int totitem = 0;
-
+
if (!C) /* needed for docs */
return prop_driver_create_mapping_types;
-
+
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);
-
+
while (input->identifier) {
if (ELEM(input->value, CREATEDRIVER_MAPPING_1_1, CREATEDRIVER_MAPPING_NONE) || (is_array)) {
RNA_enum_item_add(&item, &totitem, input);
@@ -798,22 +809,22 @@ static const EnumPropertyItem *driver_mapping_type_itemsf(bContext *C, PointerRN
/* We need at least this one! */
RNA_enum_items_add_value(&item, &totitem, input, CREATEDRIVER_MAPPING_NONE);
}
-
+
RNA_enum_item_end(&item, &totitem);
-
+
*r_free = true;
return item;
}
-/* Add Driver Button Operator ------------------------ */
+/* Add Driver (With Menu) Button Operator ------------------------ */
static int add_driver_button_poll(bContext *C)
{
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));
@@ -826,28 +837,28 @@ static int add_driver_button_none(bContext *C, wmOperator *op, short mapping_typ
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 {
@@ -855,7 +866,7 @@ static int add_driver_button_none(bContext *C, wmOperator *op, short mapping_typ
}
}
-static int add_driver_button_exec(bContext *C, wmOperator *op)
+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)) {
@@ -865,22 +876,22 @@ static int add_driver_button_exec(bContext *C, wmOperator *op)
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_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+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_exec(C, op);
+ return add_driver_button_menu_exec(C, op);
}
else {
/* Show menu */
@@ -890,30 +901,80 @@ static int add_driver_button_invoke(bContext *C, wmOperator *op, const wmEvent *
}
}
-void ANIM_OT_driver_button_add(wmOperatorType *ot)
+static void UNUSED_FUNCTION(ANIM_OT_driver_button_add_menu)(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Add Driver";
- ot->idname = "ANIM_OT_driver_button_add";
+ 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 */
- /* NOTE: No exec, as we need all these to use the current context info
- * (especially the eyedropper, which is interactive)
- */
- ot->invoke = add_driver_button_invoke;
- ot->exec = add_driver_button_exec;
+ 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_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, SPACE_IPO, RGN_TYPE_UI, "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;
+}
+
/* Remove Driver Button Operator ------------------------ */
static int remove_driver_button_exec(bContext *C, wmOperator *op)
@@ -923,30 +984,30 @@ static int remove_driver_button_exec(bContext *C, wmOperator *op)
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);
-
+
if (all)
index = -1;
-
+
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);
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 (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
@@ -956,11 +1017,11 @@ void ANIM_OT_driver_button_remove(wmOperatorType *ot)
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;
+ 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;
@@ -968,6 +1029,39 @@ void ANIM_OT_driver_button_remove(wmOperatorType *ot)
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;
+
+ /* 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, SPACE_IPO, RGN_TYPE_UI, "GRAPH_PT_drivers_popover", true, op->reports);
+ }
+
+ 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;
+}
+
/* Copy Driver Button Operator ------------------------ */
static int copy_driver_button_exec(bContext *C, wmOperator *op)
@@ -976,23 +1070,23 @@ static int copy_driver_button_exec(bContext *C, wmOperator *op)
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);
-
+
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);
-
+
UI_context_update_anim_flag(C);
-
+
MEM_freeN(path);
}
}
-
+
/* since we're just copying, we don't really need to do anything else...*/
return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
@@ -1003,11 +1097,11 @@ void ANIM_OT_copy_driver_button(wmOperatorType *ot)
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;
+ 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;
}
@@ -1020,28 +1114,28 @@ static int paste_driver_button_exec(bContext *C, wmOperator *op)
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);
-
+
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);
-
+
UI_context_update_anim_flag(C);
-
+
DEG_relations_tag_update(CTX_data_main(C));
DEG_id_tag_update(ptr.id.data, OB_RECALC_OB | OB_RECALC_DATA);
-
+
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); // XXX
-
+
MEM_freeN(path);
}
}
-
+
/* since we're just copying, we don't really need to do anything else...*/
return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
@@ -1052,11 +1146,11 @@ void ANIM_OT_paste_driver_button(wmOperatorType *ot)
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;
+ 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;
}
diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c
index 8106be79521..951dcc2dddf 100644
--- a/source/blender/editors/animation/fmodifier_ui.c
+++ b/source/blender/editors/animation/fmodifier_ui.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation, Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
@@ -30,14 +30,14 @@
/* User-Interface Stuff for F-Modifiers:
- * This file defines the (C-Coded) templates + editing callbacks needed
+ * 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,
* and NLA-Strips in the NLA Editor.
*
* Copy/Paste Buffer for F-Modifiers:
- * For now, this is also defined in this file so that it can be shared between the
+ * For now, this is also defined in this file so that it can be shared between the
*/
-
+
#include <string.h>
#include "DNA_anim_types.h"
@@ -79,7 +79,7 @@ static void validate_fmodifier_cb(bContext *UNUSED(C), void *fcm_v, void *UNUSED
{
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);
@@ -90,19 +90,19 @@ static void delete_fmodifier_cb(bContext *C, void *fmods_v, void *fcm_v)
{
ListBase *modifiers = (ListBase *)fmods_v;
FModifier *fcm = (FModifier *)fcm_v;
-
+
/* remove the given F-Modifier from the active modifier-stack */
remove_fmodifier(modifiers, fcm);
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
+ // 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);
}
/* --------------- */
-
+
/* draw settings for generator modifier */
static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, short width)
{
@@ -112,20 +112,20 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s
uiBut *but;
PointerRNA ptr;
short bwidth = width - 1.5 * UI_UNIT_X; /* max button width */
-
+
/* init the RNA-pointer */
RNA_pointer_create(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 */
@@ -135,7 +135,7 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s
char xval[32];
unsigned int i;
int maxXWidth;
-
+
/* draw polynomial order selector */
row = uiLayoutRow(layout, false);
block = uiLayoutGetBlock(row);
@@ -143,8 +143,8 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s
&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);
@@ -155,11 +155,11 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s
/* 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... */
@@ -167,11 +167,11 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s
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));
@@ -180,10 +180,10 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s
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);
@@ -195,12 +195,12 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s
}
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);
@@ -208,12 +208,12 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s
&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 */
@@ -223,25 +223,25 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s
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
+ else
uiDefBut(block, UI_BTYPE_LABEL, 1, ") ", 0, 0, 2 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
}
break;
@@ -256,10 +256,10 @@ static void draw_modifier__fn_generator(uiLayout *layout, ID *id, FModifier *fcm
{
uiLayout *col;
PointerRNA ptr;
-
+
/* init the RNA-pointer */
RNA_pointer_create(id, &RNA_FModifierFunctionGenerator, fcm, &ptr);
-
+
/* add the settings */
col = uiLayoutColumn(layout, true);
uiItemR(col, &ptr, "function_type", 0, "", ICON_NONE);
@@ -279,21 +279,21 @@ static void draw_modifier__cycles(uiLayout *layout, ID *id, FModifier *fcm, shor
{
uiLayout *split, *col;
PointerRNA ptr;
-
+
/* init the RNA-pointer */
RNA_pointer_create(id, &RNA_FModifierCycles, fcm, &ptr);
-
- /* split into 2 columns
+
+ /* 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);
@@ -308,22 +308,22 @@ static void draw_modifier__noise(uiLayout *layout, ID *id, FModifier *fcm, short
{
uiLayout *split, *col;
PointerRNA ptr;
-
+
/* init the RNA-pointer */
RNA_pointer_create(id, &RNA_FModifierNoise, fcm, &ptr);
-
+
/* blending mode */
uiItemR(layout, &ptr, "blend_type", 0, NULL, ICON_NONE);
-
+
/* 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 2 */
col = uiLayoutColumn(split, false);
uiItemR(col, &ptr, "phase", 0, NULL, ICON_NONE);
@@ -337,46 +337,46 @@ static void fmod_envelope_addpoint_cb(bContext *C, void *fcm_dv, void *UNUSED(ar
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)
+ 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;
}
}
@@ -388,7 +388,7 @@ static void fmod_envelope_deletepoint_cb(bContext *UNUSED(C), void *fcm_dv, void
FMod_Envelope *env = (FMod_Envelope *)fcm_dv;
FCM_EnvelopeData *fedn;
int index = GET_INT_FROM_POINTER(ind_v);
-
+
/* check that no data exists for the current frame... */
if (env->totvert > 1) {
/* allocate a new smaller array */
@@ -396,7 +396,7 @@ static void fmod_envelope_deletepoint_cb(bContext *UNUSED(C), void *fcm_dv, void
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;
@@ -422,10 +422,10 @@ static void draw_modifier__envelope(uiLayout *layout, ID *id, FModifier *fcm, sh
uiBut *but;
PointerRNA ptr;
int i;
-
+
/* init the RNA-pointer */
RNA_pointer_create(id, &RNA_FModifierEnvelope, fcm, &ptr);
-
+
/* general settings */
col = uiLayoutColumn(layout, true);
uiItemL(col, IFACE_("Envelope:"), ICON_NONE);
@@ -440,24 +440,24 @@ static void draw_modifier__envelope(uiLayout *layout, ID *id, FModifier *fcm, sh
* 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,
@@ -477,40 +477,40 @@ static void draw_modifier__limits(uiLayout *layout, ID *id, FModifier *fcm, shor
{
uiLayout *split, *col /* , *row */ /* UNUSED */;
PointerRNA ptr;
-
+
/* init the RNA-pointer */
RNA_pointer_create(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);
@@ -525,27 +525,27 @@ static void draw_modifier__stepped(uiLayout *layout, ID *id, FModifier *fcm, sho
{
uiLayout *col, *sub;
PointerRNA ptr;
-
+
/* init the RNA-pointer */
RNA_pointer_create(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 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);
-
+
/* 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);
@@ -561,125 +561,125 @@ void ANIM_uiTemplate_fmodifier_draw(uiLayout *layout, ID *id, ListBase *modifier
uiBut *but;
short width = 314;
PointerRNA ptr;
-
+
/* init the RNA-pointer */
RNA_pointer_create(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"));
UI_but_func_set(but, delete_fmodifier_cb, modifiers, 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, id, fcm, width);
break;
-
+
case FMODIFIER_TYPE_FN_GENERATOR: /* Built-In Function Generator */
draw_modifier__fn_generator(box, id, fcm, width);
break;
-
+
case FMODIFIER_TYPE_CYCLES: /* Cycles */
draw_modifier__cycles(box, id, fcm, width);
break;
-
+
case FMODIFIER_TYPE_ENVELOPE: /* Envelope */
draw_modifier__envelope(box, id, fcm, width);
break;
-
+
case FMODIFIER_TYPE_LIMITS: /* Limits */
draw_modifier__limits(box, id, fcm, width);
break;
-
+
case FMODIFIER_TYPE_NOISE: /* Noise */
draw_modifier__noise(box, id, fcm, width);
break;
-
+
case FMODIFIER_TYPE_STEPPED: /* Stepped */
draw_modifier__stepped(box, 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);
@@ -710,15 +710,15 @@ 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);
@@ -728,44 +728,44 @@ bool ANIM_fmodifiers_copy_to_buf(ListBase *modifiers, bool active)
}
else
copy_fmodifiers(&fmodifier_copypaste_buf, modifiers);
-
+
/* did we succeed? */
return ok;
}
-/* 'Paste' the F-Modifier(s) from the buffer to the specified list
- * - replace: free all the existing modifiers to leave only the pasted ones
+/* 'Paste' the F-Modifier(s) from the buffer to the specified list
+ * - replace: free all the existing modifiers to leave only the pasted ones
*/
bool ANIM_fmodifiers_paste_from_buf(ListBase *modifiers, bool replace, FCurve *curve)
{
FModifier *fcm;
bool ok = false;
-
+
/* sanity checks */
if (modifiers == NULL)
return 0;
-
+
bool was_cyclic = curve && BKE_fcurve_is_cyclic(curve);
/* 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);
fcmN->curve = curve;
-
+
/* 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;
}
-
+
/* adding or removing the Cycles modifier requires an update to handles */
if (curve && BKE_fcurve_is_cyclic(curve) != was_cyclic)
calchandles_fcurve(curve);
diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
index 98ad2041018..fcccf07190b 100644
--- a/source/blender/editors/animation/keyframes_draw.c
+++ b/source/blender/editors/animation/keyframes_draw.c
@@ -54,6 +54,7 @@
#include "GPU_draw.h"
#include "GPU_immediate.h"
+#include "GPU_state.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -72,10 +73,10 @@ short compare_ak_cfraPtr(void *node, void *data)
ActKeyColumn *ak = (ActKeyColumn *)node;
const float *cframe = data;
float val = *cframe;
-
+
if (IS_EQT(val, ak->cfra, BEZT_BINARYSEARCH_THRESH))
return 0;
-
+
if (val < ak->cfra)
return -1;
else if (val > ak->cfra)
@@ -91,7 +92,7 @@ static short compare_ak_bezt(void *node, void *data)
{
ActKeyColumn *ak = (ActKeyColumn *)node;
BezTriple *bezt = (BezTriple *)data;
-
+
if (bezt->vec[1][0] < ak->cfra)
return -1;
else if (bezt->vec[1][0] > ak->cfra)
@@ -105,15 +106,15 @@ static DLRBT_Node *nalloc_ak_bezt(void *data)
{
ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
BezTriple *bezt = (BezTriple *)data;
-
+
/* 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);
-
+
/* set 'modified', since this is used to identify long keyframes */
ak->modified = 1;
-
+
return (DLRBT_Node *)ak;
}
@@ -122,11 +123,11 @@ static void nupdate_ak_bezt(void *node, void *data)
{
ActKeyColumn *ak = (ActKeyColumn *)node;
BezTriple *bezt = (BezTriple *)data;
-
+
/* set selection status and 'touched' status */
if (BEZT_ISSEL_ANY(bezt)) ak->sel = SELECT;
ak->modified += 1;
-
+
/* 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;
@@ -139,7 +140,7 @@ static short compare_ak_gpframe(void *node, void *data)
{
ActKeyColumn *ak = (ActKeyColumn *)node;
bGPDframe *gpf = (bGPDframe *)data;
-
+
if (gpf->framenum < ak->cfra)
return -1;
else if (gpf->framenum > ak->cfra)
@@ -153,15 +154,15 @@ static DLRBT_Node *nalloc_ak_gpframe(void *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;
-
+
/* set 'modified', since this is used to identify long keyframes */
ak->modified = 1;
-
+
return (DLRBT_Node *)ak;
}
@@ -170,11 +171,11 @@ static void nupdate_ak_gpframe(void *node, void *data)
{
ActKeyColumn *ak = (ActKeyColumn *)node;
bGPDframe *gpf = (bGPDframe *)data;
-
+
/* set selection status and 'touched' status */
if (gpf->flag & GP_FRAME_SELECT) ak->sel = SELECT;
ak->modified += 1;
-
+
/* 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;
@@ -262,7 +263,7 @@ short compare_ab_cfraPtr(void *node, void *data)
ActKeyBlock *ab = (ActKeyBlock *)node;
const float *cframe = data;
float val = *cframe;
-
+
if (val < ab->start)
return -1;
else if (val > ab->start)
@@ -277,17 +278,17 @@ short compare_ab_cfraPtr(void *node, void *data)
static ActKeyBlock *bezts_to_new_actkeyblock(BezTriple *prev, BezTriple *beztn)
{
ActKeyBlock *ab = MEM_callocN(sizeof(ActKeyBlock), "ActKeyBlock");
-
+
ab->start = prev->vec[1][0];
ab->end = beztn->vec[1][0];
ab->val = beztn->vec[1][1];
-
+
ab->sel = (BEZT_ISSEL_ANY(prev) || BEZT_ISSEL_ANY(beztn)) ? SELECT : 0;
ab->modified = 1;
-
+
if (BEZKEYTYPE(beztn) == BEZT_KEYTYPE_MOVEHOLD)
ab->flag |= ACTKEYBLOCK_FLAG_MOVING_HOLD;
-
+
return ab;
}
@@ -295,25 +296,25 @@ static void add_bezt_to_keyblocks_list(DLRBT_Tree *blocks, BezTriple *first_bezt
{
ActKeyBlock *new_ab = NULL;
BezTriple *prev = NULL;
-
+
/* get the BezTriple immediately before the given one which has the same value */
if (beztn != first_bezt) {
- /* XXX: Unless I'm overlooking some details from the past, this should be sufficient?
+ /* XXX: Unless I'm overlooking some details from the past, this should be sufficient?
* The old code did some elaborate stuff trying to find keyframe columns for
* the given BezTriple, then step backwards to the column before that, and find
* an appropriate BezTriple with matching values there. Maybe that was warranted
- * in the past, but now, that list is only ever filled with keyframes from the
+ * in the past, but now, that list is only ever filled with keyframes from the
* current FCurve.
*
* -- Aligorith (20140415)
*/
prev = beztn - 1;
}
-
-
+
+
/* check if block needed */
if (prev == NULL) return;
-
+
if (BEZKEYTYPE(beztn) == BEZT_KEYTYPE_MOVEHOLD) {
/* Animator tagged a "moving hold"
* - Previous key must also be tagged as a moving hold, otherwise
@@ -329,11 +330,11 @@ static void add_bezt_to_keyblocks_list(DLRBT_Tree *blocks, BezTriple *first_bezt
* - Handles which control that section of the curve must be constant
*/
if (IS_EQF(beztn->vec[1][1], prev->vec[1][1]) == 0) return;
-
+
if (IS_EQF(beztn->vec[1][1], beztn->vec[0][1]) == 0) return;
if (IS_EQF(prev->vec[1][1], prev->vec[2][1]) == 0) return;
}
-
+
/* if there are no blocks already, just add as root */
if (blocks->root == NULL) {
/* just add this as the root, then call the tree-balancing functions to validate */
@@ -342,7 +343,7 @@ static void add_bezt_to_keyblocks_list(DLRBT_Tree *blocks, BezTriple *first_bezt
}
else {
ActKeyBlock *ab, *abn = NULL;
-
+
/* try to find a keyblock that starts on the previous beztriple, and add a new one if none start there
* Note: we perform a tree traversal here NOT a standard linked-list traversal...
* Note: we can't search from end to try to optimize this as it causes errors there's
@@ -353,32 +354,32 @@ static void add_bezt_to_keyblocks_list(DLRBT_Tree *blocks, BezTriple *first_bezt
// A|------------------------------------------------|A
// A|----|A|---|A|-----------------------------------|A
for (ab = blocks->root; ab; ab = abn) {
- /* check if this is a match, or whether we go left or right
+ /* check if this is a match, or whether we go left or right
* NOTE: we now use a float threshold to prevent precision errors causing problems with summaries
*/
if (IS_EQT(ab->start, prev->vec[1][0], BEZT_BINARYSEARCH_THRESH)) {
/* set selection status and 'touched' status */
if (BEZT_ISSEL_ANY(beztn))
ab->sel = SELECT;
-
+
/* XXX: only when the first one was a moving hold? */
if (BEZKEYTYPE(beztn) == BEZT_KEYTYPE_MOVEHOLD)
ab->flag |= ACTKEYBLOCK_FLAG_MOVING_HOLD;
-
+
ab->modified++;
-
+
/* done... no need to insert */
return;
}
else {
ActKeyBlock **abnp = NULL; /* branch to go down - used to hook new blocks to parents */
-
+
/* check if go left or right, but if not available, add new node */
- if (ab->start < prev->vec[1][0])
+ if (ab->start < prev->vec[1][0])
abnp = &ab->right;
else
abnp = &ab->left;
-
+
/* if this does not exist, add a new node, otherwise continue... */
if (*abnp == NULL) {
/* add a new node representing this, and attach it to the relevant place */
@@ -392,7 +393,7 @@ static void add_bezt_to_keyblocks_list(DLRBT_Tree *blocks, BezTriple *first_bezt
}
}
}
-
+
/* now, balance the tree taking into account this newly added node */
BLI_dlrbTree_insert(blocks, (DLRBT_Node *)new_ab);
}
@@ -405,13 +406,13 @@ static void set_touched_actkeycolumn(ActKeyColumn *ak)
/* sanity check */
if (ak == NULL)
return;
-
+
/* deal with self first */
if (ak->modified) {
ak->modified = 0;
ak->totcurve++;
}
-
+
/* children */
set_touched_actkeycolumn(ak->left);
set_touched_actkeycolumn(ak->right);
@@ -423,13 +424,13 @@ static void set_touched_actkeyblock(ActKeyBlock *ab)
/* sanity check */
if (ab == NULL)
return;
-
+
/* deal with self first */
if (ab->modified) {
ab->modified = 0;
ab->totcurve++;
}
-
+
/* children */
set_touched_actkeyblock(ab->left);
set_touched_actkeyblock(ab->right);
@@ -442,22 +443,22 @@ bool actkeyblock_is_valid(ActKeyBlock *ab, DLRBT_Tree *keys)
{
ActKeyColumn *ak;
short startCurves, endCurves, totCurves;
-
+
/* check that block is valid */
if (ab == NULL)
return 0;
-
+
/* find out how many curves occur at each keyframe */
ak = (ActKeyColumn *)BLI_dlrbTree_search_exact(keys, compare_ak_cfraPtr, &ab->start);
startCurves = (ak) ? ak->totcurve : 0;
-
+
ak = (ActKeyColumn *)BLI_dlrbTree_search_exact(keys, compare_ak_cfraPtr, &ab->end);
endCurves = (ak) ? ak->totcurve : 0;
-
+
/* only draw keyblock if it appears in at all of the keyframes at lowest end */
- if (!startCurves && !endCurves)
+ if (!startCurves && !endCurves)
return 0;
-
+
totCurves = (startCurves > endCurves) ? endCurves : startCurves;
return (ab->totcurve >= totCurves);
}
@@ -478,19 +479,19 @@ void draw_keyframe_shape(float x, float y, float size, bool sel, short key_type,
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;
}
@@ -521,8 +522,8 @@ void draw_keyframe_shape(float x, float y, float size, bool sel, short key_type,
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
+
+ /* 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;
@@ -560,25 +561,25 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa
{
const float icon_sz = U.widget_unit * 0.5f * yscale_fac;
const float half_icon_sz = 0.5f * icon_sz;
-
- glEnable(GL_BLEND);
-
+
+ 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;
-
+
/* draw keyblocks */
if (blocks) {
float sel_color[4], unsel_color[4];
float sel_mhcol[4], unsel_mhcol[4];
-
+
/* cache colours first */
UI_GetThemeColor4fv(TH_STRIP_SELECT, sel_color);
UI_GetThemeColor4fv(TH_STRIP, unsel_color);
-
+
sel_color[3] *= alpha;
unsel_color[3] *= alpha;
-
+
copy_v4_v4(sel_mhcol, sel_color);
sel_mhcol[3] *= 0.8f;
copy_v4_v4(unsel_mhcol, unsel_color);
@@ -618,7 +619,7 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa
immUnbindProgram();
}
}
-
+
if (keys) {
/* count keys */
unsigned int key_ct = 0;
@@ -654,7 +655,7 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa
}
}
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
/* *************************** Channel Drawing Funcs *************************** */
@@ -662,17 +663,17 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa
void draw_summary_channel(View2D *v2d, bAnimContext *ac, float ypos, float yscale_fac)
{
DLRBT_Tree keys, blocks;
-
+
BLI_dlrbTree_init(&keys);
BLI_dlrbTree_init(&blocks);
-
+
summary_to_keylist(ac, &keys, &blocks);
-
+
BLI_dlrbTree_linkedlist_sync(&keys);
BLI_dlrbTree_linkedlist_sync(&blocks);
-
+
draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, false);
-
+
BLI_dlrbTree_free(&keys);
BLI_dlrbTree_free(&blocks);
}
@@ -680,17 +681,17 @@ void draw_summary_channel(View2D *v2d, bAnimContext *ac, float ypos, float yscal
void draw_scene_channel(View2D *v2d, bDopeSheet *ads, Scene *sce, float ypos, float yscale_fac)
{
DLRBT_Tree keys, blocks;
-
+
BLI_dlrbTree_init(&keys);
BLI_dlrbTree_init(&blocks);
-
+
scene_to_keylist(ads, sce, &keys, &blocks);
-
+
BLI_dlrbTree_linkedlist_sync(&keys);
BLI_dlrbTree_linkedlist_sync(&blocks);
-
+
draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, false);
-
+
BLI_dlrbTree_free(&keys);
BLI_dlrbTree_free(&blocks);
}
@@ -698,17 +699,17 @@ void draw_scene_channel(View2D *v2d, bDopeSheet *ads, Scene *sce, float ypos, fl
void draw_object_channel(View2D *v2d, bDopeSheet *ads, Object *ob, float ypos, float yscale_fac)
{
DLRBT_Tree keys, blocks;
-
+
BLI_dlrbTree_init(&keys);
BLI_dlrbTree_init(&blocks);
-
+
ob_to_keylist(ads, ob, &keys, &blocks);
-
+
BLI_dlrbTree_linkedlist_sync(&keys);
BLI_dlrbTree_linkedlist_sync(&blocks);
-
+
draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, false);
-
+
BLI_dlrbTree_free(&keys);
BLI_dlrbTree_free(&blocks);
}
@@ -716,21 +717,21 @@ void draw_object_channel(View2D *v2d, bDopeSheet *ads, Object *ob, float ypos, f
void draw_fcurve_channel(View2D *v2d, AnimData *adt, FCurve *fcu, float ypos, float yscale_fac)
{
DLRBT_Tree keys, blocks;
-
+
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(&blocks);
-
+
fcurve_to_keylist(adt, fcu, &keys, &blocks);
-
+
BLI_dlrbTree_linkedlist_sync(&keys);
BLI_dlrbTree_linkedlist_sync(&blocks);
-
+
draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, locked);
-
+
BLI_dlrbTree_free(&keys);
BLI_dlrbTree_free(&blocks);
}
@@ -738,20 +739,20 @@ void draw_fcurve_channel(View2D *v2d, AnimData *adt, FCurve *fcu, float ypos, fl
void draw_agroup_channel(View2D *v2d, AnimData *adt, bActionGroup *agrp, float ypos, float yscale_fac)
{
DLRBT_Tree keys, blocks;
-
+
bool locked = (agrp->flag & AGRP_PROTECTED) ||
((adt && adt->action) && ID_IS_LINKED(adt->action));
-
+
BLI_dlrbTree_init(&keys);
BLI_dlrbTree_init(&blocks);
-
+
agroup_to_keylist(adt, agrp, &keys, &blocks);
-
+
BLI_dlrbTree_linkedlist_sync(&keys);
BLI_dlrbTree_linkedlist_sync(&blocks);
-
+
draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, locked);
-
+
BLI_dlrbTree_free(&keys);
BLI_dlrbTree_free(&blocks);
}
@@ -759,19 +760,19 @@ void draw_agroup_channel(View2D *v2d, AnimData *adt, bActionGroup *agrp, float y
void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos, float yscale_fac)
{
DLRBT_Tree keys, blocks;
-
+
bool locked = (act && ID_IS_LINKED(act));
-
+
BLI_dlrbTree_init(&keys);
BLI_dlrbTree_init(&blocks);
-
+
action_to_keylist(adt, act, &keys, &blocks);
-
+
BLI_dlrbTree_linkedlist_sync(&keys);
BLI_dlrbTree_linkedlist_sync(&blocks);
-
+
draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, locked);
-
+
BLI_dlrbTree_free(&keys);
BLI_dlrbTree_free(&blocks);
}
@@ -779,49 +780,49 @@ void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos, f
void draw_gpencil_channel(View2D *v2d, bDopeSheet *ads, bGPdata *gpd, float ypos, float yscale_fac)
{
DLRBT_Tree keys;
-
+
BLI_dlrbTree_init(&keys);
-
+
gpencil_to_keylist(ads, gpd, &keys);
-
+
BLI_dlrbTree_linkedlist_sync(&keys);
-
+
draw_keylist(v2d, &keys, NULL, ypos, yscale_fac, false);
-
+
BLI_dlrbTree_free(&keys);
}
void draw_gpl_channel(View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos, float yscale_fac)
{
DLRBT_Tree keys;
-
+
bool locked = (gpl->flag & GP_LAYER_LOCKED) != 0;
-
+
BLI_dlrbTree_init(&keys);
-
+
gpl_to_keylist(ads, gpl, &keys);
-
+
BLI_dlrbTree_linkedlist_sync(&keys);
-
+
draw_keylist(v2d, &keys, NULL, ypos, yscale_fac, locked);
-
+
BLI_dlrbTree_free(&keys);
}
void draw_masklay_channel(View2D *v2d, bDopeSheet *ads, MaskLayer *masklay, float ypos, float yscale_fac)
{
DLRBT_Tree keys;
-
+
bool locked = (masklay->flag & MASK_LAYERFLAG_LOCKED) != 0;
-
+
BLI_dlrbTree_init(&keys);
-
+
mask_to_keylist(ads, masklay, &keys);
-
+
BLI_dlrbTree_linkedlist_sync(&keys);
-
+
draw_keylist(v2d, &keys, NULL, ypos, yscale_fac, locked);
-
+
BLI_dlrbTree_free(&keys);
}
@@ -833,11 +834,11 @@ void summary_to_keylist(bAnimContext *ac, DLRBT_Tree *keys, DLRBT_Tree *blocks)
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?
@@ -860,7 +861,7 @@ void summary_to_keylist(bAnimContext *ac, DLRBT_Tree *keys, DLRBT_Tree *blocks)
break;
}
}
-
+
ANIM_animdata_freelist(&anim_data);
}
}
@@ -871,66 +872,66 @@ void scene_to_keylist(bDopeSheet *ads, Scene *sce, DLRBT_Tree *keys, DLRBT_Tree
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
-
+
bAnimListElem dummychan = {NULL};
-
+
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;
-
+
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);
-
+
/* 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, blocks);
-
+
ANIM_animdata_freelist(&anim_data);
}
void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, DLRBT_Tree *blocks)
-{
+{
bAnimContext ac = {NULL};
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
-
+
bAnimListElem dummychan = {NULL};
Base dummybase = {NULL};
-
+
if (ob == NULL)
return;
-
+
/* 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;
-
+
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);
-
+
/* 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, blocks);
-
+
ANIM_animdata_freelist(&anim_data);
}
@@ -974,19 +975,19 @@ void fcurve_to_keylist(AnimData *adt, FCurve *fcu, DLRBT_Tree *keys, DLRBT_Tree
/* apply NLA-mapping (if applicable) */
if (adt)
ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
-
+
/* loop through beztriples, making ActKeysColumns and ActKeyBlocks */
for (v = 0, bezt = fcu->bezt; v < fcu->totvert; v++, bezt++) {
add_bezt_to_keycolumns_list(keys, bezt);
if (blocks) add_bezt_to_keyblocks_list(blocks, fcu->bezt, bezt);
}
-
+
/* update the number of curves that elements have appeared in */
if (keys)
set_touched_actkeycolumn(keys->root);
if (blocks)
set_touched_actkeyblock(blocks->root);
-
+
/* unapply NLA-mapping if applicable */
if (adt)
ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
@@ -1021,7 +1022,7 @@ void action_to_keylist(AnimData *adt, bAction *act, DLRBT_Tree *keys, DLRBT_Tree
void gpencil_to_keylist(bDopeSheet *ads, bGPdata *gpd, DLRBT_Tree *keys)
{
bGPDlayer *gpl;
-
+
if (gpd && keys) {
/* for now, just aggregate out all the frames, but only for visible layers */
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
@@ -1035,7 +1036,7 @@ void gpencil_to_keylist(bDopeSheet *ads, bGPdata *gpd, DLRBT_Tree *keys)
void gpl_to_keylist(bDopeSheet *UNUSED(ads), bGPDlayer *gpl, DLRBT_Tree *keys)
{
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)
@@ -1056,4 +1057,3 @@ void mask_to_keylist(bDopeSheet *UNUSED(ads), MaskLayer *masklay, DLRBT_Tree *ke
}
}
}
-
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
index 0ef6aa4bd4a..1bbfa6cc979 100644
--- a/source/blender/editors/animation/keyframes_edit.c
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -56,15 +56,15 @@
* ANIM_fcurve_keyframes_loop()
* which take the data they operate on, a few callbacks defining what operations to perform.
*
- * As operators which work on keyframes usually apply the same operation on all BezTriples in
- * every channel, the code has been optimized providing a set of functions which will get the
+ * As operators which work on keyframes usually apply the same operation on all BezTriples in
+ * every channel, the code has been optimized providing a set of functions which will get the
* appropriate bezier-modify function to set. These functions (ANIM_editkeyframes_*) will need
* to be called before getting any channels.
- *
+ *
* A set of 'validation' callbacks are provided for checking if a BezTriple should be operated on.
- * These should only be used when using a 'general' BezTriple editor (i.e. selection setters which
+ * These should only be used when using a 'general' BezTriple editor (i.e. selection setters which
* don't check existing selection status).
- *
+ *
* - Joshua Leung, Dec 2008
*/
@@ -73,11 +73,11 @@
/* --------------------------- Base Functions ------------------------------------ */
-/* This function is used to loop over BezTriples in the given F-Curve, applying a given
+/* This function is used to loop over BezTriples in the given F-Curve, applying a given
* 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)
+short ANIM_fcurve_keyframes_loop(KeyframeEditData *ked, FCurve *fcu, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
{
BezTriple *bezt;
short ok = 0;
@@ -96,7 +96,7 @@ short ANIM_fcurve_keyframes_loop(KeyframeEditData *ked, FCurve *fcu, KeyframeEdi
/* 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
+ /* 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) {
@@ -106,11 +106,11 @@ short ANIM_fcurve_keyframes_loop(KeyframeEditData *ked, FCurve *fcu, KeyframeEdi
ked->curIndex = i;
ked->curflags = 0;
}
-
+
/* Only operate on this BezTriple if it fullfills 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.
*/
@@ -121,7 +121,7 @@ short ANIM_fcurve_keyframes_loop(KeyframeEditData *ked, FCurve *fcu, KeyframeEdi
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.
*/
@@ -129,7 +129,7 @@ short ANIM_fcurve_keyframes_loop(KeyframeEditData *ked, FCurve *fcu, KeyframeEdi
}
}
}
-
+
/* unset the F-Curve from the editdata now that it's done */
if (ked) {
ked->fcu = NULL;
@@ -140,7 +140,7 @@ short ANIM_fcurve_keyframes_loop(KeyframeEditData *ked, FCurve *fcu, KeyframeEdi
/* if fcu_cb (F-Curve post-editing callback) has been specified then execute it */
if (fcu_cb)
fcu_cb(fcu);
-
+
/* done */
return 0;
}
@@ -151,17 +151,17 @@ short ANIM_fcurve_keyframes_loop(KeyframeEditData *ked, FCurve *fcu, KeyframeEdi
static short agrp_keyframes_loop(KeyframeEditData *ked, bActionGroup *agrp, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
{
FCurve *fcu;
-
+
/* 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;
}
-
+
return 0;
}
@@ -169,17 +169,17 @@ static short agrp_keyframes_loop(KeyframeEditData *ked, bActionGroup *agrp, Keyf
static short act_keyframes_loop(KeyframeEditData *ked, bAction *act, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
{
FCurve *fcu;
-
+
/* 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;
}
-
+
return 0;
}
@@ -191,29 +191,29 @@ static short ob_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, Object *o
bAnimListElem *ale;
int filter;
int ret = 0;
-
+
bAnimListElem dummychan = {NULL};
Base dummybase = {NULL};
-
+
if (ob == NULL)
return 0;
-
+
/* 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;
-
+
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);
-
+
/* 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)) {
@@ -221,9 +221,9 @@ static short ob_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, Object *o
break;
}
}
-
+
ANIM_animdata_freelist(&anim_data);
-
+
/* return return code - defaults to zero if nothing happened */
return ret;
}
@@ -236,26 +236,26 @@ static short scene_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, Scene
bAnimListElem *ale;
int filter;
int ret = 0;
-
+
bAnimListElem dummychan = {NULL};
-
+
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;
-
+
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);
-
+
/* 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)) {
@@ -263,9 +263,9 @@ static short scene_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, Scene
break;
}
}
-
+
ANIM_animdata_freelist(&anim_data);
-
+
/* return return code - defaults to zero if nothing happened */
return ret;
}
@@ -276,22 +276,22 @@ static short summary_keyframes_loop(KeyframeEditData *ked, bAnimContext *ac, Key
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:
{
@@ -301,19 +301,19 @@ static short summary_keyframes_loop(KeyframeEditData *ked, bAnimContext *ac, Key
*/
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;
@@ -325,13 +325,13 @@ static short summary_keyframes_loop(KeyframeEditData *ked, bAnimContext *ac, Key
break;
}
}
-
+
if (ret_code)
break;
}
-
+
ANIM_animdata_freelist(&anim_data);
-
+
return ret_code;
}
@@ -343,21 +343,21 @@ short ANIM_animchannel_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, bA
/* 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)
+
+ /* 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 */
@@ -365,7 +365,7 @@ short ANIM_animchannel_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, bA
case ALE_ALL: /* 'all' (DopeSheet summary) */
return summary_keyframes_loop(ked, (bAnimContext *)ale->data, key_ok, key_cb, fcu_cb);
}
-
+
return 0;
}
@@ -375,21 +375,21 @@ short ANIM_animchanneldata_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads
/* 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)
+
+ /* 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 */
@@ -397,7 +397,7 @@ short ANIM_animchanneldata_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads
case ALE_ALL: /* 'all' (DopeSheet summary) */
return summary_keyframes_loop(ked, (bAnimContext *)data, key_ok, key_cb, fcu_cb);
}
-
+
return 0;
}
@@ -411,20 +411,20 @@ void ANIM_editkeyframes_refresh(bAnimContext *ac)
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);
-
+
/* loop over F-Curves that are likely to have been edited, and check them */
for (ale = anim_data.first; ale; ale = ale->next) {
FCurve *fcu = ale->key_data;
-
+
/* make sure keyframes in F-Curve are all in order, and handles are in valid positions */
sort_time_fcurve(fcu);
calchandles_fcurve(fcu);
}
-
+
/* free temp data */
ANIM_animdata_freelist(&anim_data);
}
@@ -435,7 +435,7 @@ void ANIM_editkeyframes_refresh(bAnimContext *ac)
/* ------------------------ */
/* Some macros to make this easier... */
-/* run the given check on the 3 handles
+/* run the given check on the 3 handles
* - check should be a macro, which takes the handle index as its single arg, which it substitutes later
* - requires that a var, of type short, is named 'ok', and has been initialized to 0
*/
@@ -454,16 +454,16 @@ void ANIM_editkeyframes_refresh(bAnimContext *ac)
} (void)0
/* ------------------------ */
-
+
static short ok_bezier_frame(KeyframeEditData *ked, BezTriple *bezt)
{
short ok = 0;
-
+
/* 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);
#undef KEY_CHECK_OK
-
+
/* return ok flags */
return ok;
}
@@ -471,19 +471,19 @@ static short ok_bezier_frame(KeyframeEditData *ked, BezTriple *bezt)
static short ok_bezier_framerange(KeyframeEditData *ked, BezTriple *bezt)
{
short ok = 0;
-
+
/* 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);
#undef KEY_CHECK_OK
-
+
/* return ok flags */
return ok;
}
static short ok_bezier_selected(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- /* this macro checks all beztriple handles for selection...
+ /* 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))
@@ -493,17 +493,17 @@ static short ok_bezier_selected(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
}
static short ok_bezier_value(KeyframeEditData *ked, BezTriple *bezt)
-{
+{
short ok = 0;
-
- /* value is stored in f1 property
+
+ /* 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);
#undef KEY_CHECK_OK
-
+
/* return ok flags */
return ok;
}
@@ -511,12 +511,12 @@ static short ok_bezier_value(KeyframeEditData *ked, BezTriple *bezt)
static short ok_bezier_valuerange(KeyframeEditData *ked, BezTriple *bezt)
{
short ok = 0;
-
+
/* 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);
#undef KEY_CHECK_OK
-
+
/* return ok flags */
return ok;
}
@@ -526,15 +526,15 @@ 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;
-
+
#define KEY_CHECK_OK(_index) BLI_rctf_isect_pt_v(ked->data, bezt->vec[_index])
KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
#undef KEY_CHECK_OK
-
+
/* return ok flags */
return ok;
}
- else
+ else
return 0;
}
@@ -547,9 +547,9 @@ bool keyframe_region_lasso_test(
{
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);
-
+
if (BLI_lasso_is_point_inside(data_lasso->mcords, data_lasso->mcords_tot, xy_view[0], xy_view[1], INT_MAX)) {
return true;
}
@@ -563,11 +563,11 @@ static short ok_bezier_region_lasso(KeyframeEditData *ked, BezTriple *bezt)
/* 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);
#undef KEY_CHECK_OK
-
+
/* return ok flags */
return ok;
}
@@ -581,7 +581,7 @@ static short ok_bezier_channel_lasso(KeyframeEditData *ked, BezTriple *bezt)
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
@@ -591,11 +591,11 @@ static short ok_bezier_channel_lasso(KeyframeEditData *ked, BezTriple *bezt)
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;
-
+
if (keyframe_region_lasso_test(data, pt))
return KEYFRAME_OK_KEY;
}
@@ -611,14 +611,14 @@ bool keyframe_region_circle_test(
{
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);
-
+
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;
}
@@ -628,11 +628,11 @@ static short ok_bezier_region_circle(KeyframeEditData *ked, BezTriple *bezt)
/* 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);
#undef KEY_CHECK_OK
-
+
/* return ok flags */
return ok;
}
@@ -646,7 +646,7 @@ static short ok_bezier_channel_circle(KeyframeEditData *ked, BezTriple *bezt)
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
@@ -656,11 +656,11 @@ static short ok_bezier_channel_circle(KeyframeEditData *ked, BezTriple *bezt)
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;
-
+
if (keyframe_region_circle_test(data, pt))
return KEYFRAME_OK_KEY;
}
@@ -707,16 +707,16 @@ short bezt_calc_average(KeyframeEditData *ked, BezTriple *bezt)
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)
+
+ /* 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++;
}
-
+
return 0;
}
@@ -727,24 +727,24 @@ short bezt_to_cfraelem(KeyframeEditData *ked, BezTriple *bezt)
if (bezt->f2 & SELECT) {
CfraElem *ce = MEM_callocN(sizeof(CfraElem), "cfraElem");
BLI_addtail(&ked->list, ce);
-
+
ce->cfra = bezt->vec[1][0];
}
-
+
return 0;
}
/* used to remap times from one range to another
- * requires: ked->data = KeyframeEditCD_Remap
+ * requires: ked->data = KeyframeEditCD_Remap
*/
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);
-
+
/* 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;
@@ -766,7 +766,7 @@ static short snap_bezier_nearestsec(KeyframeEditData *ked, BezTriple *bezt)
{
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;
@@ -794,7 +794,7 @@ static short snap_bezier_horizontal(KeyframeEditData *UNUSED(ked), BezTriple *be
{
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;
}
@@ -871,11 +871,11 @@ static void mirror_bezier_yaxis_ex(BezTriple *bezt, const float center)
static short mirror_bezier_cframe(KeyframeEditData *ked, BezTriple *bezt)
{
const Scene *scene = ked->scene;
-
+
if (bezt->f2 & SELECT) {
mirror_bezier_xaxis_ex(bezt, CFRA);
}
-
+
return 0;
}
@@ -885,7 +885,7 @@ static short mirror_bezier_yaxis(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
/* Yes, names are inverted, we are mirroring accross y axis, hence along x axis... */
mirror_bezier_xaxis_ex(bezt, 0.0f);
}
-
+
return 0;
}
@@ -895,7 +895,7 @@ static short mirror_bezier_xaxis(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
/* Yes, names are inverted, we are mirroring accross x axis, hence along y axis... */
mirror_bezier_yaxis_ex(bezt, 0.0f);
}
-
+
return 0;
}
@@ -905,7 +905,7 @@ static short mirror_bezier_marker(KeyframeEditData *ked, BezTriple *bezt)
if (bezt->f2 & SELECT) {
mirror_bezier_xaxis_ex(bezt, ked->f1);
}
-
+
return 0;
}
@@ -915,7 +915,7 @@ static short mirror_bezier_time(KeyframeEditData *ked, BezTriple *bezt)
if (bezt->f2 & SELECT) {
mirror_bezier_xaxis_ex(bezt, ked->f1);
}
-
+
return 0;
}
@@ -925,7 +925,7 @@ static short mirror_bezier_value(KeyframeEditData *ked, BezTriple *bezt)
if (bezt->f2 & SELECT) {
mirror_bezier_yaxis_ex(bezt, ked->f1);
}
-
+
return 0;
}
@@ -941,7 +941,7 @@ KeyframeEditFunc ANIM_editkeyframes_mirror(short type)
case MIRROR_KEYS_XAXIS: /* mirror over value 0 */
return mirror_bezier_xaxis;
case MIRROR_KEYS_MARKER: /* mirror over marker */
- return mirror_bezier_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 */
@@ -966,12 +966,12 @@ KeyframeEditFunc ANIM_editkeyframes_mirror(short type)
} (void)0
/* Sets the selected bezier handles to type 'auto' */
-static short set_bezier_auto(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
+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;
-
+
ENSURE_HANDLES_MATCH(bezt);
}
return 0;
@@ -980,19 +980,19 @@ static short set_bezier_auto(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
/* Sets the selected bezier handles to type 'auto-clamped'
* NOTE: this is like auto above, but they're handled a bit different
*/
-static short set_bezier_auto_clamped(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;
-
+
ENSURE_HANDLES_MATCH(bezt);
}
return 0;
}
/* Sets the selected bezier handles to type 'vector' */
-static short set_bezier_vector(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
+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;
@@ -1002,7 +1002,7 @@ static short set_bezier_vector(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
/* 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
-static short bezier_isfree(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
+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;
@@ -1010,15 +1010,15 @@ static short bezier_isfree(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
}
/* Sets selected bezier handles to type 'align' */
-static short set_bezier_align(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
-{
+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;
}
/* Sets selected bezier handles to type 'free' */
-static short set_bezier_free(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
+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;
@@ -1034,14 +1034,14 @@ KeyframeEditFunc ANIM_editkeyframes_handles(short code)
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;
-
+
default: /* check for toggle free or align? */
return bezier_isfree;
}
@@ -1049,23 +1049,23 @@ KeyframeEditFunc ANIM_editkeyframes_handles(short code)
/* ------- */
-static short set_bezt_constant(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
+static short set_bezt_constant(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
+ if (bezt->f2 & SELECT)
bezt->ipo = BEZT_IPO_CONST;
return 0;
}
-static short set_bezt_linear(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
+static short set_bezt_linear(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
+ if (bezt->f2 & SELECT)
bezt->ipo = BEZT_IPO_LIN;
return 0;
}
-static short set_bezt_bezier(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
+static short set_bezt_bezier(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
+ if (bezt->f2 & SELECT)
bezt->ipo = BEZT_IPO_BEZ;
return 0;
}
@@ -1150,7 +1150,7 @@ KeyframeEditFunc ANIM_editkeyframes_ipo(short code)
return set_bezt_constant;
case BEZT_IPO_LIN: /* linear */
return set_bezt_linear;
-
+
/* easing */
case BEZT_IPO_BACK:
return set_bezt_back;
@@ -1172,7 +1172,7 @@ KeyframeEditFunc ANIM_editkeyframes_ipo(short code)
return set_bezt_quint;
case BEZT_IPO_SINE:
return set_bezt_sine;
-
+
default: /* bezier */
return set_bezt_bezier;
}
@@ -1180,37 +1180,37 @@ KeyframeEditFunc ANIM_editkeyframes_ipo(short code)
/* ------- */
-static short set_keytype_keyframe(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
+static short set_keytype_keyframe(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
+ if (bezt->f2 & SELECT)
BEZKEYTYPE(bezt) = BEZT_KEYTYPE_KEYFRAME;
return 0;
}
-static short set_keytype_breakdown(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
+static short set_keytype_breakdown(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
+ if (bezt->f2 & SELECT)
BEZKEYTYPE(bezt) = BEZT_KEYTYPE_BREAKDOWN;
return 0;
}
-static short set_keytype_extreme(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
+static short set_keytype_extreme(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
+ if (bezt->f2 & SELECT)
BEZKEYTYPE(bezt) = BEZT_KEYTYPE_EXTREME;
return 0;
}
-static short set_keytype_jitter(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
+static short set_keytype_jitter(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
+ if (bezt->f2 & SELECT)
BEZKEYTYPE(bezt) = BEZT_KEYTYPE_JITTER;
return 0;
}
-static short set_keytype_moving_hold(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
+static short set_keytype_moving_hold(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
+ if (bezt->f2 & SELECT)
BEZKEYTYPE(bezt) = BEZT_KEYTYPE_MOVEHOLD;
return 0;
}
@@ -1221,16 +1221,16 @@ KeyframeEditFunc ANIM_editkeyframes_keytype(short code)
switch (code) {
case BEZT_KEYTYPE_BREAKDOWN: /* breakdown */
return set_keytype_breakdown;
-
+
case BEZT_KEYTYPE_EXTREME: /* extreme keyframe */
return set_keytype_extreme;
-
+
case BEZT_KEYTYPE_JITTER: /* jitter keyframe */
return set_keytype_jitter;
-
+
case BEZT_KEYTYPE_MOVEHOLD: /* moving hold */
return set_keytype_moving_hold;
-
+
case BEZT_KEYTYPE_KEYFRAME: /* proper keyframe */
default:
return set_keytype_keyframe;
@@ -1273,13 +1273,13 @@ KeyframeEditFunc ANIM_editkeyframes_easing(short mode)
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_IN_OUT: /* both */
return set_easingtype_easeinout;
-
+
default: /* auto */
return set_easingtype_easeauto;
}
@@ -1288,7 +1288,7 @@ KeyframeEditFunc ANIM_editkeyframes_easing(short mode)
/* ******************************************* */
/* Selection */
-static short select_bezier_add(KeyframeEditData *ked, BezTriple *bezt)
+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)) {
@@ -1302,11 +1302,11 @@ static short select_bezier_add(KeyframeEditData *ked, BezTriple *bezt)
else {
BEZT_SEL_ALL(bezt);
}
-
+
return 0;
}
-static short select_bezier_subtract(KeyframeEditData *ked, BezTriple *bezt)
+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)) {
@@ -1320,11 +1320,11 @@ static short select_bezier_subtract(KeyframeEditData *ked, BezTriple *bezt)
else {
BEZT_DESEL_ALL(bezt);
}
-
+
return 0;
}
-static short select_bezier_invert(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
+static short select_bezier_invert(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
/* Invert the selection for the whole bezier triple */
bezt->f2 ^= SELECT;
@@ -1369,33 +1369,33 @@ static short selmap_build_bezier_more(KeyframeEditData *ked, BezTriple *bezt)
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 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 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;
}
}
-
+
return 0;
}
@@ -1404,7 +1404,7 @@ 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)
*/
@@ -1412,7 +1412,7 @@ static short selmap_build_bezier_less(KeyframeEditData *ked, BezTriple *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;
}
@@ -1420,11 +1420,11 @@ static short selmap_build_bezier_less(KeyframeEditData *ked, BezTriple *bezt)
/* 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;
}
@@ -1432,11 +1432,11 @@ static short selmap_build_bezier_less(KeyframeEditData *ked, BezTriple *bezt)
/* 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;
}
@@ -1446,7 +1446,7 @@ KeyframeEditFunc ANIM_editkeyframes_buildselmap(short mode)
switch (mode) {
case SELMAP_LESS: /* less */
return selmap_build_bezier_less;
-
+
case SELMAP_MORE: /* more */
default:
return selmap_build_bezier_more;
@@ -1460,7 +1460,7 @@ short bezt_selmap_flush(KeyframeEditData *ked, BezTriple *bezt)
{
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);
@@ -1468,7 +1468,6 @@ short bezt_selmap_flush(KeyframeEditData *ked, BezTriple *bezt)
else {
BEZT_DESEL_ALL(bezt);
}
-
+
return 0;
}
-
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index bf5d4ec0300..a6ed6643257 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -48,6 +48,7 @@
#include "BKE_fcurve.h"
#include "BKE_report.h"
#include "BKE_library.h"
+#include "BKE_main.h"
#include "BKE_global.h"
#include "BKE_deform.h"
@@ -62,25 +63,25 @@
* (i.e. they will modify the order of the keyframes, and change the size of the array).
* While some of these tools may eventually be moved out into blenkernel, for now, it is
* fine to have these calls here.
- *
+ *
* There are also a few tools here which cannot be easily coded for in the other system (yet).
* These may also be moved around at some point, but for now, they are best added here.
*
* - Joshua Leung, Dec 2008
*/
-
+
/* **************************************************** */
-/* Only delete the nominated keyframe from provided F-Curve.
+/* Only delete the nominated keyframe from provided F-Curve.
* Not recommended to be used many times successively. For that
- * there is delete_fcurve_keys().
+ * there is delete_fcurve_keys().
*/
void delete_fcurve_key(FCurve *fcu, int index, bool do_recalc)
{
/* sanity check */
- if (fcu == NULL)
+ 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
@@ -89,7 +90,7 @@ void delete_fcurve_key(FCurve *fcu, int index, bool do_recalc)
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--;
@@ -99,7 +100,7 @@ void delete_fcurve_key(FCurve *fcu, int index, bool do_recalc)
MEM_freeN(fcu->bezt);
fcu->bezt = NULL;
}
-
+
/* recalc handles - only if it won't cause problems */
if (do_recalc)
calchandles_fcurve(fcu);
@@ -110,7 +111,7 @@ bool delete_fcurve_keys(FCurve *fcu)
{
int i;
bool changed = false;
-
+
if (fcu->bezt == NULL) /* ignore baked curves */
return false;
@@ -123,7 +124,7 @@ bool delete_fcurve_keys(FCurve *fcu)
changed = true;
}
}
-
+
/* Free the array of BezTriples if there are not keyframes */
if (fcu->totvert == 0)
clear_fcurve_keys(fcu);
@@ -148,30 +149,30 @@ 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]);
}
@@ -189,7 +190,7 @@ void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, boo
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))
@@ -202,7 +203,7 @@ void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, boo
totCount = fcu->totvert;
fcu->bezt = NULL;
fcu->totvert = 0;
-
+
/* now insert first keyframe, as it should be ok */
bezt = old_bezts;
insert_vert_fcurve(fcu, bezt->vec[1][0], bezt->vec[1][1], BEZKEYTYPE(bezt), 0);
@@ -210,8 +211,8 @@ void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, boo
lastb = fcu->bezt;
lastb->f1 = lastb->f2 = lastb->f3 = 0;
}
-
- /* Loop through BezTriples, comparing them. Skip any that do
+
+ /* Loop through BezTriples, comparing them. Skip any that do
* not fit the criteria for "ok" points.
*/
for (i = 1; i < totCount; i++) {
@@ -228,22 +229,22 @@ void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, boo
}
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_vert_fcurve(fcu, cur[0], cur[1], BEZKEYTYPE(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
+ /* 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)) &&
@@ -287,7 +288,7 @@ void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, boo
}
}
}
-
+
/* now free the memory used by the old BezTriples */
if (old_bezts)
MEM_freeN(old_bezts);
@@ -346,14 +347,14 @@ void smooth_fcurve(FCurve *fcu)
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++) {
@@ -362,7 +363,7 @@ void smooth_fcurve(FCurve *fcu)
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++;
@@ -370,15 +371,15 @@ void smooth_fcurve(FCurve *fcu)
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 */
+
+ /* 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) */
@@ -387,21 +388,21 @@ void smooth_fcurve(FCurve *fcu)
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++) {
@@ -409,17 +410,17 @@ void smooth_fcurve(FCurve *fcu)
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->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);
}
@@ -442,7 +443,7 @@ void sample_fcurve(FCurve *fcu)
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 */
@@ -459,39 +460,39 @@ void sample_fcurve(FCurve *fcu)
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;
@@ -503,14 +504,14 @@ void sample_fcurve(FCurve *fcu)
}
}
}
-
+
/* recalculate channel's handles? */
calchandles_fcurve(fcu);
}
/* **************************************************** */
/* Copy/Paste Tools */
-/* - The copy/paste buffer currently stores a set of temporary F-Curves containing only the keyframes
+/* - The copy/paste buffer currently stores a set of temporary F-Curves containing only the keyframes
* that were selected in each of the original F-Curves
* - All pasted frames are offset by the same amount. This is calculated as the difference in the times of
* the current frame and the 'first keyframe' (i.e. the earliest one in all channels).
@@ -526,12 +527,12 @@ static float animcopy_cfra = 0.0;
/* datatype for use in copy/paste buffer */
typedef struct tAnimCopybufItem {
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 */
-
+
int totvert; /* number of keyframes stored for this channel */
BezTriple *bezt; /* keyframes in buffer */
@@ -544,23 +545,23 @@ typedef struct tAnimCopybufItem {
void ANIM_fcurves_copybuf_free(void)
{
tAnimCopybufItem *aci, *acn;
-
+
/* free each buffer element */
for (aci = animcopybuf.first; aci; aci = acn) {
acn = aci->next;
-
+
/* free keyframes */
- if (aci->bezt)
+ if (aci->bezt)
MEM_freeN(aci->bezt);
-
+
/* free RNA-path */
if (aci->rna_path)
MEM_freeN(aci->rna_path);
-
+
/* free ourself */
BLI_freelinkN(&animcopybuf, aci);
}
-
+
/* restore initial state */
BLI_listbase_clear(&animcopybuf);
animcopy_firstframe = 999999999.0f;
@@ -571,27 +572,27 @@ 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;
@@ -599,7 +600,7 @@ short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data)
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) {
@@ -614,9 +615,9 @@ short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data)
}
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 */
@@ -624,23 +625,23 @@ short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data)
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];
@@ -648,9 +649,9 @@ short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data)
animcopy_lastframe = bezt->vec[1][0];
}
}
-
+
}
-
+
/* check if anything ended up in the buffer */
if (ELEM(NULL, animcopybuf.first, animcopybuf.last))
return -1;
@@ -729,7 +730,8 @@ static tAnimCopybufItem *pastebuf_match_path_full(FCurve *fcu, const short from_
}
/* medium match strictness: path match only (i.e. ignore ID) */
-static tAnimCopybufItem *pastebuf_match_path_property(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;
@@ -740,18 +742,18 @@ static tAnimCopybufItem *pastebuf_match_path_property(FCurve *fcu, const short f
* more involved since it needs to to 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.
+ * this should work out ok.
*/
- if (BLI_findindex(which_libbase(G.main, aci->id_type), aci->id) == -1) {
+ 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);
@@ -804,7 +806,7 @@ static void do_curve_mirror_flippping(tAnimCopybufItem *aci, BezTriple *bezt)
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];
@@ -829,18 +831,18 @@ static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float
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;
@@ -849,7 +851,7 @@ static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float
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 */
@@ -858,39 +860,39 @@ static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float
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);
}
@@ -921,12 +923,12 @@ 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;
@@ -940,7 +942,7 @@ short paste_animedit_keys(bAnimContext *ac, ListBase *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:
@@ -961,25 +963,25 @@ short paste_animedit_keys(bAnimContext *ac, ListBase *anim_data,
/* 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
+ /* 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
+ /* 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)
@@ -987,28 +989,28 @@ short paste_animedit_keys(bAnimContext *ac, ListBase *anim_data,
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(fcu, from_single, to_simple);
+ 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);
@@ -1018,16 +1020,16 @@ short paste_animedit_keys(bAnimContext *ac, ListBase *anim_data,
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 7b637e5b725..fe5714aba2e 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -29,7 +29,7 @@
* \ingroup edanimation
*/
-
+
#include <stdio.h>
#include <stddef.h>
#include <string.h>
@@ -53,20 +53,22 @@
#include "DNA_object_types.h"
#include "DNA_rigidbody_types.h"
-#include "BKE_animsys.h"
#include "BKE_action.h"
+#include "BKE_animsys.h"
#include "BKE_armature.h"
+#include "BKE_context.h"
#include "BKE_fcurve.h"
-#include "BKE_idcode.h"
-#include "BKE_nla.h"
#include "BKE_global.h"
-#include "BKE_context.h"
-#include "BKE_report.h"
+#include "BKE_idcode.h"
#include "BKE_key.h"
+#include "BKE_main.h"
#include "BKE_material.h"
+#include "BKE_nla.h"
+#include "BKE_report.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
#include "ED_anim_api.h"
#include "ED_keyframing.h"
@@ -93,42 +95,42 @@
short ANIM_get_keyframing_flags(Scene *scene, short incl_mode)
{
eInsertKeyFlags flag = INSERTKEY_NOFLAGS;
-
+
/* standard flags */
{
/* visual keying */
- if (IS_AUTOKEY_FLAG(scene, AUTOMATKEY))
+ if (IS_AUTOKEY_FLAG(scene, AUTOMATKEY))
flag |= INSERTKEY_MATRIX;
-
+
/* only needed */
- if (IS_AUTOKEY_FLAG(scene, INSERTNEEDED))
+ if (IS_AUTOKEY_FLAG(scene, INSERTNEEDED))
flag |= INSERTKEY_NEEDED;
-
+
/* default F-Curve color mode - RGB from XYZ indices */
- if (IS_AUTOKEY_FLAG(scene, XYZ2RGB))
+ 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))
+ if (IS_AUTOKEY_MODE(scene, EDITKEYS))
flag |= INSERTKEY_REPLACE;
}
-
+
return flag;
}
/* ******************************************* */
/* Animation Data Validation */
-/* Get (or add relevant data to be able to do so) the Active Action for the given
+/* Get (or add relevant data to be able to do so) the Active Action for the given
* Animation Data block, given an ID block where the Animation Data should reside.
*/
-bAction *verify_adt_action(ID *id, short add)
+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))
@@ -145,10 +147,10 @@ bAction *verify_adt_action(ID *id, short 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(G.main, actname);
-
+ 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
@@ -157,7 +159,7 @@ bAction *verify_adt_action(ID *id, short add)
/* tag depsgraph to be rebuilt to include time dependency */
/* XXX: we probably should have bmain passed down, but that involves altering too many API's */
- DEG_relations_tag_update(G.main);
+ DEG_relations_tag_update(bmain);
}
DEG_id_tag_update(&adt->action->id, DEG_TAG_COPY_ON_WRITE);
@@ -166,54 +168,54 @@ bAction *verify_adt_action(ID *id, short add)
return adt->action;
}
-/* Get (or add relevant data to be able to do so) F-Curve from the Active 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(bAction *act, const char group[], PointerRNA *ptr,
+FCurve *verify_fcurve(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
+
+ /* 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) {
@@ -222,7 +224,7 @@ FCurve *verify_fcurve(bAction *act, const char group[], PointerRNA *ptr,
}
}
}
-
+
/* add F-Curve to group */
action_groups_add_channel(act, agrp, fcu);
}
@@ -231,7 +233,7 @@ FCurve *verify_fcurve(bAction *act, const char group[], PointerRNA *ptr,
BLI_addtail(&act->curves, fcu);
}
}
-
+
/* return the F-Curve */
return fcu;
}
@@ -284,10 +286,10 @@ void update_autoflags_fcurve(FCurve *fcu, bContext *C, ReportList *reports, Poin
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);
@@ -299,22 +301,22 @@ void update_autoflags_fcurve(FCurve *fcu, bContext *C, ReportList *reports, Poin
/* -------------- BezTriple Insertion -------------------- */
-/* This function adds a given BezTriple to an F-Curve. It will allocate
+/* This function adds a given BezTriple to an F-Curve. It will allocate
* memory for the array if needed, and will insert the BezTriple into a
* suitable place in chronological order.
- *
- * NOTE: any recalculate of the F-Curve that needs to be done will need to
+ *
+ * NOTE: any recalculate of the F-Curve that needs to be done will need to
* be done by the caller.
*/
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 */
@@ -326,16 +328,16 @@ int insert_bezt_fcurve(FCurve *fcu, const BezTriple *bezt, eInsertKeyFlags flag)
/* just change the values when replacing, so as to not overwrite handles */
BezTriple *dst = (fcu->bezt + i);
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;
-
+
dst->f1 = bezt->f1;
dst->f2 = bezt->f2;
dst->f3 = bezt->f3;
-
+
/* TODO: perform some other operations? */
}
}
@@ -344,29 +346,29 @@ int insert_bezt_fcurve(FCurve *fcu, const BezTriple *bezt, eInsertKeyFlags flag)
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)
+ 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++;
}
}
/* 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,
+ * // 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)) {
@@ -380,9 +382,9 @@ int insert_bezt_fcurve(FCurve *fcu, const BezTriple *bezt, eInsertKeyFlags flag)
/* 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
+
+
+ /* 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;
@@ -390,11 +392,11 @@ int insert_bezt_fcurve(FCurve *fcu, const BezTriple *bezt, eInsertKeyFlags flag)
/**
* This function is a wrapper for insert_bezt_fcurve_internal(), and should be used when
- * adding a new keyframe to a curve, when the keyframe doesn't exist anywhere else yet.
+ * adding a new keyframe to a curve, when the keyframe doesn't exist anywhere else yet.
* It returns the index at which the keyframe was added.
*
* \param keyframe_type: The type of keyframe (eBezTriple_KeyframeType)
- * \param flag: Optional flags (eInsertKeyFlags) for controlling how keys get added
+ * \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)
@@ -402,8 +404,8 @@ int insert_vert_fcurve(FCurve *fcu, float x, float y, eBezTriple_KeyframeType ke
BezTriple beztr = {{{0}}};
unsigned int oldTot = fcu->totvert;
int a;
-
- /* set all three points, for nicer start position
+
+ /* 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;
@@ -413,7 +415,7 @@ int insert_vert_fcurve(FCurve *fcu, float x, float y, eBezTriple_KeyframeType ke
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 behaviour,
@@ -425,11 +427,11 @@ int insert_vert_fcurve(FCurve *fcu, float x, float y, eBezTriple_KeyframeType ke
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;
@@ -437,10 +439,10 @@ int insert_vert_fcurve(FCurve *fcu, float x, float y, eBezTriple_KeyframeType ke
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
@@ -448,48 +450,48 @@ int insert_vert_fcurve(FCurve *fcu, float x, float y, eBezTriple_KeyframeType ke
*/
beztr.back = 1.70158f; /* "back" easing - this value used to be used when overshoot=0, but that */
/* introduced discontinuities in how the param worked */
-
+
beztr.amplitude = 0.8f; /* "elastic" easing - values here were hand-optimised for a default duration of */
beztr.period = 4.1f; /* ~10 frames (typical mograph motion length) */
-
+
/* add temp beztriple to keyframes */
a = insert_bezt_fcurve(fcu, &beztr, flag);
-
- /* what if 'a' is a negative index?
+
+ /* 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)
+ 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
+
+ /* 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)
+ 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)
+ if ((flag & INSERTKEY_FAST) == 0)
calchandles_fcurve(fcu);
}
-
+
/* return the index at which the keyframe was added */
return a;
}
@@ -514,34 +516,34 @@ 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 ? */
@@ -550,18 +552,18 @@ static short new_key_needed(FCurve *fcu, float cFrame, float nValue)
}
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
+ else
return KEYNEEDED_JUSTADD;
}
}
-
+
/* new keyframe before prev beztriple? */
if (cFrame < prevPosi) {
/* A new keyframe will be added. However, whether the previous beztriple
@@ -570,18 +572,18 @@ static short new_key_needed(FCurve *fcu, float cFrame, float nValue)
*/
if (IS_EQF(prevVal, nValue) && IS_EQF(beztVal, nValue) && IS_EQF(prevVal, beztVal))
return KEYNEEDED_DELNEXT;
- else
+ else
return KEYNEEDED_JUSTADD;
}
}
else {
- /* just add a keyframe if there's only one keyframe
+ /* 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;
@@ -590,7 +592,7 @@ static short new_key_needed(FCurve *fcu, float cFrame, float nValue)
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
@@ -600,51 +602,56 @@ static short new_key_needed(FCurve *fcu, float cFrame, float nValue)
*/
bezt = (fcu->bezt + (fcu->totvert - 1));
valA = bezt->vec[1][1];
-
+
if (prev)
valB = prev->vec[1][1];
- else
+ else
valB = bezt->vec[1][1] + 1.0f;
-
+
if (IS_EQF(valA, nValue) && IS_EQF(valA, valB))
return KEYNEEDED_DELPREV;
- else
+ else
return KEYNEEDED_JUSTADD;
}
/* ------------------ RNA Data-Access Functions ------------------ */
/* Try to read value using RNA-properties obtained already */
-static float setting_get_rna_value(PointerRNA *ptr, PropertyRNA *prop, int index)
+static float setting_get_rna_value(Depsgraph *depsgraph, PointerRNA *ptr, PropertyRNA *prop, int index, const bool get_evaluated)
{
+ PointerRNA ptr_eval = *ptr;
float value = 0.0f;
-
+
+ if (get_evaluated) {
+ DEG_get_evaluated_rna_pointer(depsgraph, ptr, &ptr_eval);
+ }
+
switch (RNA_property_type(prop)) {
case PROP_BOOLEAN:
if (RNA_property_array_check(prop))
- value = (float)RNA_property_boolean_get_index(ptr, prop, index);
+ value = (float)RNA_property_boolean_get_index(&ptr_eval, prop, index);
else
- value = (float)RNA_property_boolean_get(ptr, prop);
+ value = (float)RNA_property_boolean_get(&ptr_eval, prop);
break;
case PROP_INT:
if (RNA_property_array_check(prop))
- value = (float)RNA_property_int_get_index(ptr, prop, index);
+ value = (float)RNA_property_int_get_index(&ptr_eval, prop, index);
else
- value = (float)RNA_property_int_get(ptr, prop);
+ value = (float)RNA_property_int_get(&ptr_eval, prop);
break;
case PROP_FLOAT:
if (RNA_property_array_check(prop))
- value = RNA_property_float_get_index(ptr, prop, index);
+ value = RNA_property_float_get_index(&ptr_eval, prop, index);
else
- value = RNA_property_float_get(ptr, prop);
+ value = RNA_property_float_get(&ptr_eval, prop);
break;
case PROP_ENUM:
- value = (float)RNA_property_enum_get(ptr, prop);
+ value = (float)RNA_property_enum_get(&ptr_eval, prop);
break;
default:
break;
}
-
+
return value;
}
@@ -658,10 +665,10 @@ enum {
VISUALKEY_SCA,
};
-/* This helper function determines if visual-keyframing should be used when
+/* This helper function determines if visual-keyframing should be used when
* inserting keyframes for the given channel. As visual-keyframing only works
- * on Object and Pose-Channel blocks, this should only get called for those
- * blocktypes, when using "standard" keying but 'Visual Keying' option in Auto-Keying
+ * on Object and Pose-Channel blocks, this should only get called for those
+ * blocktypes, when using "standard" keying but 'Visual Keying' option in Auto-Keying
* settings is on.
*/
static bool visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
@@ -671,12 +678,12 @@ static bool visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
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
+
+ /* 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
@@ -685,27 +692,27 @@ static bool visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
/* 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__);
@@ -724,20 +731,20 @@ static bool visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
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 */
@@ -750,7 +757,7 @@ static bool visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
return true;
case CONSTRAINT_TYPE_KINEMATIC:
return true;
-
+
/* single-transform constraits */
case CONSTRAINT_TYPE_TRACKTO:
if (searchtype == VISUALKEY_ROT) return true;
@@ -785,28 +792,28 @@ static bool visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
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
+/* 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_value(PointerRNA *ptr, PropertyRNA *prop, int array_index)
+static float visualkey_get_value(Depsgraph *depsgraph, PointerRNA *ptr, PropertyRNA *prop, int array_index)
{
const char *identifier = RNA_property_identifier(prop);
float tmat[4][4];
int rotmode;
-
- /* handle for Objects or PoseChannels only
+
+ /* 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
@@ -815,21 +822,26 @@ static float visualkey_get_value(PointerRNA *ptr, PropertyRNA *prop, int array_i
*/
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")) {
- return ob->obmat[3][array_index];
+ return ob_eval->obmat[3][array_index];
}
-
- copy_m4_m4(tmat, ob->obmat);
- rotmode = ob->rotmode;
+
+ 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;
-
- BKE_armature_mat_pose_to_bone(pchan, pchan->pose_mat, tmat);
- rotmode = pchan->rotmode;
-
+
+ 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 */
@@ -838,29 +850,29 @@ static float visualkey_get_value(PointerRNA *ptr, PropertyRNA *prop, int array_i
}
}
else {
- return setting_get_rna_value(ptr, prop, array_index);
+ return setting_get_rna_value(depsgraph, ptr, prop, array_index, true);
}
-
+
/* Rot/Scale code are common! */
if (strstr(identifier, "rotation_euler")) {
float eul[3];
-
+
mat4_to_eulO(eul, rotmode, tmat);
return eul[array_index];
}
else if (strstr(identifier, "rotation_quaternion")) {
float mat3[3][3], quat[4];
-
+
copy_m3_m4(mat3, tmat);
mat3_to_quat_is_ok(quat, mat3);
-
+
return quat[array_index];
}
else if (strstr(identifier, "rotation_axis_angle")) {
float axis[3], angle;
-
+
mat4_to_axis_angle(axis, &angle, tmat);
-
+
/* w = 0, x,y,z = 1,2,3 */
if (array_index == 0)
return angle;
@@ -869,19 +881,19 @@ static float visualkey_get_value(PointerRNA *ptr, PropertyRNA *prop, int array_i
}
else if (strstr(identifier, "scale")) {
float scale[3];
-
+
mat4_to_size(scale, tmat);
-
+
return scale[array_index];
}
-
+
/* as the function hasn't returned yet, read value from system in the default way */
- return setting_get_rna_value(ptr, prop, array_index);
+ return setting_get_rna_value(depsgraph, ptr, prop, array_index, true);
}
/* ------------------------- Insert Key API ------------------------- */
-/* Secondary Keyframing API call:
+/* Secondary Keyframing API call:
* Use this when validation of necessary animation data is not necessary, since an RNA-pointer to the necessary
* data being keyframed, and a pointer to the F-Curve to use have both been provided.
*
@@ -891,10 +903,10 @@ static float visualkey_get_value(PointerRNA *ptr, PropertyRNA *prop, int array_i
* the keyframe insertion. These include the 'visual' keyframing modes, quick refresh,
* and extra keyframe filtering.
*/
-bool insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, float cfra, eBezTriple_KeyframeType keytype, eInsertKeyFlags flag)
+bool insert_keyframe_direct(Depsgraph *depsgraph, ReportList *reports, PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, float cfra, eBezTriple_KeyframeType keytype, 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");
@@ -902,13 +914,13 @@ bool insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *pr
}
/* F-Curve not editable? */
if (fcurve_is_keyframable(fcu) == 0) {
- BKE_reportf(reports, RPT_ERROR,
+ 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;
}
-
+
/* 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");
@@ -916,12 +928,12 @@ bool insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *pr
}
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);
@@ -932,7 +944,7 @@ bool insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *pr
ptr = tmp_ptr;
}
}
-
+
/* update F-Curve flags to ensure proper behaviour for property type */
update_autoflags_fcurve_direct(fcu, prop);
@@ -942,39 +954,39 @@ bool insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *pr
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, cfra);
+ cfra = evaluate_driver(&anim_rna, fcu->driver, fcu->driver, cfra);
}
else {
cfra = 0.0f;
}
}
-
+
/* obtain value to give keyframe */
- if ( (flag & INSERTKEY_MATRIX) &&
+ 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
+ /* 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.
*/
- curval = visualkey_get_value(&ptr, prop, fcu->array_index);
+ curval = visualkey_get_value(depsgraph, &ptr, prop, fcu->array_index);
}
else {
/* read value from system */
- curval = setting_get_rna_value(&ptr, prop, fcu->array_index);
+ curval = setting_get_rna_value(depsgraph, &ptr, prop, fcu->array_index, false);
}
-
+
/* 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);
-
+
/* insert new keyframe at current frame */
if (insert_mode)
insert_vert_fcurve(fcu, cfra, curval, keytype, flag);
-
+
/* delete keyframe immediately before/after newly added */
switch (insert_mode) {
case KEYNEEDED_DELPREV:
@@ -984,7 +996,7 @@ bool insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *pr
delete_fcurve_key(fcu, 1, 1);
break;
}
-
+
/* only return success if keyframe added */
if (insert_mode)
return true;
@@ -992,39 +1004,41 @@ bool insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *pr
else {
/* just insert keyframe */
insert_vert_fcurve(fcu, cfra, curval, keytype, flag);
-
+
/* return success */
return true;
}
-
+
/* failed */
return false;
}
/* Main Keyframing API call:
* Use this when validation of necessary animation data is necessary, since it may not exist yet.
- *
+ *
* The flag argument is used for special settings that alter the behavior of
* the keyframe insertion. These include the 'visual' keyframing modes, quick refresh,
* and extra keyframe filtering.
*
* index of -1 keys all array indices
*/
-short insert_keyframe(ReportList *reports, ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, eBezTriple_KeyframeType keytype, 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, eInsertKeyFlags flag)
+{
PointerRNA id_ptr, ptr;
PropertyRNA *prop = NULL;
AnimData *adt;
FCurve *fcu;
int array_index_max = array_index + 1;
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,
@@ -1032,45 +1046,45 @@ short insert_keyframe(ReportList *reports, ID *id, bAction *act, const char grou
(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(id, 1);
-
+ act = verify_adt_action(bmain, id, 1);
+
if (act == NULL) {
- BKE_reportf(reports, RPT_ERROR,
+ 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);
cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
-
+
/* 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
+ * 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++) {
- /* make sure the F-Curve exists
+ /* 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...
*/
fcu = verify_fcurve(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) */
@@ -1086,12 +1100,16 @@ short insert_keyframe(ReportList *reports, ID *id, bAction *act, const char grou
fcu->color_mode = FCURVE_COLOR_AUTO_YRGB;
}
}
-
+
/* insert keyframe */
- ret += insert_keyframe_direct(reports, ptr, prop, fcu, cfra, keytype, flag);
+ ret += insert_keyframe_direct(depsgraph, reports, ptr, prop, fcu, cfra, keytype, flag);
}
}
-
+
+ if (ret) {
+ DEG_id_tag_update(&adt->action->id, DEG_TAG_COPY_ON_WRITE);
+ }
+
return ret;
}
@@ -1101,7 +1119,7 @@ short insert_keyframe(ReportList *reports, ID *id, bAction *act, const char grou
/* Main Keyframing API call:
* Use this when validation of necessary animation data isn't necessary as it
* already exists. It will delete a keyframe at the current frame.
- *
+ *
* The flag argument is used for special settings that alter the behavior of
* the keyframe deletion. These include the quick refresh options.
*/
@@ -1140,13 +1158,13 @@ short delete_keyframe(ReportList *reports, ID *id, bAction *act, const char grou
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) {
@@ -1155,18 +1173,18 @@ short delete_keyframe(ReportList *reports, ID *id, bAction *act, const char grou
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 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);
}
@@ -1175,20 +1193,20 @@ short delete_keyframe(ReportList *reports, ID *id, bAction *act, const char grou
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
+ * 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(act, group, &ptr, rna_path, array_index, 0);
@@ -1207,7 +1225,7 @@ short delete_keyframe(ReportList *reports, ID *id, bAction *act, const char grou
ret += delete_keyframe_fcurve(adt, fcu, cfra);
}
-
+
/* return success/failure */
return ret;
}
@@ -1317,11 +1335,11 @@ static int modify_key_op_poll(bContext *C)
{
ScrArea *sa = CTX_wm_area(C);
Scene *scene = CTX_data_scene(C);
-
+
/* if no area or active scene */
- if (ELEM(NULL, sa, scene))
+ if (ELEM(NULL, sa, scene))
return false;
-
+
/* should be fine */
return true;
}
@@ -1337,19 +1355,19 @@ static int insert_key_exec(bContext *C, wmOperator *op)
int type = RNA_enum_get(op->ptr, "type");
float cfra = (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
short success;
-
+
/* type is the Keying Set the user specified to use when calling the operator:
* - type == 0: use scene's active Keying Set
* - type > 0: use a user-defined Keying Set from the active scene
* - type < 0: use a builtin Keying Set
*/
- if (type == 0)
+ 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);
-
+
/* report failures */
if (ks == NULL) {
BKE_report(op->reports, RPT_ERROR, "No active keying set");
@@ -1363,12 +1381,12 @@ static int insert_key_exec(bContext *C, wmOperator *op)
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);
@@ -1383,39 +1401,39 @@ static int insert_key_exec(bContext *C, wmOperator *op)
/* 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->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
+
+ /* 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",
@@ -1424,68 +1442,68 @@ void ANIM_OT_keyframe_insert(wmOperatorType *ot)
}
/* Insert Key Operator (With Menu) ------------------------ */
-/* This operator checks if a menu should be shown for choosing the KeyingSet to use,
- * then calls the menu if necessary before
+/* This operator checks if a menu should be shown for choosing the KeyingSet to use,
+ * then calls the menu if necessary before
*/
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);
}
}
-
+
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->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
+
+ /* 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
+
+ /* 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)
*/
@@ -1502,30 +1520,30 @@ static int delete_key_exec(bContext *C, wmOperator *op)
int type = RNA_enum_get(op->ptr, "type");
float cfra = (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
short success;
-
+
/* type is the Keying Set the user specified to use when calling the operator:
* - type == 0: use scene's active Keying Set
* - type > 0: use a user-defined Keying Set from the active scene
* - type < 0: use a builtin Keying Set
*/
- if (type == 0)
+ 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);
-
+
/* 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");
@@ -1535,39 +1553,39 @@ static int delete_key_exec(bContext *C, wmOperator *op)
/* 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->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
+
+ /* 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",
@@ -1578,7 +1596,7 @@ void ANIM_OT_keyframe_delete(wmOperatorType *ot)
/* NOTE: Although this version is simpler than the more generic version for KeyingSets,
* it is more useful for animators working in the 3D view.
*/
-
+
static int clear_anim_v3d_exec(bContext *C, wmOperator *UNUSED(op))
{
bool changed = false;
@@ -1590,23 +1608,23 @@ static int clear_anim_v3d_exec(bContext *C, wmOperator *UNUSED(op))
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)
@@ -1618,7 +1636,7 @@ static int clear_anim_v3d_exec(bContext *C, wmOperator *UNUSED(op))
/* 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);
@@ -1636,7 +1654,7 @@ static int clear_anim_v3d_exec(bContext *C, wmOperator *UNUSED(op))
/* send updates */
WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -1646,13 +1664,13 @@ void ANIM_OT_keyframe_clear_v3d(wmOperatorType *ot)
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;
-
+ ot->exec = clear_anim_v3d_exec;
+
ot->poll = ED_operator_areaactive;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1662,22 +1680,22 @@ 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,
@@ -1685,57 +1703,57 @@ static int delete_key_v3d_exec(bContext *C, wmOperator *op)
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 dealign 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
+
+ /* 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);
}
}
-
+
/* 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, OB_RECALC_OB);
}
CTX_DATA_END;
-
+
/* send updates */
WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -1745,13 +1763,13 @@ void ANIM_OT_keyframe_delete_v3d(wmOperatorType *ot)
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;
-
+ ot->exec = delete_key_v3d_exec;
+
ot->poll = ED_operator_areaactive;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1761,6 +1779,8 @@ void ANIM_OT_keyframe_delete_v3d(wmOperatorType *ot)
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}};
@@ -1773,16 +1793,16 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
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
@@ -1791,9 +1811,9 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
*/
NlaStrip *strip = (NlaStrip *)ptr.data;
FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), index);
-
+
if (fcu) {
- success = insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, ts->keyframe_type, 0);
+ success = insert_keyframe_direct(depsgraph, op->reports, ptr, prop, fcu, cfra, ts->keyframe_type, 0);
}
else {
BKE_report(op->reports, RPT_ERROR,
@@ -1804,29 +1824,52 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
/* 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(op->reports, ptr, prop, fcu, cfra, ts->keyframe_type, INSERTKEY_DRIVER);
+ success = insert_keyframe_direct(depsgraph, op->reports, ptr, prop, fcu, cfra, ts->keyframe_type, 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 behaviour in this case.
+ *
+ * TODO: Perhaps we can extend this behaviour 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(op->reports, ptr.id.data, NULL, NULL, path, index, cfra, ts->keyframe_type, flag);
-
+
+ success = insert_keyframe(bmain, depsgraph, op->reports, ptr.id.data, NULL, group, path, index, cfra, ts->keyframe_type, flag);
+
MEM_freeN(path);
}
else {
- BKE_report(op->reports, RPT_WARNING,
+ BKE_report(op->reports, RPT_WARNING,
"Failed to resolve path to property, "
"try manually specifying this using a Keying Set instead");
}
@@ -1834,7 +1877,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
}
else {
if (prop && !RNA_property_animateable(&ptr, prop)) {
- BKE_reportf(op->reports, RPT_WARNING,
+ BKE_reportf(op->reports, RPT_WARNING,
"\"%s\" property cannot be animated",
RNA_property_identifier(prop));
}
@@ -1844,15 +1887,15 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
(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_ADDED, NULL);
}
-
+
return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
@@ -1862,11 +1905,11 @@ void ANIM_OT_keyframe_insert_button(wmOperatorType *ot)
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->exec = insert_key_button_exec;
ot->poll = modify_key_op_poll;
-
+
/* flags */
ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
@@ -1886,7 +1929,7 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
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 */
@@ -1902,7 +1945,7 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
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,
@@ -1916,7 +1959,7 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
*/
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) {
@@ -1930,13 +1973,13 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
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(op->reports, ptr.id.data, NULL, NULL, path, index, cfra, 0);
MEM_freeN(path);
}
@@ -1947,16 +1990,16 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
else if (G.debug & G_DEBUG) {
printf("ptr.data = %p, prop = %p\n", (void *)ptr.data, (void *)prop);
}
-
-
+
+
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;
}
@@ -1966,11 +2009,11 @@ void ANIM_OT_keyframe_delete_button(wmOperatorType *ot)
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->exec = delete_key_button_exec;
ot->poll = modify_key_op_poll;
-
+
/* flags */
ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
@@ -1998,13 +2041,13 @@ static int clear_key_button_exec(bContext *C, wmOperator *op)
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(op->reports, ptr.id.data, NULL, NULL, path, index, 0);
MEM_freeN(path);
}
@@ -2019,7 +2062,7 @@ static int clear_key_button_exec(bContext *C, wmOperator *op)
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);
}
@@ -2051,11 +2094,11 @@ 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
@@ -2070,7 +2113,7 @@ bool autokeyframe_cfra_can_key(Scene *scene, ID *id)
* 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;
}
@@ -2087,12 +2130,12 @@ 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
*/
@@ -2102,26 +2145,26 @@ bool fcurve_frame_has_keyframe(FCurve *fcu, float frame, short filter)
return true;
}
}
-
+
return false;
}
-/* Checks whether an Action has a keyframe for a given frame
+/* Checks whether an Action has a keyframe for a given frame
* Since we're only concerned whether a keyframe exists, we can simply loop until a match is found...
*/
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
+
+ /* 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) {
@@ -2131,7 +2174,7 @@ static bool action_frame_has_keyframe(bAction *act, float frame, short filter)
return true;
}
}
-
+
/* nothing found */
return false;
}
@@ -2142,27 +2185,27 @@ 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,
+ /* 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')
+
+ /* 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;
@@ -2176,24 +2219,24 @@ static bool object_frame_has_keyframe(Object *ob, float frame, short filter)
/* 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;
}
@@ -2206,7 +2249,7 @@ 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 */
@@ -2219,15 +2262,15 @@ bool id_frame_has_keyframe(ID *id, float frame, short filter)
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;
}
diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c
index a3c7a23f8ee..5bf23a53819 100644
--- a/source/blender/editors/animation/keyingsets.c
+++ b/source/blender/editors/animation/keyingsets.c
@@ -29,7 +29,7 @@
* \ingroup edanimation
*/
-
+
#include <stdio.h>
#include <stddef.h>
#include <string.h>
@@ -84,10 +84,10 @@ static int keyingset_poll_default_add(bContext *C)
static int keyingset_poll_active_edit(bContext *C)
{
Scene *scene = CTX_data_scene(C);
-
+
if (scene == NULL)
return 0;
-
+
/* there must be an active KeyingSet (and KeyingSets) */
return ((scene->active_keyingset > 0) && (scene->keyingsets.first));
}
@@ -97,42 +97,42 @@ static int 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));
}
-
+
/* 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;
-
- /* validate flags
+
+ /* 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);
-
+
/* 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);
-
+
/* send notifiers */
WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -142,7 +142,7 @@ void ANIM_OT_keying_set_add(wmOperatorType *ot)
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;
@@ -154,7 +154,7 @@ 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
@@ -169,17 +169,17 @@ static int remove_active_keyingset_exec(bContext *C, wmOperator *op)
}
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;
}
@@ -189,7 +189,7 @@ void ANIM_OT_keying_set_remove(wmOperatorType *ot)
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;
@@ -202,7 +202,7 @@ 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
@@ -213,16 +213,16 @@ static int add_empty_ks_path_exec(bContext *C, wmOperator *op)
}
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;
}
@@ -232,7 +232,7 @@ void ANIM_OT_keying_set_path_add(wmOperatorType *ot)
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;
@@ -244,15 +244,15 @@ 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--;
}
@@ -265,7 +265,7 @@ static int remove_active_ks_path_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "No active keying set to remove a path from");
return OPERATOR_CANCELLED;
}
-
+
return OPERATOR_FINISHED;
}
@@ -275,7 +275,7 @@ void ANIM_OT_keying_set_path_remove(wmOperatorType *ot)
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;
@@ -296,33 +296,33 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op)
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
+ * - add a new one if it doesn't exist
*/
if (scene->active_keyingset == 0) {
short flag = 0, keyingflag = 0;
-
- /* validate flags
+
+ /* 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))
+
+ 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) {
@@ -332,41 +332,41 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op)
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
+
+ /* 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;
}
@@ -376,11 +376,11 @@ void ANIM_OT_keyingset_button_add(wmOperatorType *ot)
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;
+ ot->exec = add_keyingset_button_exec;
//op->poll = ???
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -399,13 +399,13 @@ static int remove_keyingset_button_exec(bContext *C, wmOperator *op)
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
@@ -421,35 +421,35 @@ static int remove_keyingset_button_exec(bContext *C, wmOperator *op)
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;
}
@@ -459,11 +459,11 @@ void ANIM_OT_keyingset_button_remove(wmOperatorType *ot)
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;
+ ot->exec = remove_keyingset_button_exec;
//op->poll = ???
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -477,13 +477,13 @@ static int keyingset_active_menu_invoke(bContext *C, wmOperator *op, const wmEve
{
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);
-
+
return OPERATOR_INTERFACE;
}
@@ -491,33 +491,33 @@ static int keyingset_active_menu_exec(bContext *C, wmOperator *op)
{
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;
-
+
/* send notifiers */
WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL);
-
+
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->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);
@@ -541,7 +541,7 @@ KeyingSetInfo *ANIM_keyingset_info_find_name(const char name[])
/* sanity checks */
if ((name == NULL) || (name[0] == 0))
return NULL;
-
+
/* search by comparing names */
return BLI_findstring(&keyingset_type_infos, name, offsetof(KeyingSetInfo, idname));
}
@@ -550,17 +550,17 @@ KeyingSetInfo *ANIM_keyingset_info_find_name(const char name[])
KeyingSet *ANIM_builtin_keyingset_get_named(KeyingSet *prevKS, const char name[])
{
KeyingSet *ks, *first = 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;
-
+
/* loop over KeyingSets checking names */
for (ks = first; ks; ks = ks->next) {
if (STREQ(name, ks->idname))
@@ -582,18 +582,18 @@ KeyingSet *ANIM_builtin_keyingset_get_named(KeyingSet *prevKS, const char name[]
void ANIM_keyingset_info_register(KeyingSetInfo *ksi)
{
KeyingSet *ks;
-
- /* create a new KeyingSet
+
+ /* 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));
-
+
/* Copy description... */
BLI_strncpy(ks->description, ksi->description, sizeof(ks->description));
-
+
/* add type-info to the list */
BLI_addtail(&keyingset_type_infos, ksi);
}
@@ -621,7 +621,7 @@ void ANIM_keyingset_info_unregister(Main *bmain, KeyingSetInfo *ksi)
MEM_freeN(ks);
}
}
-
+
/* free the type info */
BLI_freelinkN(&keyingset_type_infos, ksi);
}
@@ -631,17 +631,17 @@ void ANIM_keyingset_info_unregister(Main *bmain, KeyingSetInfo *ksi)
void ANIM_keyingset_infos_exit(void)
{
KeyingSetInfo *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 builtin sets */
BKE_keyingsets_free(&builtin_keyingsets);
}
@@ -667,7 +667,7 @@ 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)
@@ -683,22 +683,22 @@ KeyingSet *ANIM_scene_get_active_keyingset(Scene *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
+ /* 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
+
+ /* still here, so try builtins list too
* - builtins are from (<= -1)
* - none/invalid is (= 0)
*/
@@ -712,15 +712,15 @@ int ANIM_scene_get_keyingset_index(Scene *scene, KeyingSet *ks)
/* Get Keying Set to use for Auto-Keyframing some transforms */
KeyingSet *ANIM_get_keyingset_for_autokeying(Scene *scene, const char *tranformKSName)
{
- /* get KeyingSet to use
- * - use the active KeyingSet if defined (and user wants to use it for all autokeying),
+ /* 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
+ else
return ANIM_builtin_keyingset_get_named(NULL, tranformKSName);
}
@@ -738,8 +738,8 @@ const EnumPropertyItem *ANIM_keying_sets_enum_itemf(bContext *C, PointerRNA *UNU
if (C == NULL) {
return DummyRNA_DEFAULT_items;
}
-
- /* active Keying Set
+
+ /* active Keying Set
* - only include entry if it exists
*/
if (scene->active_keyingset) {
@@ -748,14 +748,14 @@ const EnumPropertyItem *ANIM_keying_sets_enum_itemf(bContext *C, PointerRNA *UNU
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
+
+ /* user-defined Keying Sets
* - these are listed in the order in which they were defined for the active scene
*/
if (scene->keyingsets.first) {
@@ -768,11 +768,11 @@ const EnumPropertyItem *ANIM_keying_sets_enum_itemf(bContext *C, PointerRNA *UNU
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--) {
@@ -802,7 +802,7 @@ 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);
-
+
/* get the associated 'type info' for this KeyingSet */
if (ksi == NULL)
return 0;
@@ -811,13 +811,13 @@ bool ANIM_keyingset_context_ok_poll(bContext *C, KeyingSet *ks)
/* check if it can be used in the current context */
return (ksi->poll(ksi, C));
}
-
+
return true;
}
/* Special 'Overrides' Iterator for Relative KeyingSets ------ */
-/* 'Data Sources' for relative Keying Set 'overrides'
+/* 'Data Sources' for relative Keying Set 'overrides'
* - this is basically a wrapper for PointerRNA's in a linked list
* - do not allow this to be accessed from outside for now
*/
@@ -827,14 +827,14 @@ typedef struct tRKS_DSource {
} tRKS_DSource;
-/* Iterator used for overriding the behavior of iterators defined for
- * relative Keying Sets, with the main usage of this being operators
+/* 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)
{
tRKS_DSource *ds;
-
+
for (ds = dsources->first; ds; ds = ds->next) {
/* run generate callback on this data */
ksi->generate(ksi, C, ks, &ds->ptr);
@@ -845,8 +845,8 @@ static void RKS_ITER_overrides_list(KeyingSetInfo *ksi, bContext *C, KeyingSet *
void ANIM_relative_keyingset_add_source(ListBase *dsources, ID *id, StructRNA *srna, void *data)
{
tRKS_DSource *ds;
-
- /* sanity checks
+
+ /* 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
*/
@@ -854,11 +854,11 @@ void ANIM_relative_keyingset_add_source(ListBase *dsources, ID *id, StructRNA *s
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);
@@ -880,31 +880,31 @@ 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
+
+ /* 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)
+ 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))
@@ -916,16 +916,16 @@ short ANIM_validate_keyingset(bContext *C, ListBase *dsources, KeyingSet *ks)
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)
{
short result = 0;
-
+
/* 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
@@ -939,14 +939,14 @@ static short keyingset_apply_keying_flags(const short base_flags, const short ov
else { \
result |= (base_flags & kflag); \
}
-
- /* Apply the flags one by one...
+
+ /* 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;
@@ -958,6 +958,8 @@ static short keyingset_apply_keying_flags(const short base_flags, const short ov
*/
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;
@@ -965,11 +967,11 @@ int ANIM_apply_keyingset(bContext *C, ListBase *dsources, bAction *act, KeyingSe
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 */
@@ -977,20 +979,20 @@ int ANIM_apply_keyingset(bContext *C, ListBase *dsources, bAction *act, KeyingSe
}
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,
@@ -998,10 +1000,10 @@ int ANIM_apply_keyingset(bContext *C, ListBase *dsources, bAction *act, KeyingSe
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;
@@ -1009,59 +1011,59 @@ int ANIM_apply_keyingset(bContext *C, ListBase *dsources, bAction *act, KeyingSe
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);
i = 0; /* start from start of array, instead of the previously specified index - T48020 */
}
}
-
+
/* we should do at least one step */
if (arraylen == i)
arraylen++;
-
- /* for each possible index, perform operation
+
+ /* 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(reports, ksp->id, act, groupname, ksp->rna_path, i, cfra, keytype, kflag2);
+ success += insert_keyframe(bmain, depsgraph, reports, ksp->id, act, groupname, ksp->rna_path, i, cfra, keytype, kflag2);
else if (mode == MODIFYKEY_MODE_DELETE)
success += delete_keyframe(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, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
break;
}
default:
DEG_id_tag_update(ksp->id, DEG_TAG_COPY_ON_WRITE);
break;
}
-
+
/* send notifiers for updates (this doesn't require context to work!) */
WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
}
-
+
/* return the number of channels successfully affected */
return success;
}
diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c
index 07c9225c443..c1fb1dcf82f 100644
--- a/source/blender/editors/armature/armature_add.c
+++ b/source/blender/editors/armature/armature_add.c
@@ -66,12 +66,12 @@
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;
@@ -81,7 +81,7 @@ EditBone *ED_armature_ebone_add(bArmature *arm, const char *name)
bone->rad_tail = 0.05f;
bone->segments = 1;
bone->layer = arm->layer;
-
+
/* Bendy-Bone parameters */
bone->roll1 = 0.0f;
bone->roll2 = 0.0f;
@@ -103,7 +103,7 @@ EditBone *ED_armature_ebone_add_primitive(Object *obedit_arm, float length, bool
EditBone *bone;
ED_armature_edit_deselect_all(obedit_arm);
-
+
/* Create a bone */
bone = ED_armature_ebone_add(arm, "Bone");
@@ -134,7 +134,7 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op))
v3d = CTX_wm_view3d(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)) {
@@ -142,7 +142,7 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op))
break;
}
}
-
+
if (ebone == NULL) {
for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
if (EBONE_VISIBLE(arm, ebone)) {
@@ -150,14 +150,14 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op))
break;
}
}
- if (ebone == NULL)
+ 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)
@@ -171,10 +171,10 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op))
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;
@@ -186,28 +186,28 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op))
newbone->parent = ebone;
newbone->flag |= BONE_CONNECTED;
}
-
+
const View3DCursor *curs = ED_view3d_cursor3d_get(scene, v3d);
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;
}
@@ -226,9 +226,9 @@ static int armature_click_extrude_invoke(bContext *C, wmOperator *op, const wmEv
scene = CTX_data_scene(C);
ar = CTX_wm_region(C);
v3d = CTX_wm_view3d(C);
-
+
View3DCursor *cursor = ED_view3d_cursor3d_get(scene, v3d);
-
+
copy_v3_v3(oldcurs, cursor->location);
VECCOPY2D(mval_f, event->mval);
@@ -250,12 +250,12 @@ void ARMATURE_OT_click_extrude(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -266,12 +266,12 @@ void ARMATURE_OT_click_extrude(wmOperatorType *ot)
EditBone *add_points_bone(Object *obedit, float head[3], float tail[3])
{
EditBone *ebo;
-
+
ebo = ED_armature_ebone_add(obedit->data, "Bone");
-
+
copy_v3_v3(ebo->head, head);
copy_v3_v3(ebo->tail, tail);
-
+
return ebo;
}
@@ -377,7 +377,7 @@ void updateDuplicateSubtargetObjects(EditBone *dupBone, ListBase *editbones, Obj
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) {
@@ -387,17 +387,17 @@ void updateDuplicateSubtargetObjects(EditBone *dupBone, ListBase *editbones, Obj
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 */
+ 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
+ * so, update the constraint to point at the
* duplicate of the old subtarget.
*/
if (oldtarget->temp.ebone) {
@@ -407,7 +407,7 @@ void updateDuplicateSubtargetObjects(EditBone *dupBone, ListBase *editbones, Obj
}
}
}
-
+
if (cti->flush_constraint_targets)
cti->flush_constraint_targets(curcon, &targets, 0);
}
@@ -426,20 +426,20 @@ EditBone *duplicateEditBoneObjects(EditBone *curBone, const char *name, ListBase
Object *src_ob, Object *dst_ob)
{
EditBone *eBone = MEM_mallocN(sizeof(EditBone), "addup_editbone");
-
+
/* Copy data from old bone to new bone */
memcpy(eBone, curBone, sizeof(EditBone));
-
+
curBone->temp.ebone = eBone;
eBone->temp.ebone = curBone;
-
+
if (name != NULL) {
BLI_strncpy(eBone->name, name, sizeof(eBone->name));
}
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);
@@ -449,7 +449,7 @@ EditBone *duplicateEditBoneObjects(EditBone *curBone, const char *name, ListBase
*/
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
@@ -462,7 +462,7 @@ EditBone *duplicateEditBoneObjects(EditBone *curBone, const char *name, ListBase
}
}
}
-
+
return eBone;
}
@@ -506,7 +506,7 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
}
}
-
+
/* 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) &&
@@ -567,7 +567,7 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
updateDuplicateSubtarget(ebone, arm->edbo, obedit);
}
}
-
+
/* correct the active bone */
if (arm->act_edbone && arm->act_edbone->temp.ebone) {
arm->act_edbone = arm->act_edbone->temp.ebone;
@@ -585,7 +585,7 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
ED_armature_edit_validate_active(arm);
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
-
+
return OPERATOR_FINISHED;
}
@@ -596,11 +596,11 @@ void ARMATURE_OT_duplicate(wmOperatorType *ot)
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;
@@ -846,7 +846,7 @@ static int armature_extrude_exec(bContext *C, wmOperator *op)
}
}
}
-
+
/* Duplicate the necessary bones */
for (ebone = arm->edbo->first; ((ebone) && (ebone != first)); ebone = ebone->next) {
if (EBONE_VISIBLE(arm, ebone)) {
@@ -864,7 +864,7 @@ static int armature_extrude_exec(bContext *C, wmOperator *op)
do_extrude = 2;
}
}
-
+
if (do_extrude) {
/* we re-use code for mirror editing... */
flipbone = NULL;
@@ -879,7 +879,7 @@ static int armature_extrude_exec(bContext *C, wmOperator *op)
if ((flipbone == NULL) && (forked))
flipbone = ebone;
}
-
+
for (a = 0; a < 2; a++) {
if (a == 1) {
if (flipbone == NULL)
@@ -888,31 +888,31 @@ static int armature_extrude_exec(bContext *C, wmOperator *op)
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;
-
+
newbone->flag = ebone->flag & (BONE_TIPSEL | BONE_RELATIVE_PARENTING); // copies it, in case mirrored bone
-
+
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;
@@ -921,7 +921,7 @@ static int armature_extrude_exec(bContext *C, wmOperator *op)
newbone->rad_tail = ebone->rad_tail;
newbone->segments = 1;
newbone->layer = ebone->layer;
-
+
/* Bendy-Bone parameters */
newbone->roll1 = ebone->roll1;
newbone->roll2 = ebone->roll2;
@@ -936,7 +936,7 @@ static int armature_extrude_exec(bContext *C, wmOperator *op)
BLI_strncpy(newbone->name, ebone->name, sizeof(newbone->name));
-
+
if (flipbone && forked) { // only set if mirror edit
if (strlen(newbone->name) < (MAXBONENAME - 2)) {
if (a == 0) strcat(newbone->name, "_L");
@@ -944,18 +944,18 @@ static int armature_extrude_exec(bContext *C, wmOperator *op)
}
}
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);
}
@@ -986,14 +986,14 @@ void ARMATURE_OT_extrude(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* props */
RNA_def_boolean(ot->srna, "forked", 0, "Forked", "");
}
@@ -1002,16 +1002,16 @@ void ARMATURE_OT_extrude(wmOperatorType *ot)
/*op makes a new bone and returns it with its tip selected */
-static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op)
+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];
-
+
RNA_string_get(op->ptr, "name", name);
-
+
copy_v3_v3(curs, ED_view3d_cursor3d_get(CTX_data_scene(C), CTX_wm_view3d(C))->location);
/* Get inverse point for head and orientation for tail */
@@ -1021,18 +1021,18 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op)
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);
-
+
ED_armature_edit_deselect_all(obedit);
-
+
/* Create a bone */
bone = ED_armature_ebone_add(obedit->data, name);
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
@@ -1050,23 +1050,23 @@ void ARMATURE_OT_bone_primitive_add(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
RNA_def_string(ot->srna, "name", "Bone", MAXBONENAME, "Name", "Name of the newly created bone");
-
+
}
/* ********************** Subdivide *******************************/
/* Subdivide Operators:
* This group of operators all use the same 'exec' callback, but they are called
- * through several different operators - a combined menu (which just calls the exec in the
+ * through several different operators - a combined menu (which just calls the exec in the
* appropriate ways), and two separate ones.
*/
@@ -1075,10 +1075,10 @@ 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)
@@ -1087,37 +1087,37 @@ static int armature_subdivide_exec(bContext *C, wmOperator *op)
/* 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)
@@ -1127,10 +1127,10 @@ static int armature_subdivide_exec(bContext *C, wmOperator *op)
}
}
CTX_DATA_END;
-
+
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
-
+
return OPERATOR_FINISHED;
}
@@ -1142,14 +1142,14 @@ void ARMATURE_OT_subdivide(wmOperatorType *ot)
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;
-
+
/* 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) */
diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c
index 7372be8896f..ccc1eefd9dc 100644
--- a/source/blender/editors/armature/armature_edit.c
+++ b/source/blender/editors/armature/armature_edit.c
@@ -29,7 +29,7 @@
* \ingroup edarmature
*/
-#include <assert.h>
+#include <assert.h>
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
@@ -50,6 +50,7 @@
#include "BKE_context.h"
#include "BKE_layer.h"
#include "BKE_global.h"
+#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_object.h"
@@ -68,7 +69,7 @@
/* ************************** Object Tools Exports ******************************* */
/* NOTE: these functions are exported to the Object module to be called from the tools there */
-void ED_armature_transform_apply(Object *ob, float mat[4][4], const bool do_props)
+void ED_armature_transform_apply(Main *bmain, Object *ob, float mat[4][4], const bool do_props)
{
bArmature *arm = ob->data;
@@ -79,7 +80,7 @@ void ED_armature_transform_apply(Object *ob, float mat[4][4], const bool do_prop
ED_armature_transform_bones(arm, mat, do_props);
/* Turn the list into an armature */
- ED_armature_from_edit(arm);
+ ED_armature_from_edit(bmain, arm);
ED_armature_edit_free(arm);
}
@@ -94,20 +95,20 @@ void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4], const b
/* 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;
@@ -120,7 +121,7 @@ void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4], const b
}
}
-void ED_armature_transform(struct bArmature *arm, float mat[4][4], const bool do_props)
+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);
@@ -133,14 +134,14 @@ void ED_armature_transform(struct bArmature *arm, float mat[4][4], const bool do
ED_armature_transform_bones(arm, mat, do_props);
/* Go back to object mode*/
- ED_armature_from_edit(arm);
+ 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(Object *ob, float cursor[3], int centermode, int around)
+void ED_armature_origin_set(Main *bmain, Object *ob, float cursor[3], int centermode, int around)
{
const bool is_editmode = BKE_object_is_in_editmode(ob);
EditBone *ebone;
@@ -181,16 +182,16 @@ void ED_armature_origin_set(Object *ob, float cursor[3], int centermode, int aro
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(arm);
+ ED_armature_from_edit(bmain, arm);
ED_armature_edit_free(arm);
}
@@ -292,7 +293,7 @@ static const EnumPropertyItem prop_calc_roll_types[] = {
};
-static int armature_calc_roll_exec(bContext *C, wmOperator *op)
+static int armature_calc_roll_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_edit_object(C);
eCalcRollTypes type = RNA_enum_get(op->ptr, "type");
@@ -319,12 +320,12 @@ static int armature_calc_roll_exec(bContext *C, wmOperator *op)
View3D *v3d = CTX_wm_view3d(C); /* can be NULL */
float cursor_local[3];
const View3DCursor *cursor = ED_view3d_cursor3d_get(scene, v3d);
-
+
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)) {
@@ -393,7 +394,7 @@ static int armature_calc_roll_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "No region view3d available");
return OPERATOR_CANCELLED;
}
-
+
copy_v3_v3(vec, rv3d->viewinv[2]);
mul_m3_v3(imat, vec);
}
@@ -404,7 +405,7 @@ static int armature_calc_roll_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "No active bone set");
return OPERATOR_CANCELLED;
}
-
+
ED_armature_ebone_to_mat3(ebone, mat);
copy_v3_v3(vec, mat[2]);
}
@@ -415,9 +416,9 @@ static int armature_calc_roll_exec(bContext *C, wmOperator *op)
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 */
@@ -425,7 +426,7 @@ static int armature_calc_roll_exec(bContext *C, wmOperator *op)
}
}
}
-
+
if (arm->flag & ARM_MIRROR_EDIT) {
for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
if ((EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) == 0) {
@@ -436,10 +437,10 @@ static int armature_calc_roll_exec(bContext *C, wmOperator *op)
}
}
}
-
+
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -449,12 +450,12 @@ void ARMATURE_OT_calculate_roll(wmOperatorType *ot)
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;
@@ -521,10 +522,10 @@ void ARMATURE_OT_roll_clear(wmOperatorType *ot)
/* temporary data-structure for merge/fill bones */
typedef struct EditBonePoint {
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 */
-
+
float vec[3]; /* the actual location of the point in local/EditMode space */
} EditBonePoint;
@@ -533,11 +534,11 @@ 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) {
@@ -546,12 +547,12 @@ static void chains_find_tips(ListBase *edbo, ListBase *list)
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) {
@@ -562,12 +563,12 @@ static void chains_find_tips(ListBase *edbo, ListBase *list)
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;
@@ -582,14 +583,14 @@ 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) {
@@ -610,11 +611,11 @@ static void fill_add_joint(EditBone *ebo, short eb_tail, ListBase *points)
}
}
}
-
+
/* 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;
@@ -623,7 +624,7 @@ static void fill_add_joint(EditBone *ebo, short eb_tail, ListBase *points)
copy_v3_v3(ebp->vec, ebo->head);
ebp->head_owner = ebo;
}
-
+
BLI_addtail(points, ebp);
}
}
@@ -666,7 +667,7 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op)
}
}
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)
@@ -699,14 +700,14 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op)
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, ED_view3d_cursor3d_get(scene, v3d)->location);
-
+
/* Create a bone */
newbone = add_points_bone(obedit, ebp->vec, curs);
}
@@ -714,11 +715,11 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op)
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)))
{
@@ -726,7 +727,7 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op)
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 */
@@ -759,7 +760,7 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op)
else if (ebp_b->head_owner) {
headtail = 2;
}
-
+
/* assign head/tail combinations */
if (headtail == 2) {
copy_v3_v3(head, ebp_a->vec);
@@ -769,11 +770,11 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op)
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 */
@@ -808,13 +809,13 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op)
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;
}
@@ -824,18 +825,18 @@ void ARMATURE_OT_fill(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* --------------------- */
-/* this function merges between two bones, removes them and those in-between,
+/* 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)
@@ -844,7 +845,7 @@ static void bones_merge(Object *obedit, EditBone *start, EditBone *end, EditBone
EditBone *ebo, *ebone, *newbone;
LinkData *chain;
float head[3], tail[3];
-
+
/* check if same bone */
if (start == end) {
if (G.debug & G_DEBUG) {
@@ -852,7 +853,7 @@ static void bones_merge(Object *obedit, EditBone *start, EditBone *end, EditBone
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)
@@ -876,17 +877,17 @@ static void bones_merge(Object *obedit, EditBone *start, EditBone *end, EditBone
/* 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
+
+ /* 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!)
+ /* 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
*/
@@ -898,23 +899,23 @@ static void bones_merge(Object *obedit, EditBone *start, EditBone *end, EditBone
break;
}
}
-
+
/* carry on to the next tip now */
- if (found)
+ 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);
}
@@ -925,33 +926,33 @@ static int armature_merge_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
bArmature *arm = (obedit) ? obedit->data : NULL;
short type = RNA_enum_get(op->ptr, "type");
-
+
/* sanity checks */
if (ELEM(NULL, obedit, arm))
return OPERATOR_CANCELLED;
-
+
/* 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)) return OPERATOR_CANCELLED;
-
+
/* 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 */
@@ -964,37 +965,37 @@ static int armature_merge_exec(bContext *C, wmOperator *op)
bend = ebo;
bchild = child;
}
- else
+ else
bstart = ebo;
}
else {
/* chain is broken... merge any continous 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);
-
+
return OPERATOR_FINISHED;
}
@@ -1009,15 +1010,15 @@ void ARMATURE_OT_merge(wmOperatorType *ot)
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", "");
}
@@ -1029,41 +1030,41 @@ void ARMATURE_OT_merge(wmOperatorType *ot)
* easy to retrieve any hierarchical/chain relationships which are necessary for
* this to be done easily.
*/
-
+
/* helper to clear BONE_TRANSFORM flags */
static void armature_clear_swap_done_flags(bArmature *arm)
{
EditBone *ebone;
-
+
for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
ebone->flag &= ~BONE_TRANSFORM;
}
}
-static int armature_switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
+static int armature_switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = CTX_data_edit_object(C);
bArmature *arm = (bArmature *)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)) return OPERATOR_CANCELLED;
-
+
/* ensure that mirror bones will also be operated on */
armature_tag_select_mirrored(arm);
-
- /* clear BONE_TRANSFORM flags
+
+ /* 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
@@ -1071,14 +1072,14 @@ static int armature_switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
* 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
@@ -1088,44 +1089,44 @@ static int armature_switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
ebo->flag |= BONE_CONNECTED;
else
ebo->flag &= ~BONE_CONNECTED;
-
- /* get next bones
+
+ /* 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
+ /* 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,
+ * - 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);
-
+
return OPERATOR_FINISHED;
}
@@ -1135,11 +1136,11 @@ void ARMATURE_OT_switch_direction(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1150,10 +1151,10 @@ void ARMATURE_OT_switch_direction(wmOperatorType *ot)
static void fix_connected_bone(EditBone *ebone)
{
float diff[3];
-
+
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);
@@ -1164,14 +1165,14 @@ static void fix_connected_bone(EditBone *ebone)
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);
}
}
-}
+}
static void bone_align_to_bone(ListBase *edbo, EditBone *selbone, EditBone *actbone)
{
@@ -1186,21 +1187,21 @@ static void bone_align_to_bone(ListBase *edbo, EditBone *selbone, EditBone *actb
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);
}
-static int armature_align_bones_exec(bContext *C, wmOperator *op)
+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");
@@ -1208,28 +1209,28 @@ static int armature_align_bones_exec(bContext *C, wmOperator *op)
}
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
+ * - 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)
+ if (actmirb == NULL)
actmirb = actbone;
}
-
- /* if there is only 1 selected bone, we assume that that is the active bone,
+
+ /* 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.
+ * 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);
@@ -1240,11 +1241,11 @@ static int armature_align_bones_exec(bContext *C, wmOperator *op)
/* 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
+ * - 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)
{
@@ -1262,7 +1263,7 @@ static int armature_align_bones_exec(bContext *C, wmOperator *op)
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -1272,11 +1273,11 @@ void ARMATURE_OT_align(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1373,6 +1374,7 @@ static int armature_delete_selected_exec(bContext *C, wmOperator *UNUSED(op))
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
}
}
+ MEM_freeN(objects);
if (!changed_multi) {
return OPERATOR_CANCELLED;
@@ -1387,12 +1389,12 @@ void ARMATURE_OT_delete(wmOperatorType *ot)
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;
}
@@ -1596,11 +1598,11 @@ void ARMATURE_OT_hide(wmOperatorType *ot)
ot->name = "Hide Selected Bones";
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1614,7 +1616,7 @@ static int armature_reveal_exec(bContext *C, wmOperator *op)
bArmature *arm = obedit->data;
EditBone *ebone;
const bool select = RNA_boolean_get(op->ptr, "select");
-
+
for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
if (arm->layer & ebone->layer) {
if (ebone->flag & BONE_HIDDEN_A) {
@@ -1639,11 +1641,11 @@ void ARMATURE_OT_reveal(wmOperatorType *ot)
ot->name = "Reveal Bones";
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h
index c40872cbd3a..a37a2bada08 100644
--- a/source/blender/editors/armature/armature_intern.h
+++ b/source/blender/editors/armature/armature_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -146,25 +146,25 @@ void POSE_OT_toggle_bone_selection_overlay(struct wmOperatorType *ot);
/* Temporary data linking PoseChannels with the F-Curves they affect */
typedef struct tPChanFCurveLink {
struct tPChanFCurveLink *next, *prev;
-
+
ListBase fcurves; /* F-Curves for this PoseChannel (wrapped with LinkData) */
struct bPoseChannel *pchan; /* Pose Channel which data is attached to */
-
+
char *pchan_path; /* RNA Path to this Pose Channel (needs to be freed when we're done) */
-
+
float oldloc[3]; /* transform values at start of operator (to be restored before each modal step) */
float oldrot[3];
float oldscale[3];
float oldquat[4];
float oldangle;
float oldaxis[3];
-
+
float roll1, roll2; /* old bbone values (to be restored along with the transform properties) */
float curveInX, curveInY; /* (NOTE: we haven't renamed these this time, as their names are already long enough) */
float curveOutX, curveOutY;
float ease1, ease2;
float scaleIn, scaleOut;
-
+
struct IDProperty *oldprops; /* copy of custom properties at start of operator (to be restored before each modal step) */
} tPChanFCurveLink;
@@ -251,4 +251,3 @@ int bone_looper(struct Object *ob, struct Bone *bone, void *data,
#endif /* __ARMATURE_INTERN_H__ */
-
diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c
index e8d45f72f89..350dee07a2c 100644
--- a/source/blender/editors/armature/armature_naming.c
+++ b/source/blender/editors/armature/armature_naming.c
@@ -105,15 +105,15 @@ static void constraint_bone_name_fix(Object *ob, ListBase *conlist, const char *
{
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)) {
@@ -121,11 +121,11 @@ static void constraint_bone_name_fix(Object *ob, ListBase *conlist, const char *
}
}
}
-
+
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;
@@ -137,24 +137,24 @@ static void constraint_bone_name_fix(Object *ob, ListBase *conlist, const char *
/* called by UI for renaming a bone */
/* warning: make sure the original bone was not renamed yet! */
/* seems messy, but thats what you get with not using pointers but channel names :) */
-void ED_armature_bone_rename(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);
@@ -165,7 +165,7 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n
}
else {
Bone *bone = BKE_armature_find_bone_name(arm, oldname);
-
+
if (bone) {
unique_bone_name(arm, newname);
BLI_strncpy(bone->name, newname, MAXBONENAME);
@@ -174,15 +174,15 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n
return;
}
}
-
+
/* do entire dbase - objects */
- for (ob = G.main->object.first; ob; ob = ob->id.next) {
+ for (ob = bmain->object.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);
@@ -204,9 +204,9 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n
BLI_assert(BKE_pose_channels_is_valid(ob->pose) == true);
}
-
+
/* Update any object constraints to use the new bone name */
- for (cob = G.main->object.first; cob; cob = cob->id.next) {
+ for (cob = bmain->object.first; cob; cob = cob->id.next) {
if (cob->constraints.first)
constraint_bone_name_fix(ob, &cob->constraints, oldname, newname);
if (cob->pose) {
@@ -217,7 +217,7 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n
}
}
}
-
+
/* See if an object is parented to this armature */
if (ob->parent && (ob->parent->data == arm)) {
if (ob->partype == PARBONE) {
@@ -226,14 +226,14 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n
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) {
@@ -266,20 +266,20 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n
}
}
}
-
+
/* 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 = G.main->screen.first; screen; screen = screen->id.next) {
+ for (screen = bmain->screen.first; screen; screen = screen->id.next) {
ScrArea *sa;
/* add regions */
for (sa = screen->areabase.first; sa; sa = sa->next) {
@@ -316,7 +316,7 @@ 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(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;
@@ -332,7 +332,7 @@ void ED_armature_bones_flip_names(bArmature *arm, ListBase *bones_names, const b
* 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(arm, name, name_flip);
+ ED_armature_bone_rename(bmain, arm, name, name_flip);
if (!STREQ(name, name_flip)) {
bfn = alloca(sizeof(BoneFlipNameData));
@@ -346,7 +346,7 @@ void ED_armature_bones_flip_names(bArmature *arm, ListBase *bones_names, const b
* 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(arm, bfn->name, bfn->name_flip);
+ ED_armature_bone_rename(bmain, arm, bfn->name, bfn->name_flip);
}
}
@@ -355,6 +355,7 @@ void ED_armature_bones_flip_names(bArmature *arm, ListBase *bones_names, const b
static int armature_flip_names_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
Object *ob = CTX_data_edit_object(C);
bArmature *arm;
@@ -374,10 +375,10 @@ static int armature_flip_names_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- ED_armature_bones_flip_names(arm, &bones_names, do_strip_numbers);
+ 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, OB_RECALC_DATA);
@@ -397,11 +398,11 @@ void ARMATURE_OT_flip_names(wmOperatorType *ot)
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;
@@ -413,31 +414,32 @@ void ARMATURE_OT_flip_names(wmOperatorType *ot)
static int armature_autoside_names_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
Object *ob = CTX_data_edit_object(C);
bArmature *arm;
char newname[MAXBONENAME];
short axis = RNA_enum_get(op->ptr, "type");
-
+
/* paranoia checks */
- if (ELEM(NULL, ob, ob->pose))
+ if (ELEM(NULL, ob, ob->pose))
return OPERATOR_CANCELLED;
arm = ob->data;
-
+
/* loop through selected bones, auto-naming them */
CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
{
BLI_strncpy(newname, ebone->name, sizeof(newname));
if (bone_autoside_name(newname, 1, axis, ebone->head[axis], ebone->tail[axis]))
- ED_armature_bone_rename(arm, ebone->name, newname);
+ ED_armature_bone_rename(bmain, arm, ebone->name, newname);
}
CTX_DATA_END;
-
+
/* since we renamed stuff... */
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -449,21 +451,20 @@ void ARMATURE_OT_autoside_names(wmOperatorType *ot)
{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 8dfc11aea19..e54769221f5 100644
--- a/source/blender/editors/armature/armature_ops.c
+++ b/source/blender/editors/armature/armature_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -46,16 +46,16 @@ 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);
@@ -77,10 +77,10 @@ void ED_operatortypes_armature(void)
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);
@@ -88,19 +88,19 @@ void ED_operatortypes_armature(void)
/* 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);
@@ -109,7 +109,7 @@ void ED_operatortypes_armature(void)
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);
@@ -118,38 +118,38 @@ void ED_operatortypes_armature(void)
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_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_toggle_bone_selection_overlay);
-
+
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);
@@ -191,7 +191,7 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
wmKeyMapItem *kmi;
-
+
/* Armature ------------------------ */
keymap = WM_keymap_find(keyconf, "Armature", 0, 0);
keymap->poll = ED_operator_editarmature;
@@ -204,16 +204,20 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "ARMATURE_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "ARMATURE_OT_align", AKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "ARMATURE_OT_calculate_roll", NKEY, KM_PRESS, KM_CTRL, 0);
+#else
+ WM_keymap_add_item(keymap, "ARMATURE_OT_calculate_roll", NKEY, KM_PRESS, KM_SHIFT, 0);
+#endif
WM_keymap_add_item(keymap, "ARMATURE_OT_roll_clear", RKEY, KM_PRESS, KM_ALT, 0);
-
+
WM_keymap_add_item(keymap, "ARMATURE_OT_switch_direction", FKEY, KM_PRESS, KM_ALT, 0);
-
+
WM_keymap_add_item(keymap, "ARMATURE_OT_bone_primitive_add", AKEY, KM_PRESS, KM_SHIFT, 0);
-
+
WM_keymap_add_item(keymap, "ARMATURE_OT_parent_set", PKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "ARMATURE_OT_parent_clear", PKEY, KM_PRESS, KM_ALT, 0);
-
+
kmi = WM_keymap_add_item(keymap, "ARMATURE_OT_select_all", AKEY, KM_PRESS, 0, 0);
RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE);
kmi = WM_keymap_add_item(keymap, "ARMATURE_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0);
@@ -221,14 +225,14 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "ARMATURE_OT_select_mirror", MKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "extend", false);
-
+
kmi = WM_keymap_add_item(keymap, "ARMATURE_OT_select_hierarchy", LEFTBRACKETKEY, KM_PRESS, 0, 0);
RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_PARENT);
RNA_boolean_set(kmi->ptr, "extend", false);
kmi = WM_keymap_add_item(keymap, "ARMATURE_OT_select_hierarchy", LEFTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_PARENT);
RNA_boolean_set(kmi->ptr, "extend", true);
-
+
kmi = WM_keymap_add_item(keymap, "ARMATURE_OT_select_hierarchy", RIGHTBRACKETKEY, KM_PRESS, 0, 0);
RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_CHILD);
RNA_boolean_set(kmi->ptr, "extend", false);
@@ -244,8 +248,10 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "ARMATURE_OT_select_linked", LKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "ARMATURE_OT_shortest_path_pick", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
-
+
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_armature_delete", XKEY, KM_PRESS, 0, 0);
+#endif
WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_armature_delete", DELKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "ARMATURE_OT_dissolve", XKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "ARMATURE_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
@@ -255,19 +261,19 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "ARMATURE_OT_fill", FKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "ARMATURE_OT_merge", MKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "ARMATURE_OT_split", YKEY, KM_PRESS, 0, 0);
-
+
WM_keymap_add_item(keymap, "ARMATURE_OT_separate", PKEY, KM_PRESS, 0, 0);
-
+
/* set flags */
WM_keymap_add_menu(keymap, "VIEW3D_MT_bone_options_toggle", WKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_menu(keymap, "VIEW3D_MT_bone_options_enable", WKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
WM_keymap_add_menu(keymap, "VIEW3D_MT_bone_options_disable", WKEY, KM_PRESS, KM_ALT, 0);
-
+
/* armature/bone layers */
WM_keymap_add_item(keymap, "ARMATURE_OT_layers_show_all", ACCENTGRAVEKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "ARMATURE_OT_armature_layers", MKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "ARMATURE_OT_bone_layers", MKEY, KM_PRESS, 0, 0);
-
+
/* special transforms: */
/* 1) envelope/b-bone size */
kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", SKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
@@ -278,7 +284,7 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
/* 3) set roll */
kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", RKEY, KM_PRESS, KM_CTRL, 0);
RNA_enum_set(kmi->ptr, "mode", TFM_BONE_ROLL);
-
+
/* menus */
WM_keymap_add_menu(keymap, "VIEW3D_MT_armature_specials", WKEY, KM_PRESS, 0, 0);
@@ -286,36 +292,36 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
/* only set in posemode, by space_view3d listener */
keymap = WM_keymap_find(keyconf, "Pose", 0, 0);
keymap->poll = ED_operator_posemode;
-
+
/* set parent and add object are object-based operators, but we make them
* available here because it's useful to do in pose mode too */
WM_keymap_add_item(keymap, "OBJECT_OT_parent_set", PKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_menu(keymap, "INFO_MT_add", AKEY, KM_PRESS, KM_SHIFT, 0);
-
+
kmi = WM_keymap_add_item(keymap, "POSE_OT_hide", HKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "unselected", false);
kmi = WM_keymap_add_item(keymap, "POSE_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "unselected", true);
WM_keymap_add_item(keymap, "POSE_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0);
-
+
WM_keymap_add_menu(keymap, "VIEW3D_MT_pose_apply", AKEY, KM_PRESS, KM_CTRL, 0);
-
+
/* TODO: clear pose */
WM_keymap_add_item(keymap, "POSE_OT_rot_clear", RKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "POSE_OT_loc_clear", GKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "POSE_OT_scale_clear", SKEY, KM_PRESS, KM_ALT, 0);
-
+
WM_keymap_add_item(keymap, "POSE_OT_quaternions_flip", FKEY, KM_PRESS, KM_ALT, 0);
-
+
WM_keymap_add_item(keymap, "POSE_OT_rotation_mode_set", RKEY, KM_PRESS, KM_CTRL, 0);
-
+
WM_keymap_add_item(keymap, "POSE_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
kmi = WM_keymap_add_item(keymap, "POSE_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "flipped", false);
kmi = WM_keymap_add_item(keymap, "POSE_OT_paste", VKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "flipped", true);
-
+
#ifdef __APPLE__
WM_keymap_add_item(keymap, "POSE_OT_copy", CKEY, KM_PRESS, KM_OSKEY, 0);
kmi = WM_keymap_add_item(keymap, "POSE_OT_paste", VKEY, KM_PRESS, KM_OSKEY, 0);
@@ -337,7 +343,7 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "POSE_OT_select_hierarchy", LEFTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_PARENT);
RNA_boolean_set(kmi->ptr, "extend", true);
-
+
kmi = WM_keymap_add_item(keymap, "POSE_OT_select_hierarchy", RIGHTBRACKETKEY, KM_PRESS, 0, 0);
RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_CHILD);
RNA_boolean_set(kmi->ptr, "extend", false);
@@ -348,14 +354,14 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "POSE_OT_select_linked", LKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "POSE_OT_select_grouped", GKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "POSE_OT_select_mirror", FKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
-
+
WM_keymap_add_item(keymap, "POSE_OT_constraint_add_with_targets", CKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
WM_keymap_add_item(keymap, "POSE_OT_constraints_clear", CKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
WM_keymap_add_item(keymap, "POSE_OT_ik_add", IKEY, KM_PRESS, /*KM_CTRL|*/ KM_SHIFT, 0);
WM_keymap_add_item(keymap, "POSE_OT_ik_clear", IKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
-
+
WM_keymap_add_menu(keymap, "VIEW3D_MT_pose_group", GKEY, KM_PRESS, KM_CTRL, 0);
-
+
/* set flags */
WM_keymap_add_menu(keymap, "VIEW3D_MT_bone_options_toggle", WKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_menu(keymap, "VIEW3D_MT_bone_options_enable", WKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
@@ -366,25 +372,25 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "ARMATURE_OT_armature_layers", MKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "POSE_OT_bone_layers", MKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "POSE_OT_toggle_bone_selection_overlay", ZKEY, KM_PRESS, 0, 0);
-
+
/* special transforms: */
/* 1) envelope/b-bone size */
kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", SKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
RNA_enum_set(kmi->ptr, "mode", TFM_BONESIZE);
-
+
/* keyframes management */
WM_keymap_verify_item(keymap, "ANIM_OT_keyframe_insert_menu", IKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "ANIM_OT_keyframe_delete_v3d", IKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_verify_item(keymap, "ANIM_OT_keying_set_active_set", IKEY, KM_PRESS, KM_CTRL | KM_SHIFT | KM_ALT, 0);
-
+
/* Pose -> PoseLib ------------- */
/* only set in posemode, by space_view3d listener */
WM_keymap_add_item(keymap, "POSELIB_OT_browse_interactive", LKEY, KM_PRESS, KM_CTRL, 0);
-
+
WM_keymap_add_item(keymap, "POSELIB_OT_pose_add", LKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "POSELIB_OT_pose_remove", LKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "POSELIB_OT_pose_rename", LKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
-
+
/* Pose -> Pose Sliding ------------- */
/* only set in posemode, by space_view3d listener */
WM_keymap_add_item(keymap, "POSE_OT_push", EKEY, KM_PRESS, KM_CTRL, 0);
@@ -395,4 +401,3 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
WM_keymap_add_menu(keymap, "VIEW3D_MT_pose_specials", WKEY, KM_PRESS, 0, 0);
WM_keymap_add_menu(keymap, "VIEW3D_MT_pose_propagate", PKEY, KM_PRESS, KM_ALT, 0);
}
-
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index 91f8a8713bc..e0155a8c435 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -110,7 +110,7 @@ static void joined_armature_fix_links_constraints(
bActionConstraint *data = con->data;
if (data->act) {
- BKE_action_fix_paths_rename(&tarArm->id, data->act, "pose.bones[",
+ BKE_action_fix_paths_rename(&tarArm->id, data->act, "pose.bones[",
pchan->name, curbone->name, 0, 0, false);
}
}
@@ -122,7 +122,7 @@ static void joined_armature_fix_links_constraints(
typedef struct tJoinArmature_AdtFixData {
Object *srcArm;
Object *tarArm;
-
+
GHash *names_map;
} tJoinArmature_AdtFixData;
@@ -135,34 +135,34 @@ 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,
+
+ /* 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 */
@@ -171,7 +171,7 @@ static void joined_armature_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data
/* 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
@@ -180,7 +180,7 @@ static void joined_armature_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data
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)) {
@@ -210,7 +210,7 @@ static void joined_armature_fix_links(Main *bmain, Object *tarArm, Object *srcAr
Object *ob;
bPose *pose;
bPoseChannel *pchant;
-
+
/* let's go through all objects in database */
for (ob = bmain->object.first; ob; ob = ob->id.next) {
/* do some object-type specific things */
@@ -220,12 +220,12 @@ static void joined_armature_fix_links(Main *bmain, Object *tarArm, Object *srcAr
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? */
@@ -235,7 +235,7 @@ static void joined_armature_fix_links(Main *bmain, Object *tarArm, Object *srcAr
BLI_strncpy(ob->parsubstr, curbone->name, sizeof(ob->parsubstr));
}
}
-
+
/* make tar armature be new parent */
ob->parent = tarArm;
}
@@ -254,13 +254,13 @@ int join_armature_exec(bContext *C, wmOperator *op)
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 || ob->type != OB_ARMATURE)
return OPERATOR_CANCELLED;
if (!arm || arm->edbo)
return OPERATOR_CANCELLED;
-
+
CTX_DATA_BEGIN(C, Base *, base, selected_editable_bases)
{
if (base->object == ob) {
@@ -278,7 +278,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
/* 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->pose;
ob->mode &= ~OB_MODE_POSE;
@@ -288,36 +288,36 @@ int join_armature_exec(bContext *C, wmOperator *op)
if ((base->object->type == OB_ARMATURE) && (base->object != ob)) {
tJoinArmature_AdtFixData afd = {NULL};
bArmature *curarm = base->object->data;
-
+
/* we assume that each armature datablock is only used in a single place */
BLI_assert(ob->data != base->object->data);
-
+
/* init callback data for fixing up AnimData links later */
afd.srcArm = base->object;
afd.tarArm = ob;
afd.names_map = BLI_ghash_str_new("join_armature_adt_fix");
-
+
/* Make a list of editbones in current armature */
ED_armature_to_edit(base->object->data);
-
+
/* Get Pose of current armature */
opose = base->object->pose;
base->object->mode &= ~OB_MODE_POSE;
//BASACT->flag &= ~OB_MODE_POSE;
-
+
/* Find the difference matrix */
invert_m4_m4(oimat, ob->obmat);
mul_m4_m4m4(mat, oimat, base->object->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];
@@ -325,48 +325,48 @@ int join_armature_exec(bContext *C, wmOperator *op)
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, base->object, 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,
+
+ /* 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!
*/
@@ -377,10 +377,10 @@ int join_armature_exec(bContext *C, wmOperator *op)
}
else {
/* merge in data - we'll fix the drivers manually */
- BKE_animdata_merge_copy(&ob->id, &base->object->id, ADT_MERGECOPY_KEEP_DST, false);
+ BKE_animdata_merge_copy(bmain, &ob->id, &base->object->id, ADT_MERGECOPY_KEEP_DST, false);
}
}
-
+
if (curarm->adt) {
if (arm->adt == NULL) {
/* no animdata, so just use a copy of the whole thing */
@@ -388,42 +388,43 @@ int join_armature_exec(bContext *C, wmOperator *op)
}
else {
/* merge in data - we'll fix the drivers manually */
- BKE_animdata_merge_copy(&arm->id, &curarm->id, ADT_MERGECOPY_KEEP_DST, false);
+ 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, base->object);
}
}
CTX_DATA_END;
-
+
DEG_relations_tag_update(bmain); /* because we removed object(s) */
- ED_armature_from_edit(arm);
+ ED_armature_from_edit(bmain, arm);
ED_armature_edit_free(arm);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
-
+
return OPERATOR_FINISHED;
}
/* *********************************** Separate *********************************************** */
/* Helper function for armature separating - link fixing */
-static void separated_armature_fix_links(Object *origArm, Object *newArm)
+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 = G.main->object.first; ob; ob = ob->id.next) {
+ for (ob = bmain->object.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) {
@@ -431,11 +432,11 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm)
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
@@ -462,18 +463,18 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm)
}
}
}
-
+
/* 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
@@ -492,14 +493,14 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm)
}
}
}
-
+
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? */
@@ -512,31 +513,31 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm)
}
}
-/* Helper function for armature separating - remove certain bones from the given armature
+/* Helper function for armature separating - remove certain bones from the given armature
* sel: remove selected bones from the armature, otherwise the unselected bones are removed
* (ob is not in editmode)
*/
-static void separate_armature_bones(Object *ob, short sel)
+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) {
@@ -545,25 +546,25 @@ static void separate_armature_bones(Object *ob, short sel)
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;
}
-
+
/* 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(ob->data);
+ ED_armature_from_edit(bmain, ob->data);
ED_armature_edit_free(ob->data);
}
@@ -576,14 +577,14 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
Object *oldob, *newob;
Base *oldbase, *newbase;
-
+
/* sanity checks */
if (obedit == NULL)
return OPERATOR_CANCELLED;
-
+
/* set wait cursor in case this takes a while */
WM_cursor_wait(1);
-
+
/* 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
@@ -604,16 +605,16 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
}
}
CTX_DATA_END;
-
+
/* 1) store starting settings and exit editmode */
oldob = obedit;
oldbase = view_layer->basact;
oldob->mode &= ~OB_MODE_POSE;
//oldbase->flag &= ~OB_POSEMODE;
-
- ED_armature_from_edit(obedit->data);
+
+ ED_armature_from_edit(bmain, obedit->data);
ED_armature_edit_free(obedit->data);
-
+
/* 2) duplicate base */
newbase = ED_object_add_duplicate(bmain, scene, view_layer, oldbase, USER_DUP_ARM); /* only duplicate linked armature */
DEG_relations_tag_update(bmain);
@@ -623,22 +624,22 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
/* 3) remove bones that shouldn't still be around on both armatures */
- separate_armature_bones(oldob, 1);
- separate_armature_bones(newob, 0);
-
-
+ 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(oldob, newob);
-
+ separated_armature_fix_links(bmain, oldob, newob);
+
DEG_id_tag_update(&oldob->id, OB_RECALC_DATA); /* this is the original one */
DEG_id_tag_update(&newob->id, OB_RECALC_DATA); /* this is the separated one */
-
-
+
+
/* 5) restore original conditions */
obedit = oldob;
-
+
ED_armature_to_edit(obedit->data);
-
+
/* parents tips remain selected when connected children are removed. */
ED_armature_edit_deselect_all(obedit);
@@ -646,10 +647,10 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
-
+
/* recalc/redraw + cleanup */
WM_cursor_wait(0);
-
+
return OPERATOR_FINISHED;
}
@@ -659,12 +660,12 @@ void ARMATURE_OT_separate(wmOperatorType *ot)
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;
}
@@ -688,13 +689,13 @@ static void bone_connect_to_new_parent(ListBase *edbo, EditBone *selbone, EditBo
{
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) {
@@ -702,21 +703,21 @@ static void bone_connect_to_new_parent(ListBase *edbo, EditBone *selbone, EditBo
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);
@@ -739,14 +740,14 @@ static const EnumPropertyItem prop_editarm_make_parent_types[] = {
{0, NULL, 0, NULL, NULL}
};
-static int armature_parent_set_exec(bContext *C, wmOperator *op)
+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");
@@ -754,27 +755,27 @@ static int armature_parent_set_exec(bContext *C, wmOperator *op)
}
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
+ * - 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)
+ if (actmirb == NULL)
actmirb = actbone;
}
-
- /* if there is only 1 selected bone, we assume that that is the active bone,
+
+ /* 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.
+ * 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);
}
@@ -783,16 +784,16 @@ static int armature_parent_set_exec(bContext *C, wmOperator *op)
/* 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
+ * - 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)
+ 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);
@@ -800,11 +801,11 @@ static int armature_parent_set_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
}
-
+
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -814,7 +815,7 @@ static int armature_parent_set_invoke(bContext *C, wmOperator *UNUSED(op), const
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) {
@@ -824,13 +825,13 @@ static int armature_parent_set_invoke(bContext *C, wmOperator *UNUSED(op), const
CTX_DATA_END;
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);
-
+
UI_popup_menu_end(C, pup);
-
+
return OPERATOR_INTERFACE;
}
@@ -840,15 +841,15 @@ void ARMATURE_OT_parent_set(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
RNA_def_enum(ot->srna, "type", prop_editarm_make_parent_types, 0, "ParentType", "Type of parenting");
}
@@ -866,28 +867,28 @@ static void editbone_clear_parent(EditBone *ebone, int mode)
/* 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)
+static int armature_parent_clear_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_edit_object(C);
bArmature *arm = (bArmature *)ob->data;
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;
-
+
ED_armature_edit_sync_selection(arm->edbo);
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -897,15 +898,14 @@ void ARMATURE_OT_parent_clear(wmOperatorType *ot)
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 65f845ce34c..e295e1fd35a 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -149,10 +149,10 @@ void *get_bone_from_selectbuffer(
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;
@@ -184,7 +184,7 @@ void *get_bone_from_selectbuffer(
data = ebone;
}
-
+
if (data) {
if (sel) {
if (do_nearest) {
@@ -225,7 +225,7 @@ void *get_bone_from_selectbuffer(
}
}
}
-
+
if (firstunSel) {
*r_base = firstunSel_base;
return firstunSel;
@@ -249,12 +249,14 @@ void *get_nearest_bone(
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);
+
+ hits = view3d_opengl_select(
+ &vc, buffer, MAXPICKBUF, &rect,
+ VIEW3D_SELECT_PICK_NEAREST, VIEW3D_SELECT_FILTER_NOP);
*r_base = NULL;
@@ -310,7 +312,7 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEv
curBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
}
}
-
+
if (curBone->flag & BONE_CONNECTED)
next = curBone->parent;
else
@@ -339,11 +341,11 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEv
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;
}
@@ -358,15 +360,15 @@ void ARMATURE_OT_select_linked(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
}
@@ -446,9 +448,11 @@ static EditBone *get_nearest_editbonepoint(
{
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);
+ 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;
@@ -458,7 +462,9 @@ static EditBone *get_nearest_editbonepoint(
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);
+ 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);
@@ -505,7 +511,7 @@ cache_end:
dep = 1;
else if ( (hitresult & BONESEL_TIP) && (ebone->flag & BONE_TIPSEL) == 0)
dep = 1;
- else
+ else
dep = 2;
}
else {
@@ -638,10 +644,10 @@ bool ED_armature_edit_select_pick(bContext *C, const int mval[2], bool extend, b
ED_armature_edit_deselect_all_multi(objects, objects_len);
MEM_freeN(objects);
}
-
+
/* 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 */
@@ -706,9 +712,9 @@ bool ED_armature_edit_select_pick(bContext *C, const int mval[2], bool extend, b
else
nearBone->flag |= selmask;
}
-
+
ED_armature_edit_sync_selection(arm->edbo);
-
+
if (nearBone) {
/* then now check for active status */
if (ebone_select_flag(nearBone)) {
@@ -717,6 +723,7 @@ bool ED_armature_edit_select_pick(bContext *C, const int mval[2], bool extend, b
if (vc.view_layer->basact != basact) {
vc.view_layer->basact = basact;
+ DEG_id_tag_update(&vc.scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, vc.scene);
}
}
@@ -748,7 +755,7 @@ static int armature_de_select_all_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
}
-
+
/* Set the flags */
CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
{
@@ -783,7 +790,7 @@ static int armature_de_select_all_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -793,14 +800,14 @@ void ARMATURE_OT_select_all(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
WM_operator_properties_select_all(ot);
}
@@ -1228,7 +1235,7 @@ static int armature_select_hierarchy_exec(bContext *C, wmOperator *op)
int direction = RNA_enum_get(op->ptr, "direction");
const bool add_to_sel = RNA_boolean_get(op->ptr, "extend");
bool changed = false;
-
+
ob = obedit;
arm = (bArmature *)ob->data;
@@ -1286,15 +1293,15 @@ static int armature_select_hierarchy_exec(bContext *C, wmOperator *op)
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;
}
@@ -1305,16 +1312,16 @@ void ARMATURE_OT_select_hierarchy(wmOperatorType *ot)
{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;
diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c
index 1722cbd5c5c..63068e61ba3 100644
--- a/source/blender/editors/armature/armature_skinning.c
+++ b/source/blender/editors/armature/armature_skinning.c
@@ -45,10 +45,12 @@
#include "BKE_armature.h"
#include "BKE_context.h"
#include "BKE_deform.h"
+#include "BKE_mesh_iterators.h"
+#include "BKE_mesh_runtime.h"
+#include "BKE_modifier.h"
#include "BKE_object_deform.h"
#include "BKE_report.h"
#include "BKE_subsurf.h"
-#include "BKE_modifier.h"
#include "DEG_depsgraph.h"
@@ -71,7 +73,7 @@ static int bone_skinnable_cb(Object *UNUSED(ob), Bone *bone, void *datap)
* This function performs 2 functions:
*
* a) It returns 1 if the bone is skinnable.
- * If we loop over all bones with this
+ * 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,
@@ -96,10 +98,10 @@ static int bone_skinnable_cb(Object *UNUSED(ob), Bone *bone, void *datap)
segments = bone->segments;
else
segments = 1;
-
+
if (data->list != NULL) {
hbone = (Bone ***) &data->list;
-
+
for (a = 0; a < segments; a++) {
**hbone = bone;
++*hbone;
@@ -111,10 +113,10 @@ static int bone_skinnable_cb(Object *UNUSED(ob), Bone *bone, void *datap)
return 0;
}
-static int vgroup_add_unique_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
+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).
+ * 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)) {
@@ -126,7 +128,7 @@ static int vgroup_add_unique_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
return 0;
}
-static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
+static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
{
/* Bones that are deforming
* are regarded to be "skinnable" and are eligible for
@@ -134,16 +136,16 @@ static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
*
* This function performs 2 functions:
*
- * a) If the bone is skinnable, it creates
+ * 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 -- the
* bDeformGroup pointer is set to point
* to the deform group with the bone's
- * name, and the pointer the handle
+ * 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
@@ -162,7 +164,7 @@ static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
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);
@@ -172,10 +174,10 @@ static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
defgroup = NULL;
}
}
-
+
if (data->list != NULL) {
hgroup = (bDeformGroup ***) &data->list;
-
+
for (a = 0; a < segments; a++) {
**hgroup = defgroup;
++*hgroup;
@@ -215,25 +217,25 @@ static void envelope_bone_weighting(
}
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)
@@ -258,7 +260,7 @@ static void add_verts_to_dgroups(
* into account and vertex weights can be mirrored.
*
* The mesh vertex positions used are either the final deformed coords
- * from the derivedmesh in weightpaint mode, the final subsurf coords
+ * from the evaluated mesh in weightpaint mode, the final subsurf coords
* when parenting, or simply the original mesh coords.
*/
@@ -282,10 +284,10 @@ static void add_verts_to_dgroups(
/* 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;
@@ -313,13 +315,13 @@ static void add_verts_to_dgroups(
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;
@@ -328,10 +330,10 @@ static void add_verts_to_dgroups(
}
}
}
-
+
segments--;
}
-
+
/* compute root and tip */
if (bbone) {
mul_v3_m4v3(root[j], bone->arm_mat, bbone[segments].mat[3]);
@@ -346,10 +348,10 @@ static void add_verts_to_dgroups(
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))
@@ -357,7 +359,7 @@ static void add_verts_to_dgroups(
}
else
selected[j] = 1;
-
+
/* find flipped group */
if (dgroup && mirror) {
char name_flip[MAXBONENAME];
@@ -372,15 +374,11 @@ static void add_verts_to_dgroups(
verts = MEM_callocN(mesh->totvert * sizeof(*verts), "closestboneverts");
if (wpmode) {
- /* if in weight paint mode, use final verts from derivedmesh */
- DerivedMesh *dm = mesh_get_derived_final(depsgraph, scene, ob, CD_MASK_BAREMESH);
-
- if (dm->foreachMappedVert) {
- mesh_get_mapped_verts_coords(dm, verts, mesh->totvert);
- vertsfilled = 1;
- }
-
- dm->release(dm);
+ /* if in weight paint mode, use final verts from evaluated mesh */
+ Mesh *me_eval = mesh_get_eval_final(depsgraph, scene, ob, 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.
@@ -431,7 +429,7 @@ 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
+ /* Lets try to create some vertex groups
* based on the bones of the parent armature.
*/
bArmature *arm = par->data;
@@ -439,7 +437,7 @@ void ED_object_vgroup_calc_from_armature(
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
+ /* 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);
@@ -451,7 +449,7 @@ void ED_object_vgroup_calc_from_armature(
}
}
else if (ELEM(mode, ARM_GROUPS_ENVELOPE, ARM_GROUPS_AUTO)) {
- /* Traverse the bone list, trying to create vertex groups
+ /* Traverse the bone list, trying to create vertex groups
* that are populated with the vertices for which the
* bone is closest.
*/
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c
index ffa8b9f5007..02d45a4e041 100644
--- a/source/blender/editors/armature/armature_utils.c
+++ b/source/blender/editors/armature/armature_utils.c
@@ -57,7 +57,7 @@
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) {
@@ -67,7 +67,7 @@ void ED_armature_edit_sync_selection(ListBase *edbo)
else
ebo->flag &= ~BONE_ROOTSEL;
}
-
+
if ((ebo->flag & BONE_TIPSEL) && (ebo->flag & BONE_ROOTSEL))
ebo->flag |= BONE_SELECTED;
else
@@ -94,27 +94,27 @@ void ED_armature_edit_validate_active(struct bArmature *arm)
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
+ /* 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 += 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);
}
-
+
return count;
}
@@ -273,13 +273,13 @@ EditBone *ED_armature_ebone_get_mirrored(const ListBase *edbo, EditBone *ebo)
if (ebo == NULL)
return NULL;
-
+
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);
}
-
+
return NULL;
}
@@ -293,7 +293,7 @@ void armature_select_mirrored_ex(bArmature *arm, const int flag)
/* 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) {
@@ -304,7 +304,7 @@ void armature_select_mirrored_ex(bArmature *arm, const int flag)
}
}
}
-
+
}
void armature_select_mirrored(bArmature *arm)
@@ -333,7 +333,7 @@ void armature_tag_select_mirrored(bArmature *arm)
}
}
}
-
+
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);
@@ -363,17 +363,17 @@ 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];
@@ -381,7 +381,7 @@ void ED_armature_edit_transform_mirror_update(Object *obedit)
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) {
@@ -398,7 +398,7 @@ void ED_armature_edit_transform_mirror_update(Object *obedit)
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;
@@ -411,7 +411,7 @@ void ED_armature_edit_transform_mirror_update(Object *obedit)
eboflip->roll = -ebo->roll;
eboflip->xwidth = ebo->xwidth;
eboflip->zwidth = ebo->zwidth;
-
+
eboflip->curveInX = -ebo->curveInX;
eboflip->curveOutX = -ebo->curveOutX;
eboflip->roll1 = -ebo->roll1;
@@ -432,17 +432,17 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone
EditBone *eBoneAct = NULL;
EditBone *eBoneTest = NULL;
Bone *curBone;
-
+
for (curBone = bones->first; curBone; curBone = curBone->next) {
eBone = MEM_callocN(sizeof(EditBone), "make_editbone");
-
+
/* 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 */
@@ -462,11 +462,11 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone
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;
@@ -492,20 +492,20 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone
if (curBone->prop)
eBone->prop = IDP_CopyProperty(curBone->prop);
-
+
BLI_addtail(edbo, eBone);
-
+
/* Add children if necessary */
if (curBone->childbase.first) {
eBoneTest = make_boneList(edbo, &curBone->childbase, eBone, actBone);
if (eBoneTest)
eBoneAct = eBoneTest;
}
-
+
if (curBone == actBone)
eBoneAct = eBone;
}
-
+
return eBoneAct;
}
@@ -585,23 +585,23 @@ static void armature_finalize_restpose(ListBase *bonelist, ListBase *editbonelis
}
/* put EditMode back in Object */
-void ED_armature_from_edit(bArmature *arm)
+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)
@@ -612,19 +612,19 @@ void ED_armature_from_edit(bArmature *arm)
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 */
@@ -632,10 +632,10 @@ void ED_armature_from_edit(bArmature *arm)
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;
@@ -659,7 +659,7 @@ void ED_armature_from_edit(bArmature *arm)
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). */
@@ -674,24 +674,24 @@ void ED_armature_from_edit(bArmature *arm)
BLI_addtail(&arm->bonebase, newBone);
}
}
-
+
/* 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 = G.main->object.first; obt; obt = obt->id.next) {
+ for (obt = bmain->object.first; obt; obt = obt->id.next) {
if (obt->data == arm) {
BKE_pose_rebuild(obt, arm);
}
}
-
+
DEG_id_tag_update(&arm->id, 0);
}
void ED_armature_edit_free(struct bArmature *arm)
{
EditBone *eBone;
-
+
/* Clear the editbones list */
if (arm->edbo) {
if (arm->edbo->first) {
@@ -701,7 +701,7 @@ void ED_armature_edit_free(struct bArmature *arm)
MEM_freeN(eBone->prop);
}
}
-
+
BLI_freelistN(arm->edbo);
}
MEM_freeN(arm->edbo);
diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c
new file mode 100644
index 00000000000..b74b515b37f
--- /dev/null
+++ b/source/blender/editors/armature/editarmature_retarget.c
@@ -0,0 +1,2644 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Martin Poirier
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * autoarmature.c: Interface for automagically manipulating armature (retarget, created, ...)
+ */
+
+/** \file blender/editors/armature/editarmature_retarget.c
+ * \ingroup edarmature
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "PIL_time.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+
+#include "BKE_constraint.h"
+#include "BKE_armature.h"
+#include "BKE_context.h"
+#include "BKE_main.h"
+
+#include "ED_armature.h"
+#include "ED_undo.h"
+
+#include "BIF_retarget.h"
+
+#include "armature_intern.h"
+
+/************ RIG RETARGET DATA STRUCTURES ***************/
+
+typedef struct MemoNode {
+ float weight;
+ int next;
+} MemoNode;
+
+typedef struct RetargetParam {
+ RigGraph *rigg;
+ RigArc *iarc;
+ RigNode *inode_start;
+ bContext *context;
+} RetargetParam;
+
+typedef enum {
+ RETARGET_LENGTH,
+ RETARGET_AGGRESSIVE
+} RetargetMode;
+
+typedef enum {
+ METHOD_BRUTE_FORCE = 0,
+ METHOD_MEMOIZE = 1
+} RetargetMethod;
+
+typedef enum {
+ ARC_FREE = 0,
+ ARC_TAKEN = 1,
+ ARC_USED = 2
+} ArcUsageFlags;
+
+static RigGraph *GLOBAL_RIGG = NULL;
+
+/*******************************************************************************************************/
+
+void exec_retargetArctoArc(TaskPool * __restrict pool, void *taskdata, int threadid);
+
+static void RIG_calculateEdgeAngles(RigEdge *edge_first, RigEdge *edge_second);
+float rollBoneByQuat(EditBone *bone, float old_up_axis[3], float qrot[4]);
+
+/* two levels */
+#define SHAPE_LEVELS (SHAPE_RADIX * SHAPE_RADIX)
+
+/*********************************** EDITBONE UTILS ****************************************************/
+
+static int countEditBoneChildren(ListBase *list, EditBone *parent)
+{
+ EditBone *ebone;
+ int count = 0;
+
+ for (ebone = list->first; ebone; ebone = ebone->next) {
+ if (ebone->parent == parent) {
+ count++;
+ }
+ }
+
+ return count;
+}
+
+static EditBone *nextEditBoneChild(ListBase *list, EditBone *parent, int n)
+{
+ EditBone *ebone;
+
+ for (ebone = list->first; ebone; ebone = ebone->next) {
+ if (ebone->parent == parent) {
+ if (n == 0) {
+ return ebone;
+ }
+ n--;
+ }
+ }
+
+ return NULL;
+}
+
+static void getEditBoneRollUpAxis(EditBone *bone, float roll, float up_axis[3])
+{
+ float mat[3][3], nor[3];
+
+ sub_v3_v3v3(nor, bone->tail, bone->head);
+
+ vec_roll_to_mat3(nor, roll, mat);
+ copy_v3_v3(up_axis, mat[2]);
+}
+
+static float rollBoneByQuatAligned(EditBone *bone, float old_up_axis[3], float qrot[4], float qroll[4], float aligned_axis[3])
+{
+ float nor[3], new_up_axis[3], x_axis[3], z_axis[3];
+
+ copy_v3_v3(new_up_axis, old_up_axis);
+ mul_qt_v3(qrot, new_up_axis);
+
+ sub_v3_v3v3(nor, bone->tail, bone->head);
+
+ cross_v3_v3v3(x_axis, nor, aligned_axis);
+ cross_v3_v3v3(z_axis, x_axis, nor);
+
+ normalize_v3(new_up_axis);
+ normalize_v3(x_axis);
+ normalize_v3(z_axis);
+
+ if (dot_v3v3(new_up_axis, x_axis) < 0) {
+ negate_v3(x_axis);
+ }
+
+ if (dot_v3v3(new_up_axis, z_axis) < 0) {
+ negate_v3(z_axis);
+ }
+
+ if (angle_normalized_v3v3(x_axis, new_up_axis) < angle_normalized_v3v3(z_axis, new_up_axis)) {
+ rotation_between_vecs_to_quat(qroll, new_up_axis, x_axis); /* set roll rotation quat */
+ return ED_armature_ebone_roll_to_vector(bone, x_axis, false);
+ }
+ else {
+ rotation_between_vecs_to_quat(qroll, new_up_axis, z_axis); /* set roll rotation quat */
+ return ED_armature_ebone_roll_to_vector(bone, z_axis, false);
+ }
+}
+
+static float rollBoneByQuatJoint(RigEdge *edge, RigEdge *previous, float qrot[4], float qroll[4], float up_axis[3])
+{
+ if (previous == NULL) {
+ /* default to up_axis if no previous */
+ return rollBoneByQuatAligned(edge->bone, edge->up_axis, qrot, qroll, up_axis);
+ }
+ else {
+ float new_up_axis[3];
+ float vec_first[3], vec_second[3], normal[3];
+
+ if (previous->bone) {
+ sub_v3_v3v3(vec_first, previous->bone->tail, previous->bone->head);
+ }
+ else if (previous->prev->bone) {
+ sub_v3_v3v3(vec_first, edge->bone->head, previous->prev->bone->tail);
+ }
+ else {
+ /* default to up_axis if first bone in the chain is an offset */
+ return rollBoneByQuatAligned(edge->bone, edge->up_axis, qrot, qroll, up_axis);
+ }
+
+ sub_v3_v3v3(vec_second, edge->bone->tail, edge->bone->head);
+
+ normalize_v3(vec_first);
+ normalize_v3(vec_second);
+
+ cross_v3_v3v3(normal, vec_first, vec_second);
+ normalize_v3(normal);
+
+ axis_angle_to_quat(qroll, vec_second, edge->up_angle);
+
+ mul_qt_v3(qroll, normal);
+
+ copy_v3_v3(new_up_axis, edge->up_axis);
+ mul_qt_v3(qrot, new_up_axis);
+
+ normalize_v3(new_up_axis);
+
+ /* real qroll between normal and up_axis */
+ rotation_between_vecs_to_quat(qroll, new_up_axis, normal);
+
+ return ED_armature_ebone_roll_to_vector(edge->bone, normal, false);
+ }
+}
+
+float rollBoneByQuat(EditBone *bone, float old_up_axis[3], float qrot[4])
+{
+ float new_up_axis[3];
+
+ copy_v3_v3(new_up_axis, old_up_axis);
+ mul_qt_v3(qrot, new_up_axis);
+
+ return ED_armature_ebone_roll_to_vector(bone, new_up_axis, false);
+}
+
+/************************************ DESTRUCTORS ******************************************************/
+
+static void RIG_freeRigArc(BArc *arc)
+{
+ BLI_freelistN(&((RigArc *)arc)->edges);
+}
+
+void RIG_freeRigGraph(BGraph *rg)
+{
+ RigGraph *rigg = (RigGraph *)rg;
+ BNode *node;
+ BArc *arc;
+
+ BLI_task_pool_free(rigg->task_pool);
+ BLI_task_scheduler_free(rigg->task_scheduler);
+
+ if (rigg->link_mesh) {
+ REEB_freeGraph(rigg->link_mesh);
+ }
+
+ for (arc = rg->arcs.first; arc; arc = arc->next) {
+ RIG_freeRigArc(arc);
+ }
+ BLI_freelistN(&rg->arcs);
+
+ for (node = rg->nodes.first; node; node = node->next) {
+ BLI_freeNode(rg, (BNode *)node);
+ }
+ BLI_freelistN(&rg->nodes);
+
+ BLI_freelistN(&rigg->controls);
+
+ BLI_ghash_free(rigg->bones_map, NULL, NULL);
+ BLI_ghash_free(rigg->controls_map, NULL, NULL);
+
+ if (rigg->flag & RIG_FREE_BONELIST) {
+ BLI_freelistN(rigg->editbones);
+ MEM_freeN(rigg->editbones);
+ }
+
+ MEM_freeN(rg);
+}
+
+/************************************* ALLOCATORS ******************************************************/
+
+static RigGraph *newRigGraph(void)
+{
+ RigGraph *rg;
+ int totthread;
+
+ rg = MEM_callocN(sizeof(RigGraph), "rig graph");
+
+ rg->head = NULL;
+
+ rg->bones_map = BLI_ghash_str_new("newRigGraph bones gh");
+ rg->controls_map = BLI_ghash_str_new("newRigGraph cont gh");
+
+ rg->free_arc = RIG_freeRigArc;
+ rg->free_node = NULL;
+
+#ifdef USE_THREADS
+ totthread = TASK_SCHEDULER_AUTO_THREADS;
+#else
+ totthread = TASK_SCHEDULER_SINGLE_THREAD;
+#endif
+
+ rg->task_scheduler = BLI_task_scheduler_create(totthread);
+ rg->task_pool = BLI_task_pool_create(rg->task_scheduler, NULL);
+
+ return rg;
+}
+
+static RigArc *newRigArc(RigGraph *rg)
+{
+ RigArc *arc;
+
+ arc = MEM_callocN(sizeof(RigArc), "rig arc");
+ arc->count = 0;
+ BLI_addtail(&rg->arcs, arc);
+
+ return arc;
+}
+
+static RigControl *newRigControl(RigGraph *rg)
+{
+ RigControl *ctrl;
+
+ ctrl = MEM_callocN(sizeof(RigControl), "rig control");
+
+ BLI_addtail(&rg->controls, ctrl);
+
+ return ctrl;
+}
+
+static RigNode *newRigNodeHead(RigGraph *rg, RigArc *arc, float p[3])
+{
+ RigNode *node;
+ node = MEM_callocN(sizeof(RigNode), "rig node");
+ BLI_addtail(&rg->nodes, node);
+
+ copy_v3_v3(node->p, p);
+ node->degree = 1;
+ node->arcs = NULL;
+
+ arc->head = node;
+
+ return node;
+}
+
+static void addRigNodeHead(RigGraph *UNUSED(rg), RigArc *arc, RigNode *node)
+{
+ node->degree++;
+
+ arc->head = node;
+}
+
+static RigNode *newRigNode(RigGraph *rg, float p[3])
+{
+ RigNode *node;
+ node = MEM_callocN(sizeof(RigNode), "rig node");
+ BLI_addtail(&rg->nodes, node);
+
+ copy_v3_v3(node->p, p);
+ node->degree = 0;
+ node->arcs = NULL;
+
+ return node;
+}
+
+static RigNode *newRigNodeTail(RigGraph *rg, RigArc *arc, float p[3])
+{
+ RigNode *node = newRigNode(rg, p);
+
+ node->degree = 1;
+ arc->tail = node;
+
+ return node;
+}
+
+static void RIG_appendEdgeToArc(RigArc *arc, RigEdge *edge)
+{
+ BLI_addtail(&arc->edges, edge);
+
+ if (edge->prev == NULL) {
+ copy_v3_v3(edge->head, arc->head->p);
+ }
+ else {
+ RigEdge *last_edge = edge->prev;
+ copy_v3_v3(edge->head, last_edge->tail);
+ RIG_calculateEdgeAngles(last_edge, edge);
+ }
+
+ edge->length = len_v3v3(edge->head, edge->tail);
+
+ arc->length += edge->length;
+
+ arc->count += 1;
+}
+
+static void RIG_addEdgeToArc(RigArc *arc, float tail[3], EditBone *bone)
+{
+ RigEdge *edge;
+
+ edge = MEM_callocN(sizeof(RigEdge), "rig edge");
+
+ copy_v3_v3(edge->tail, tail);
+ edge->bone = bone;
+
+ if (bone) {
+ getEditBoneRollUpAxis(bone, bone->roll, edge->up_axis);
+ }
+
+ RIG_appendEdgeToArc(arc, edge);
+}
+/************************************** CLONING TEMPLATES **********************************************/
+
+static void renameTemplateBone(char *name, char *template_name, ListBase *editbones, char *side_string, char *num_string)
+{
+ int i, j;
+
+ for (i = 0, j = 0; i < (MAXBONENAME - 1) && j < (MAXBONENAME - 1) && template_name[i] != '\0'; i++) {
+ if (template_name[i] == '&') {
+ if (template_name[i + 1] == 'S' || template_name[i + 1] == 's') {
+ j += BLI_strncpy_rlen(name + j, side_string, MAXBONENAME);
+ i++;
+ }
+ else if (template_name[i + 1] == 'N' || template_name[i + 1] == 'n') {
+ j += BLI_strncpy_rlen(name + j, num_string, MAXBONENAME);
+ i++;
+ }
+ else {
+ name[j] = template_name[i];
+ j++;
+ }
+ }
+ else {
+ name[j] = template_name[i];
+ j++;
+ }
+ }
+
+ name[j] = '\0';
+
+ ED_armature_ebone_unique_name(editbones, name, NULL);
+}
+
+static RigControl *cloneControl(RigGraph *rg, RigGraph *src_rg, RigControl *src_ctrl, GHash *ptr_hash, char *side_string, char *num_string)
+{
+ RigControl *ctrl;
+ char name[MAXBONENAME];
+
+ ctrl = newRigControl(rg);
+
+ copy_v3_v3(ctrl->head, src_ctrl->head);
+ copy_v3_v3(ctrl->tail, src_ctrl->tail);
+ copy_v3_v3(ctrl->up_axis, src_ctrl->up_axis);
+ copy_v3_v3(ctrl->offset, src_ctrl->offset);
+
+ ctrl->tail_mode = src_ctrl->tail_mode;
+ ctrl->flag = src_ctrl->flag;
+
+ renameTemplateBone(name, src_ctrl->bone->name, rg->editbones, side_string, num_string);
+ ctrl->bone = duplicateEditBoneObjects(src_ctrl->bone, name, rg->editbones, src_rg->ob, rg->ob);
+ ctrl->bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ BLI_ghash_insert(ptr_hash, src_ctrl->bone, ctrl->bone);
+
+ ctrl->link = src_ctrl->link;
+ ctrl->link_tail = src_ctrl->link_tail;
+
+ return ctrl;
+}
+
+static RigArc *cloneArc(RigGraph *rg, RigGraph *src_rg, RigArc *src_arc, GHash *ptr_hash, char *side_string, char *num_string)
+{
+ RigEdge *src_edge;
+ RigArc *arc;
+
+ arc = newRigArc(rg);
+
+ arc->head = BLI_ghash_lookup(ptr_hash, src_arc->head);
+ arc->tail = BLI_ghash_lookup(ptr_hash, src_arc->tail);
+
+ arc->head->degree++;
+ arc->tail->degree++;
+
+ arc->length = src_arc->length;
+
+ arc->count = src_arc->count;
+
+ for (src_edge = src_arc->edges.first; src_edge; src_edge = src_edge->next) {
+ RigEdge *edge;
+
+ edge = MEM_callocN(sizeof(RigEdge), "rig edge");
+
+ copy_v3_v3(edge->head, src_edge->head);
+ copy_v3_v3(edge->tail, src_edge->tail);
+ copy_v3_v3(edge->up_axis, src_edge->up_axis);
+
+ edge->length = src_edge->length;
+ edge->angle = src_edge->angle;
+ edge->up_angle = src_edge->up_angle;
+
+ if (src_edge->bone != NULL) {
+ char name[MAXBONENAME];
+ renameTemplateBone(name, src_edge->bone->name, rg->editbones, side_string, num_string);
+ edge->bone = duplicateEditBoneObjects(src_edge->bone, name, rg->editbones, src_rg->ob, rg->ob);
+ edge->bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ BLI_ghash_insert(ptr_hash, src_edge->bone, edge->bone);
+ }
+
+ BLI_addtail(&arc->edges, edge);
+ }
+
+ return arc;
+}
+
+static RigGraph *cloneRigGraph(RigGraph *src, ListBase *editbones, Object *ob, char *side_string, char *num_string)
+{
+ GHash *ptr_hash;
+ RigNode *node;
+ RigArc *arc;
+ RigControl *ctrl;
+ RigGraph *rg;
+
+ ptr_hash = BLI_ghash_ptr_new("cloneRigGraph gh");
+
+ rg = newRigGraph();
+
+ rg->ob = ob;
+ rg->editbones = editbones;
+
+ preEditBoneDuplicate(rg->editbones); /* prime bones for duplication */
+ preEditBoneDuplicate(src->editbones); /* prime bones for duplication */
+
+ /* Clone nodes */
+ for (node = src->nodes.first; node; node = node->next) {
+ RigNode *cloned_node = newRigNode(rg, node->p);
+ BLI_ghash_insert(ptr_hash, node, cloned_node);
+ }
+
+ rg->head = BLI_ghash_lookup(ptr_hash, src->head);
+
+ /* Clone arcs */
+ for (arc = src->arcs.first; arc; arc = arc->next) {
+ cloneArc(rg, src, arc, ptr_hash, side_string, num_string);
+ }
+
+ /* Clone controls */
+ for (ctrl = src->controls.first; ctrl; ctrl = ctrl->next) {
+ cloneControl(rg, src, ctrl, ptr_hash, side_string, num_string);
+ }
+
+ /* Relink bones properly */
+ for (arc = rg->arcs.first; arc; arc = arc->next) {
+ RigEdge *edge;
+
+ for (edge = arc->edges.first; edge; edge = edge->next) {
+ if (edge->bone != NULL) {
+ EditBone *bone;
+
+ updateDuplicateSubtargetObjects(edge->bone, src->editbones, src->ob, rg->ob);
+
+ if (edge->bone->parent) {
+ bone = BLI_ghash_lookup(ptr_hash, edge->bone->parent);
+
+ if (bone != NULL) {
+ edge->bone->parent = bone;
+ }
+ else {
+ /* disconnect since parent isn't cloned
+ * this will only happen when cloning from selected bones
+ * */
+ edge->bone->flag &= ~BONE_CONNECTED;
+ }
+ }
+ }
+ }
+ }
+
+ for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next) {
+ EditBone *bone;
+
+ updateDuplicateSubtargetObjects(ctrl->bone, src->editbones, src->ob, rg->ob);
+
+ if (ctrl->bone->parent) {
+ bone = BLI_ghash_lookup(ptr_hash, ctrl->bone->parent);
+
+ if (bone != NULL) {
+ ctrl->bone->parent = bone;
+ }
+ else {
+ /* disconnect since parent isn't cloned
+ * this will only happen when cloning from selected bones
+ * */
+ ctrl->bone->flag &= ~BONE_CONNECTED;
+ }
+ }
+
+ ctrl->link = BLI_ghash_lookup(ptr_hash, ctrl->link);
+ ctrl->link_tail = BLI_ghash_lookup(ptr_hash, ctrl->link_tail);
+ }
+
+ BLI_ghash_free(ptr_hash, NULL, NULL);
+
+ return rg;
+}
+
+
+/*******************************************************************************************************/
+
+static void RIG_calculateEdgeAngles(RigEdge *edge_first, RigEdge *edge_second)
+{
+ float vec_first[3], vec_second[3];
+
+ sub_v3_v3v3(vec_first, edge_first->tail, edge_first->head);
+ sub_v3_v3v3(vec_second, edge_second->tail, edge_second->head);
+
+ normalize_v3(vec_first);
+ normalize_v3(vec_second);
+
+ edge_first->angle = angle_normalized_v3v3(vec_first, vec_second);
+
+ if (edge_second->bone != NULL) {
+ float normal[3];
+
+ cross_v3_v3v3(normal, vec_first, vec_second);
+ normalize_v3(normal);
+
+ edge_second->up_angle = angle_normalized_v3v3(normal, edge_second->up_axis);
+ }
+}
+
+/************************************ CONTROL BONES ****************************************************/
+
+static void RIG_addControlBone(RigGraph *rg, EditBone *bone)
+{
+ RigControl *ctrl = newRigControl(rg);
+ ctrl->bone = bone;
+ copy_v3_v3(ctrl->head, bone->head);
+ copy_v3_v3(ctrl->tail, bone->tail);
+ getEditBoneRollUpAxis(bone, bone->roll, ctrl->up_axis);
+ ctrl->tail_mode = TL_NONE;
+
+ BLI_ghash_insert(rg->controls_map, bone->name, ctrl);
+}
+
+static int RIG_parentControl(RigControl *ctrl, EditBone *link)
+{
+ if (link) {
+ float offset[3];
+ int flag = 0;
+
+ sub_v3_v3v3(offset, ctrl->bone->head, link->head);
+
+ /* if root matches, check for direction too */
+ if (dot_v3v3(offset, offset) < 0.0001f) {
+ float vbone[3], vparent[3];
+
+ flag |= RIG_CTRL_FIT_ROOT;
+
+ sub_v3_v3v3(vbone, ctrl->bone->tail, ctrl->bone->head);
+ sub_v3_v3v3(vparent, link->tail, link->head);
+
+ /* test for opposite direction */
+ if (dot_v3v3(vbone, vparent) > 0) {
+ float nor[3];
+ float len;
+
+ cross_v3_v3v3(nor, vbone, vparent);
+
+ len = dot_v3v3(nor, nor);
+ if (len < 0.0001f) {
+ flag |= RIG_CTRL_FIT_BONE;
+ }
+ }
+ }
+
+ /* Bail out if old one is automatically better */
+ if (flag < ctrl->flag) {
+ return 0;
+ }
+
+ /* if there's already a link
+ * overwrite only if new link is higher in the chain */
+ if (ctrl->link && flag == ctrl->flag) {
+ EditBone *bone = NULL;
+
+ for (bone = ctrl->link; bone; bone = bone->parent) {
+ /* if link is in the chain, break and use that one */
+ if (bone == link) {
+ break;
+ }
+ }
+
+ /* not in chain, don't update link */
+ if (bone == NULL) {
+ return 0;
+ }
+ }
+
+
+ ctrl->link = link;
+ ctrl->flag = flag;
+
+ copy_v3_v3(ctrl->offset, offset);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static void RIG_reconnectControlBones(RigGraph *rg)
+{
+ RigControl *ctrl;
+ bool changed = true;
+
+ /* first pass, link to deform bones */
+ for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next) {
+ bPoseChannel *pchan;
+ bConstraint *con;
+ int found = 0;
+
+ /* DO SOME MAGIC HERE */
+ for (pchan = rg->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) {
+ int target_index;
+
+ cti->get_constraint_targets(con, &targets);
+
+ for (target_index = 0, ct = targets.first; ct; target_index++, ct = ct->next) {
+ if ((ct->tar == rg->ob) && STREQ(ct->subtarget, ctrl->bone->name)) {
+ /* SET bone link to bone corresponding to pchan */
+ EditBone *link = BLI_ghash_lookup(rg->bones_map, pchan->name);
+
+ /* Making sure bone is in this armature */
+ if (link != NULL) {
+ /* for pole targets, link to parent bone instead, if possible */
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC && target_index == 1) {
+ if (link->parent && BLI_ghash_haskey(rg->bones_map, link->parent->name)) {
+ link = link->parent;
+ }
+ }
+
+ found = RIG_parentControl(ctrl, link);
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
+ }
+ }
+
+ /* if not found yet, check parent */
+ if (found == 0) {
+ if (ctrl->bone->parent) {
+ /* make sure parent is a deforming bone
+ * NULL if not
+ * */
+ EditBone *link = BLI_ghash_lookup(rg->bones_map, ctrl->bone->parent->name);
+
+ found = RIG_parentControl(ctrl, link);
+ }
+
+ /* check if bone is not superposed on another one */
+ {
+ RigArc *arc;
+ RigArc *best_arc = NULL;
+ EditBone *link = NULL;
+
+ for (arc = rg->arcs.first; arc; arc = arc->next) {
+ RigEdge *edge;
+ for (edge = arc->edges.first; edge; edge = edge->next) {
+ if (edge->bone) {
+ int fit = 0;
+
+ fit = len_v3v3(ctrl->bone->head, edge->bone->head) < 0.0001f;
+ fit = fit || len_v3v3(ctrl->bone->tail, edge->bone->tail) < 0.0001f;
+
+ if (fit) {
+ /* pick the bone on the arc with the lowest symmetry level
+ * means you connect control to the trunk of the skeleton */
+ if (best_arc == NULL || arc->symmetry_level < best_arc->symmetry_level) {
+ best_arc = arc;
+ link = edge->bone;
+ }
+ }
+ }
+ }
+ }
+
+ found = RIG_parentControl(ctrl, link);
+ }
+ }
+
+ /* if not found yet, check child */
+ if (found == 0) {
+ RigArc *arc;
+ RigArc *best_arc = NULL;
+ EditBone *link = NULL;
+
+ for (arc = rg->arcs.first; arc; arc = arc->next) {
+ RigEdge *edge;
+ for (edge = arc->edges.first; edge; edge = edge->next) {
+ if (edge->bone && edge->bone->parent == ctrl->bone) {
+ /* pick the bone on the arc with the lowest symmetry level
+ * means you connect control to the trunk of the skeleton */
+ if (best_arc == NULL || arc->symmetry_level < best_arc->symmetry_level) {
+ best_arc = arc;
+ link = edge->bone;
+ }
+ }
+ }
+ }
+
+ found = RIG_parentControl(ctrl, link);
+ }
+
+ }
+
+
+ /* second pass, make chains in control bones */
+ while (changed) {
+ changed = false;
+
+ for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next) {
+ /* if control is not linked yet */
+ if (ctrl->link == NULL) {
+ bPoseChannel *pchan;
+ bConstraint *con;
+ RigControl *ctrl_parent = NULL;
+ RigControl *ctrl_child;
+ int found = 0;
+
+ if (ctrl->bone->parent) {
+ ctrl_parent = BLI_ghash_lookup(rg->controls_map, ctrl->bone->parent->name);
+ }
+
+ /* check constraints first */
+
+ /* DO SOME MAGIC HERE */
+ for (pchan = rg->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) {
+ if ((ct->tar == rg->ob) && STREQ(ct->subtarget, ctrl->bone->name)) {
+ /* SET bone link to ctrl corresponding to pchan */
+ RigControl *link = BLI_ghash_lookup(rg->controls_map, pchan->name);
+
+ /* if owner is a control bone, link with it */
+ if (link && link->link) {
+ RIG_parentControl(ctrl, link->bone);
+ found = 1;
+ break;
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
+ }
+ }
+
+ if (found == 0) {
+ /* check if parent is already linked */
+ if (ctrl_parent && ctrl_parent->link) {
+ RIG_parentControl(ctrl, ctrl_parent->bone);
+ changed = true;
+ }
+ else {
+ /* check childs */
+ for (ctrl_child = rg->controls.first; ctrl_child; ctrl_child = ctrl_child->next) {
+ /* if a child is linked, link to that one */
+ if (ctrl_child->link && ctrl_child->bone->parent == ctrl->bone) {
+ RIG_parentControl(ctrl, ctrl_child->bone);
+ changed = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* third pass, link control tails */
+ for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next) {
+ /* fit bone already means full match, so skip those */
+ if ((ctrl->flag & RIG_CTRL_FIT_BONE) == 0) {
+ GHashIterator ghi;
+
+ /* look on deform bones first */
+ BLI_ghashIterator_init(&ghi, rg->bones_map);
+
+ for (; !BLI_ghashIterator_done(&ghi); BLI_ghashIterator_step(&ghi)) {
+ EditBone *bone = (EditBone *)BLI_ghashIterator_getValue(&ghi);
+
+ /* don't link with parent */
+ if (bone->parent != ctrl->bone) {
+ if (len_v3v3(ctrl->bone->tail, bone->head) < 0.01f) {
+ ctrl->tail_mode = TL_HEAD;
+ ctrl->link_tail = bone;
+ break;
+ }
+ else if (len_v3v3(ctrl->bone->tail, bone->tail) < 0.01f) {
+ ctrl->tail_mode = TL_TAIL;
+ ctrl->link_tail = bone;
+ break;
+ }
+ }
+ }
+
+ /* if we haven't found one yet, look in control bones */
+ if (ctrl->tail_mode == TL_NONE) {
+ /* pass */
+ }
+ }
+ }
+
+}
+
+/*******************************************************************************************************/
+
+static void RIG_joinArcs(RigGraph *rg, RigNode *node, RigArc *joined_arc1, RigArc *joined_arc2)
+{
+ RigEdge *edge, *next_edge;
+
+ /* ignore cases where joint is at start or end */
+ if (joined_arc1->head == joined_arc2->head || joined_arc1->tail == joined_arc2->tail) {
+ return;
+ }
+
+ /* swap arcs to make sure arc1 is before arc2 */
+ if (joined_arc1->head == joined_arc2->tail) {
+ RigArc *tmp = joined_arc1;
+ joined_arc1 = joined_arc2;
+ joined_arc2 = tmp;
+ }
+
+ for (edge = joined_arc2->edges.first; edge; edge = next_edge) {
+ next_edge = edge->next;
+
+ RIG_appendEdgeToArc(joined_arc1, edge);
+ }
+
+ joined_arc1->tail = joined_arc2->tail;
+
+ BLI_listbase_clear(&joined_arc2->edges);
+
+ BLI_removeArc((BGraph *)rg, (BArc *)joined_arc2);
+
+ BLI_removeNode((BGraph *)rg, (BNode *)node);
+}
+
+static void RIG_removeNormalNodes(RigGraph *rg)
+{
+ RigNode *node, *next_node;
+
+ for (node = rg->nodes.first; node; node = next_node) {
+ next_node = node->next;
+
+ if (node->degree == 2) {
+ RigArc *arc, *joined_arc1 = NULL, *joined_arc2 = NULL;
+
+ for (arc = rg->arcs.first; arc; arc = arc->next) {
+ if (arc->head == node || arc->tail == node) {
+ if (joined_arc1 == NULL) {
+ joined_arc1 = arc;
+ }
+ else {
+ joined_arc2 = arc;
+ break;
+ }
+ }
+ }
+
+ RIG_joinArcs(rg, node, joined_arc1, joined_arc2);
+ }
+ }
+}
+
+static void RIG_removeUneededOffsets(RigGraph *rg)
+{
+ RigArc *arc;
+
+ for (arc = rg->arcs.first; arc; arc = arc->next) {
+ RigEdge *first_edge, *last_edge;
+
+ first_edge = arc->edges.first;
+ last_edge = arc->edges.last;
+
+ if (first_edge->bone == NULL) {
+ if (first_edge->bone == NULL && len_v3v3(first_edge->tail, arc->head->p) <= 0.001f) {
+ BLI_remlink(&arc->edges, first_edge);
+ MEM_freeN(first_edge);
+ }
+ else if (arc->head->degree == 1) {
+ RigNode *new_node = (RigNode *)BLI_FindNodeByPosition((BGraph *)rg, first_edge->tail, 0.001f);
+
+ if (new_node) {
+ BLI_remlink(&arc->edges, first_edge);
+ MEM_freeN(first_edge);
+ BLI_replaceNodeInArc((BGraph *)rg, (BArc *)arc, (BNode *)new_node, (BNode *)arc->head);
+ }
+ else {
+ RigEdge *next_edge = first_edge->next;
+
+ if (next_edge) {
+ BLI_remlink(&arc->edges, first_edge);
+ MEM_freeN(first_edge);
+
+ copy_v3_v3(arc->head->p, next_edge->head);
+ }
+ }
+ }
+ else {
+ /* check if all arc connected start with a null edge */
+ RigArc *other_arc;
+ for (other_arc = rg->arcs.first; other_arc; other_arc = other_arc->next) {
+ if (other_arc != arc) {
+ RigEdge *test_edge;
+ if (other_arc->head == arc->head) {
+ test_edge = other_arc->edges.first;
+
+ if (test_edge->bone != NULL) {
+ break;
+ }
+ }
+ else if (other_arc->tail == arc->head) {
+ test_edge = other_arc->edges.last;
+
+ if (test_edge->bone != NULL) {
+ break;
+ }
+ }
+ }
+ }
+
+ if (other_arc == NULL) {
+ RigNode *new_node = (RigNode *)BLI_FindNodeByPosition((BGraph *)rg, first_edge->tail, 0.001);
+
+ if (new_node) {
+ /* remove null edge in other arcs too */
+ for (other_arc = rg->arcs.first; other_arc; other_arc = other_arc->next) {
+ if (other_arc != arc) {
+ RigEdge *test_edge;
+ if (other_arc->head == arc->head) {
+ BLI_replaceNodeInArc((BGraph *)rg, (BArc *)other_arc, (BNode *)new_node, (BNode *)other_arc->head);
+ test_edge = other_arc->edges.first;
+ BLI_remlink(&other_arc->edges, test_edge);
+ MEM_freeN(test_edge);
+ }
+ else if (other_arc->tail == arc->head) {
+ BLI_replaceNodeInArc((BGraph *)rg, (BArc *)other_arc, (BNode *)new_node, (BNode *)other_arc->tail);
+ test_edge = other_arc->edges.last;
+ BLI_remlink(&other_arc->edges, test_edge);
+ MEM_freeN(test_edge);
+ }
+ }
+ }
+
+ BLI_remlink(&arc->edges, first_edge);
+ MEM_freeN(first_edge);
+ BLI_replaceNodeInArc((BGraph *)rg, (BArc *)arc, (BNode *)new_node, (BNode *)arc->head);
+ }
+ else {
+ RigEdge *next_edge = first_edge->next;
+
+ if (next_edge) {
+ BLI_remlink(&arc->edges, first_edge);
+ MEM_freeN(first_edge);
+
+ copy_v3_v3(arc->head->p, next_edge->head);
+
+ /* remove null edge in other arcs too */
+ for (other_arc = rg->arcs.first; other_arc; other_arc = other_arc->next) {
+ if (other_arc != arc) {
+ RigEdge *test_edge;
+ if (other_arc->head == arc->head) {
+ test_edge = other_arc->edges.first;
+ BLI_remlink(&other_arc->edges, test_edge);
+ MEM_freeN(test_edge);
+ }
+ else if (other_arc->tail == arc->head) {
+ test_edge = other_arc->edges.last;
+ BLI_remlink(&other_arc->edges, test_edge);
+ MEM_freeN(test_edge);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (last_edge->bone == NULL) {
+ if (len_v3v3(last_edge->head, arc->tail->p) <= 0.001f) {
+ BLI_remlink(&arc->edges, last_edge);
+ MEM_freeN(last_edge);
+ }
+ else if (arc->tail->degree == 1) {
+ RigNode *new_node = (RigNode *)BLI_FindNodeByPosition((BGraph *)rg, last_edge->head, 0.001f);
+
+ if (new_node) {
+ RigEdge *previous_edge = last_edge->prev;
+
+ BLI_remlink(&arc->edges, last_edge);
+ MEM_freeN(last_edge);
+ BLI_replaceNodeInArc((BGraph *)rg, (BArc *)arc, (BNode *)new_node, (BNode *)arc->tail);
+
+ /* set previous angle to 0, since there's no following edges */
+ if (previous_edge) {
+ previous_edge->angle = 0;
+ }
+ }
+ else {
+ RigEdge *previous_edge = last_edge->prev;
+
+ if (previous_edge) {
+ BLI_remlink(&arc->edges, last_edge);
+ MEM_freeN(last_edge);
+
+ copy_v3_v3(arc->tail->p, previous_edge->tail);
+ previous_edge->angle = 0;
+ }
+ }
+ }
+ }
+ }
+}
+
+static void RIG_arcFromBoneChain(RigGraph *rg, ListBase *list, EditBone *root_bone, RigNode *starting_node, bool selected)
+{
+ EditBone *bone, *last_bone = root_bone;
+ RigArc *arc = NULL;
+ int contain_head = 0;
+
+ for (bone = root_bone; bone; bone = nextEditBoneChild(list, bone, 0)) {
+ int nb_children;
+
+ if (selected == 0 || (bone->flag & BONE_SELECTED)) {
+ if ((bone->flag & BONE_NO_DEFORM) == 0) {
+ BLI_ghash_insert(rg->bones_map, bone->name, bone);
+
+ if (arc == NULL) {
+ arc = newRigArc(rg);
+
+ if (starting_node == NULL) {
+ starting_node = newRigNodeHead(rg, arc, root_bone->head);
+ }
+ else {
+ addRigNodeHead(rg, arc, starting_node);
+ }
+ }
+
+ if (bone->parent && (bone->flag & BONE_CONNECTED) == 0) {
+ RIG_addEdgeToArc(arc, bone->head, NULL);
+ }
+
+ RIG_addEdgeToArc(arc, bone->tail, bone);
+
+ last_bone = bone;
+
+ if (STREQ(bone->name, "head")) {
+ contain_head = 1;
+ }
+ }
+ else if ((bone->flag & BONE_EDITMODE_LOCKED) == 0) { /* ignore locked bones */
+ RIG_addControlBone(rg, bone);
+ }
+ }
+
+ nb_children = countEditBoneChildren(list, bone);
+ if (nb_children > 1) {
+ RigNode *end_node = NULL;
+ int i;
+
+ if (arc != NULL) {
+ end_node = newRigNodeTail(rg, arc, bone->tail);
+ }
+ else {
+ end_node = newRigNode(rg, bone->tail);
+ }
+
+ for (i = 0; i < nb_children; i++) {
+ root_bone = nextEditBoneChild(list, bone, i);
+ RIG_arcFromBoneChain(rg, list, root_bone, end_node, selected);
+ }
+
+ /* arc ends here, break */
+ break;
+ }
+ }
+
+ /* If the loop exited without forking */
+ if (arc != NULL && bone == NULL) {
+ newRigNodeTail(rg, arc, last_bone->tail);
+ }
+
+ if (contain_head) {
+ rg->head = arc->tail;
+ }
+}
+
+/*******************************************************************************************************/
+static void RIG_findHead(RigGraph *rg)
+{
+ if (rg->head == NULL) {
+ if (BLI_listbase_is_single(&rg->arcs)) {
+ RigArc *arc = rg->arcs.first;
+
+ rg->head = (RigNode *)arc->head;
+ }
+ else {
+ RigArc *arc;
+
+ for (arc = rg->arcs.first; arc; arc = arc->next) {
+ RigEdge *edge = arc->edges.last;
+
+ if (edge->bone->flag & (BONE_TIPSEL | BONE_SELECTED)) {
+ rg->head = arc->tail;
+ break;
+ }
+ }
+ }
+
+ if (rg->head == NULL) {
+ rg->head = rg->nodes.first;
+ }
+ }
+}
+
+/*******************************************************************************************************/
+
+static void RIG_printNode(RigNode *node, const char name[])
+{
+ printf("%s %p %i <%0.3f, %0.3f, %0.3f>\n", name, (void *)node, node->degree, node->p[0], node->p[1], node->p[2]);
+
+ if (node->symmetry_flag & SYM_TOPOLOGICAL) {
+ if (node->symmetry_flag & SYM_AXIAL)
+ printf("Symmetry AXIAL\n");
+ else if (node->symmetry_flag & SYM_RADIAL)
+ printf("Symmetry RADIAL\n");
+
+ print_v3("symmetry axis", node->symmetry_axis);
+ }
+}
+
+void RIG_printArcBones(RigArc *arc)
+{
+ RigEdge *edge;
+
+ for (edge = arc->edges.first; edge; edge = edge->next) {
+ if (edge->bone)
+ printf("%s ", edge->bone->name);
+ else
+ printf("---- ");
+ }
+ printf("\n");
+}
+
+static void RIG_printCtrl(RigControl *ctrl, char *indent)
+{
+ char text[128];
+
+ printf("%sBone: %s\n", indent, ctrl->bone->name);
+ printf("%sLink: %s\n", indent, ctrl->link ? ctrl->link->name : "!NONE!");
+
+ BLI_snprintf(text, sizeof(text), "%soffset", indent);
+ print_v3(text, ctrl->offset);
+
+ printf("%sFlag: %i\n", indent, ctrl->flag);
+}
+
+static void RIG_printLinkedCtrl(RigGraph *rg, EditBone *bone, int tabs)
+{
+ RigControl *ctrl;
+ char indent[64];
+ char *s = indent;
+ int i;
+
+ for (i = 0; i < tabs; i++) {
+ s[0] = '\t';
+ s++;
+ }
+ s[0] = 0;
+
+ for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next) {
+ if (ctrl->link == bone) {
+ RIG_printCtrl(ctrl, indent);
+ RIG_printLinkedCtrl(rg, ctrl->bone, tabs + 1);
+ }
+ }
+}
+
+void RIG_printArc(RigGraph *rg, RigArc *arc)
+{
+ RigEdge *edge;
+
+ RIG_printNode((RigNode *)arc->head, "head");
+
+ for (edge = arc->edges.first; edge; edge = edge->next) {
+ printf("\tinner joints %0.3f %0.3f %0.3f\n", edge->tail[0], edge->tail[1], edge->tail[2]);
+ printf("\t\tlength %f\n", edge->length);
+ printf("\t\tangle %f\n", edge->angle * (float)(180 / M_PI));
+ if (edge->bone) {
+ printf("\t\t%s\n", edge->bone->name);
+ RIG_printLinkedCtrl(rg, edge->bone, 3);
+ }
+ }
+ printf("symmetry level: %i flag: %i group %i\n", arc->symmetry_level, arc->symmetry_flag, arc->symmetry_group);
+
+ RIG_printNode((RigNode *)arc->tail, "tail");
+}
+
+void RIG_printGraph(RigGraph *rg)
+{
+ RigArc *arc;
+
+ printf("---- ARCS ----\n");
+ for (arc = rg->arcs.first; arc; arc = arc->next) {
+ RIG_printArc(rg, arc);
+ printf("\n");
+ }
+
+ if (rg->head) {
+ RIG_printNode(rg->head, "HEAD NODE:");
+ }
+ else {
+ printf("HEAD NODE: NONE\n");
+ }
+}
+
+/*******************************************************************************************************/
+
+RigGraph *RIG_graphFromArmature(const bContext *C, Object *ob, bArmature *arm)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ EditBone *ebone;
+ RigGraph *rg;
+
+ rg = newRigGraph();
+
+ if (obedit == ob) {
+ rg->editbones = ((bArmature *)obedit->data)->edbo;
+ }
+ else {
+ rg->editbones = MEM_callocN(sizeof(ListBase), "EditBones");
+ make_boneList(rg->editbones, &arm->bonebase, NULL, NULL);
+ rg->flag |= RIG_FREE_BONELIST;
+ }
+
+ rg->ob = ob;
+
+ /* Do the rotations */
+ for (ebone = rg->editbones->first; ebone; ebone = ebone->next) {
+ if (ebone->parent == NULL) {
+ RIG_arcFromBoneChain(rg, rg->editbones, ebone, NULL, 0);
+ }
+ }
+
+ BLI_removeDoubleNodes((BGraph *)rg, 0.001);
+
+ RIG_removeNormalNodes(rg);
+
+ RIG_removeUneededOffsets(rg);
+
+ BLI_buildAdjacencyList((BGraph *)rg);
+
+ RIG_findHead(rg);
+
+ BLI_markdownSymmetry((BGraph *)rg, (BNode *)rg->head, scene->toolsettings->skgen_symmetry_limit);
+
+ RIG_reconnectControlBones(rg); /* after symmetry, because we use levels to find best match */
+
+ if (BLI_isGraphCyclic((BGraph *)rg)) {
+ printf("armature cyclic\n");
+ }
+
+ return rg;
+}
+
+static RigGraph *armatureSelectedToGraph(bContext *C, Object *ob, bArmature *arm)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ EditBone *ebone;
+ RigGraph *rg;
+
+ rg = newRigGraph();
+
+ if (obedit == ob) {
+ rg->editbones = arm->edbo;
+ }
+ else {
+ rg->editbones = MEM_callocN(sizeof(ListBase), "EditBones");
+ make_boneList(rg->editbones, &arm->bonebase, NULL, NULL);
+ rg->flag |= RIG_FREE_BONELIST;
+ }
+
+ rg->ob = ob;
+
+ /* Do the rotations */
+ for (ebone = rg->editbones->first; ebone; ebone = ebone->next) {
+ if (ebone->parent == NULL) {
+ RIG_arcFromBoneChain(rg, rg->editbones, ebone, NULL, 1);
+ }
+ }
+
+ BLI_removeDoubleNodes((BGraph *)rg, 0.001);
+
+ RIG_removeNormalNodes(rg);
+
+ RIG_removeUneededOffsets(rg);
+
+ BLI_buildAdjacencyList((BGraph *)rg);
+
+ RIG_findHead(rg);
+
+ BLI_markdownSymmetry((BGraph *)rg, (BNode *)rg->head, scene->toolsettings->skgen_symmetry_limit);
+
+ RIG_reconnectControlBones(rg); /* after symmetry, because we use levels to find best match */
+
+ if (BLI_isGraphCyclic((BGraph *)rg)) {
+ printf("armature cyclic\n");
+ }
+
+ return rg;
+}
+/************************************ GENERATING *****************************************************/
+
+#if 0
+static EditBone *add_editbonetolist(char *name, ListBase *list)
+{
+ EditBone *bone = MEM_callocN(sizeof(EditBone), "eBone");
+
+ BLI_strncpy(bone->name, name, sizeof(bone->name));
+ ED_armature_ebone_unique_name(list, bone->name, NULL);
+
+ BLI_addtail(list, bone);
+
+ bone->flag |= BONE_TIPSEL;
+ bone->weight = 1.0F;
+ bone->dist = 0.25F;
+ bone->xwidth = 0.1;
+ bone->zwidth = 0.1;
+ bone->rad_head = 0.10;
+ bone->rad_tail = 0.05;
+ bone->segments = 1;
+ bone->layer = 1; //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;
+}
+#endif
+
+#if 0 /* UNUSED */
+static void generateMissingArcsFromNode(RigGraph *rigg, ReebNode *node, int multi_level_limit)
+{
+ while (node->multi_level > multi_level_limit && node->link_up)
+ {
+ node = node->link_up;
+ }
+
+ while (node->multi_level < multi_level_limit && node->link_down)
+ {
+ node = node->link_down;
+ }
+
+ if (node->multi_level == multi_level_limit)
+ {
+ int i;
+
+ for (i = 0; i < node->degree; i++)
+ {
+ ReebArc *earc = node->arcs[i];
+
+ if (earc->flag == ARC_FREE && earc->head == node)
+ {
+ ReebNode *other = BIF_otherNodeFromIndex(earc, node);
+
+ earc->flag = ARC_USED;
+
+ //generateBonesForArc(rigg, earc, node, other);
+ generateMissingArcsFromNode(rigg, other, multi_level_limit);
+ }
+ }
+ }
+}
+
+static void generateMissingArcs(RigGraph *rigg)
+{
+ ReebGraph *reebg;
+ int multi_level_limit = 5;
+
+ for (reebg = rigg->link_mesh; reebg; reebg = reebg->link_up)
+ {
+ ReebArc *earc;
+
+ for (earc = reebg->arcs.first; earc; earc = earc->next)
+ {
+ if (earc->flag == ARC_USED)
+ {
+ generateMissingArcsFromNode(rigg, earc->head, multi_level_limit);
+ generateMissingArcsFromNode(rigg, earc->tail, multi_level_limit);
+ }
+ }
+ }
+}
+#endif
+
+/************************************ RETARGETTING *****************************************************/
+
+static void repositionControl(RigGraph *rigg, RigControl *ctrl, float head[3], float tail[3], float qrot[4], float resize);
+
+static void repositionTailControl(RigGraph *rigg, RigControl *ctrl);
+
+static void finalizeControl(RigGraph *rigg, RigControl *ctrl, float resize)
+{
+ if ((ctrl->flag & RIG_CTRL_DONE) == RIG_CTRL_DONE) {
+ RigControl *ctrl_child;
+
+#if 0
+ printf("CTRL: %s LINK: %s", ctrl->bone->name, ctrl->link->name);
+
+ if (ctrl->link_tail)
+ {
+ printf(" TAIL: %s", ctrl->link_tail->name);
+ }
+
+ printf("\n");
+#endif
+
+ /* if there was a tail link: apply link, recalc resize factor and qrot */
+ if (ctrl->tail_mode != TL_NONE) {
+ float *tail_vec = NULL;
+ float v1[3], v2[3], qtail[4];
+
+ if (ctrl->tail_mode == TL_TAIL) {
+ tail_vec = ctrl->link_tail->tail;
+ }
+ else if (ctrl->tail_mode == TL_HEAD) {
+ tail_vec = ctrl->link_tail->head;
+ }
+
+ sub_v3_v3v3(v1, ctrl->bone->tail, ctrl->bone->head);
+ sub_v3_v3v3(v2, tail_vec, ctrl->bone->head);
+
+ copy_v3_v3(ctrl->bone->tail, tail_vec);
+
+ rotation_between_vecs_to_quat(qtail, v1, v2);
+ mul_qt_qtqt(ctrl->qrot, qtail, ctrl->qrot);
+
+ resize = len_v3(v2) / len_v3v3(ctrl->head, ctrl->tail);
+ }
+
+ ctrl->bone->roll = rollBoneByQuat(ctrl->bone, ctrl->up_axis, ctrl->qrot);
+
+ /* Cascade to connected control bones */
+ for (ctrl_child = rigg->controls.first; ctrl_child; ctrl_child = ctrl_child->next) {
+ if (ctrl_child->link == ctrl->bone) {
+ repositionControl(rigg, ctrl_child, ctrl->bone->head, ctrl->bone->tail, ctrl->qrot, resize);
+ }
+ if (ctrl_child->link_tail == ctrl->bone) {
+ repositionTailControl(rigg, ctrl_child);
+ }
+ }
+ }
+}
+
+static void repositionTailControl(RigGraph *rigg, RigControl *ctrl)
+{
+ ctrl->flag |= RIG_CTRL_TAIL_DONE;
+
+ finalizeControl(rigg, ctrl, 1); /* resize will be recalculated anyway so we don't need it */
+}
+
+static void repositionControl(RigGraph *rigg, RigControl *ctrl, float head[3], float UNUSED(tail[3]), float qrot[4], float resize)
+{
+ float parent_offset[3], tail_offset[3];
+
+ copy_v3_v3(parent_offset, ctrl->offset);
+ mul_v3_fl(parent_offset, resize);
+ mul_qt_v3(qrot, parent_offset);
+
+ add_v3_v3v3(ctrl->bone->head, head, parent_offset);
+
+ ctrl->flag |= RIG_CTRL_HEAD_DONE;
+
+ copy_qt_qt(ctrl->qrot, qrot);
+
+ if (ctrl->tail_mode == TL_NONE) {
+ sub_v3_v3v3(tail_offset, ctrl->tail, ctrl->head);
+ mul_v3_fl(tail_offset, resize);
+ mul_qt_v3(qrot, tail_offset);
+
+ add_v3_v3v3(ctrl->bone->tail, ctrl->bone->head, tail_offset);
+
+ ctrl->flag |= RIG_CTRL_TAIL_DONE;
+ }
+
+ finalizeControl(rigg, ctrl, resize);
+}
+
+static void repositionBone(bContext *C, RigGraph *rigg, RigEdge *edge, float vec0[3], float vec1[3], float up_axis[3])
+{
+ Scene *scene = CTX_data_scene(C);
+ EditBone *bone;
+ RigControl *ctrl;
+ float qrot[4], resize;
+ float v1[3], v2[3];
+ float l1, l2;
+
+ bone = edge->bone;
+
+ sub_v3_v3v3(v1, edge->tail, edge->head);
+ sub_v3_v3v3(v2, vec1, vec0);
+
+ l1 = normalize_v3(v1);
+ l2 = normalize_v3(v2);
+
+ resize = l2 / l1;
+
+ rotation_between_vecs_to_quat(qrot, v1, v2);
+
+ copy_v3_v3(bone->head, vec0);
+ copy_v3_v3(bone->tail, vec1);
+
+ if (!is_zero_v3(up_axis)) {
+ float qroll[4];
+
+ if (scene->toolsettings->skgen_retarget_roll == SK_RETARGET_ROLL_VIEW) {
+ bone->roll = rollBoneByQuatAligned(bone, edge->up_axis, qrot, qroll, up_axis);
+ }
+ else if (scene->toolsettings->skgen_retarget_roll == SK_RETARGET_ROLL_JOINT) {
+ bone->roll = rollBoneByQuatJoint(edge, edge->prev, qrot, qroll, up_axis);
+ }
+ else {
+ unit_qt(qroll);
+ }
+
+ mul_qt_qtqt(qrot, qroll, qrot);
+ }
+ else {
+ bone->roll = rollBoneByQuat(bone, edge->up_axis, qrot);
+ }
+
+ for (ctrl = rigg->controls.first; ctrl; ctrl = ctrl->next) {
+ if (ctrl->link == bone) {
+ repositionControl(rigg, ctrl, vec0, vec1, qrot, resize);
+ }
+ if (ctrl->link_tail == bone) {
+ repositionTailControl(rigg, ctrl);
+ }
+ }
+}
+
+static RetargetMode detectArcRetargetMode(RigArc *arc);
+static void retargetArctoArcLength(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode *inode_start);
+
+
+static RetargetMode detectArcRetargetMode(RigArc *iarc)
+{
+ RetargetMode mode = RETARGET_AGGRESSIVE;
+ ReebArc *earc = iarc->link_mesh;
+ RigEdge *edge;
+ int large_angle = 0;
+ float avg_angle = 0;
+ /* float avg_length = 0; */ /* UNUSED */
+ int nb_edges = 0;
+
+
+ for (edge = iarc->edges.first; edge; edge = edge->next) {
+ avg_angle += edge->angle;
+ nb_edges++;
+ }
+
+ avg_angle /= nb_edges - 1; /* -1 because last edge doesn't have an angle */
+
+ /* avg_length = iarc->length / nb_edges; */ /* UNUSED */
+
+
+ if (nb_edges > 2) {
+ for (edge = iarc->edges.first; edge; edge = edge->next) {
+ if (fabsf(edge->angle - avg_angle) > (float)(M_PI / 6)) {
+ large_angle = 1;
+ }
+ }
+ }
+ else if (nb_edges == 2 && avg_angle > 0) {
+ large_angle = 1;
+ }
+
+
+ if (large_angle == 0) {
+ mode = RETARGET_LENGTH;
+ }
+
+ if (earc->bcount <= (iarc->count - 1)) {
+ mode = RETARGET_LENGTH;
+ }
+
+ return mode;
+}
+
+#ifndef USE_THREADS
+static void printMovesNeeded(int *positions, int nb_positions)
+{
+ int moves = 0;
+ int i;
+
+ for (i = 0; i < nb_positions; i++) {
+ moves += positions[i] - (i + 1);
+ }
+
+ printf("%i moves needed\n", moves);
+}
+
+static void printPositions(int *positions, int nb_positions)
+{
+ int i;
+
+ for (i = 0; i < nb_positions; i++) {
+ printf("%i ", positions[i]);
+ }
+ printf("\n");
+}
+#endif
+
+#define MAX_COST FLT_MAX /* FIX ME */
+
+static float costDistance(BArcIterator *iter, float *vec0, float *vec1, int i0, int i1, float distance_weight)
+{
+ EmbedBucket *bucket = NULL;
+ float max_dist = 0;
+ float v1[3], v2[3], c[3];
+ float v1_inpf;
+
+ if (distance_weight > 0) {
+ sub_v3_v3v3(v1, vec0, vec1);
+
+ v1_inpf = dot_v3v3(v1, v1);
+
+ if (v1_inpf > 0) {
+ int j;
+ for (j = i0 + 1; j < i1 - 1; j++) {
+ float dist;
+
+ bucket = IT_peek(iter, j);
+
+ sub_v3_v3v3(v2, bucket->p, vec1);
+
+ cross_v3_v3v3(c, v1, v2);
+
+ dist = dot_v3v3(c, c) / v1_inpf;
+
+ max_dist = dist > max_dist ? dist : max_dist;
+ }
+
+ return distance_weight * max_dist;
+ }
+ else {
+ return MAX_COST;
+ }
+ }
+ else {
+ return 0;
+ }
+}
+
+static float costAngle(float original_angle, float vec_first[3], float vec_second[3], float angle_weight)
+{
+ if (angle_weight > 0) {
+ float current_angle;
+
+ if (!is_zero_v3(vec_first) && !is_zero_v3(vec_second)) {
+ current_angle = saacos(dot_v3v3(vec_first, vec_second));
+
+ return angle_weight * fabsf(current_angle - original_angle);
+ }
+ else {
+ return angle_weight * (float)M_PI;
+ }
+ }
+ else {
+ return 0;
+ }
+}
+
+static float costLength(float original_length, float current_length, float length_weight)
+{
+ if (current_length == 0) {
+ return MAX_COST;
+ }
+ else {
+ float length_ratio = fabsf((current_length - original_length) / original_length);
+ return length_weight * length_ratio * length_ratio;
+ }
+}
+
+#if 0
+static float calcCostLengthDistance(BArcIterator *iter, float **vec_cache, RigEdge *edge, float *vec1, float *vec2, int i1, int i2)
+{
+ float vec[3];
+ float length;
+
+ sub_v3_v3v3(vec, vec2, vec1);
+ length = normalize_v3(vec);
+
+ return costLength(edge->length, length) + costDistance(iter, vec1, vec2, i1, i2);
+}
+#endif
+
+static float calcCostAngleLengthDistance(BArcIterator *iter, float **UNUSED(vec_cache), RigEdge *edge,
+ float *vec0, float *vec1, float *vec2, int i1, int i2,
+ float angle_weight, float length_weight, float distance_weight)
+{
+ float vec_second[3], vec_first[3];
+ float length2;
+ float new_cost = 0;
+
+ sub_v3_v3v3(vec_second, vec2, vec1);
+ length2 = normalize_v3(vec_second);
+
+
+ /* Angle cost */
+ if (edge->prev) {
+ sub_v3_v3v3(vec_first, vec1, vec0);
+ normalize_v3(vec_first);
+
+ new_cost += costAngle(edge->prev->angle, vec_first, vec_second, angle_weight);
+ }
+
+ /* Length cost */
+ new_cost += costLength(edge->length, length2, length_weight);
+
+ /* Distance cost */
+ new_cost += costDistance(iter, vec1, vec2, i1, i2, distance_weight);
+
+ return new_cost;
+}
+
+static int indexMemoNode(int nb_positions, int previous, int current, int joints_left)
+{
+ return joints_left * nb_positions * nb_positions + current * nb_positions + previous;
+}
+
+static void copyMemoPositions(int *positions, MemoNode *table, int nb_positions, int joints_left)
+{
+ int previous = 0, current = 0;
+ int i = 0;
+
+ for (i = 0; joints_left > 0; joints_left--, i++) {
+ MemoNode *node;
+ node = table + indexMemoNode(nb_positions, previous, current, joints_left);
+
+ positions[i] = node->next;
+
+ previous = current;
+ current = node->next;
+ }
+}
+
+static MemoNode *solveJoints(MemoNode *table, BArcIterator *iter, float **vec_cache,
+ int nb_joints, int nb_positions, int previous, int current, RigEdge *edge,
+ int joints_left, float angle_weight, float length_weight, float distance_weight)
+{
+ MemoNode *node;
+ int index = indexMemoNode(nb_positions, previous, current, joints_left);
+
+ node = table + index;
+
+ if (node->weight != 0) {
+ return node;
+ }
+ else if (joints_left == 0) {
+ float *vec0 = vec_cache[previous];
+ float *vec1 = vec_cache[current];
+ float *vec2 = vec_cache[nb_positions + 1];
+
+ node->weight = calcCostAngleLengthDistance(iter, vec_cache, edge, vec0, vec1, vec2, current, iter->length, angle_weight, length_weight, distance_weight);
+
+ return node;
+ }
+ else {
+ MemoNode *min_node = NULL;
+ float *vec0 = vec_cache[previous];
+ float *vec1 = vec_cache[current];
+ float min_weight = 0.0f;
+ int min_next = 0;
+ int next;
+
+ for (next = current + 1; next <= nb_positions - (joints_left - 1); next++) {
+ MemoNode *next_node;
+ float *vec2 = vec_cache[next];
+ float weight = 0.0f;
+
+ /* ADD WEIGHT OF PREVIOUS - CURRENT - NEXT triple */
+ weight = calcCostAngleLengthDistance(iter, vec_cache, edge, vec0, vec1, vec2, current, next, angle_weight, length_weight, distance_weight);
+
+ if (weight >= MAX_COST) {
+ continue;
+ }
+
+ /* add node weight */
+ next_node = solveJoints(table, iter, vec_cache, nb_joints, nb_positions, current, next, edge->next, joints_left - 1, angle_weight, length_weight, distance_weight);
+ weight += next_node->weight;
+
+ if (min_node == NULL || weight < min_weight) {
+ min_weight = weight;
+ min_node = next_node;
+ min_next = next;
+ }
+ }
+
+ if (min_node) {
+ node->weight = min_weight;
+ node->next = min_next;
+ return node;
+ }
+ else {
+ node->weight = MAX_COST;
+ return node;
+ }
+ }
+
+}
+
+static int testFlipArc(RigArc *iarc, RigNode *inode_start)
+{
+ ReebArc *earc = iarc->link_mesh;
+ ReebNode *enode_start = BIF_NodeFromIndex(earc, inode_start->link_mesh);
+
+ /* no flip needed if both nodes are the same */
+ if ((enode_start == earc->head && inode_start == iarc->head) ||
+ (enode_start == earc->tail && inode_start == iarc->tail))
+ {
+ return 0;
+ }
+ else {
+ return 1;
+ }
+}
+
+static void retargetArctoArcAggresive(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode *inode_start)
+{
+ ReebArcIterator arc_iter;
+ BArcIterator *iter = (BArcIterator *)&arc_iter;
+ RigEdge *edge;
+ ReebNode *node_start, *node_end;
+ ReebArc *earc = iarc->link_mesh;
+ float angle_weight = 1.0; // GET FROM CONTEXT
+ float length_weight = 1.0;
+ float distance_weight = 1.0;
+#ifndef USE_THREADS
+ float min_cost = FLT_MAX;
+#endif
+ float *vec0, *vec1;
+ int *best_positions;
+ int nb_edges = BLI_listbase_count(&iarc->edges);
+ int nb_joints = nb_edges - 1;
+ RetargetMethod method = METHOD_MEMOIZE;
+ int i;
+
+ if (nb_joints > earc->bcount) {
+ printf("NOT ENOUGH BUCKETS!\n");
+ return;
+ }
+
+ best_positions = MEM_callocN(sizeof(int) * nb_joints, "Best positions");
+
+ if (testFlipArc(iarc, inode_start)) {
+ node_start = earc->tail;
+ node_end = earc->head;
+ }
+ else {
+ node_start = earc->head;
+ node_end = earc->tail;
+ }
+
+ /* equal number of joints and potential position, just fill them in */
+ if (nb_joints == earc->bcount) {
+ /* init with first values */
+ for (i = 0; i < nb_joints; i++) {
+ best_positions[i] = i + 1;
+ }
+ }
+ if (method == METHOD_MEMOIZE) {
+ int nb_positions = earc->bcount;
+ int nb_memo_nodes = nb_positions * nb_positions * (nb_joints + 1);
+ MemoNode *table = MEM_callocN(nb_memo_nodes * sizeof(MemoNode), "memoization table");
+#ifndef USE_THREADS
+ MemoNode *result;
+#endif
+ float **positions_cache = MEM_callocN(sizeof(float *) * (nb_positions + 2), "positions cache");
+
+ positions_cache[0] = node_start->p;
+ positions_cache[nb_positions + 1] = node_end->p;
+
+ initArcIterator(iter, earc, node_start);
+
+ for (i = 1; i <= nb_positions; i++) {
+ EmbedBucket *bucket = IT_peek(iter, i);
+ positions_cache[i] = bucket->p;
+ }
+
+#ifndef USE_THREADS
+ result = solveJoints(table, iter, positions_cache, nb_joints, earc->bcount, 0, 0, iarc->edges.first, nb_joints, angle_weight, length_weight, distance_weight);
+ min_cost = result->weight;
+#else
+ solveJoints(table, iter, positions_cache, nb_joints, earc->bcount, 0, 0, iarc->edges.first, nb_joints, angle_weight, length_weight, distance_weight);
+#endif
+
+ copyMemoPositions(best_positions, table, earc->bcount, nb_joints);
+
+ MEM_freeN(table);
+ MEM_freeN(positions_cache);
+ }
+
+ vec0 = node_start->p;
+ initArcIterator(iter, earc, node_start);
+
+#ifndef USE_THREADS
+ printPositions(best_positions, nb_joints);
+ printMovesNeeded(best_positions, nb_joints);
+ printf("min_cost %f\n", min_cost);
+ printf("buckets: %i\n", earc->bcount);
+#endif
+
+ /* set joints to best position */
+ for (edge = iarc->edges.first, i = 0;
+ edge;
+ edge = edge->next, i++)
+ {
+ float *no = NULL;
+ if (i < nb_joints) {
+ EmbedBucket *bucket = IT_peek(iter, best_positions[i]);
+ vec1 = bucket->p;
+ no = bucket->no;
+ }
+ else {
+ vec1 = node_end->p;
+ no = node_end->no;
+ }
+
+ if (edge->bone) {
+ repositionBone(C, rigg, edge, vec0, vec1, no);
+ }
+
+ vec0 = vec1;
+ }
+
+ MEM_freeN(best_positions);
+}
+
+static void retargetArctoArcLength(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode *inode_start)
+{
+ ReebArcIterator arc_iter;
+ BArcIterator *iter = (BArcIterator *)&arc_iter;
+ ReebArc *earc = iarc->link_mesh;
+ ReebNode *node_start, *node_end;
+ RigEdge *edge;
+ EmbedBucket *bucket = NULL;
+ float embedding_length = 0;
+ float *vec0 = NULL;
+ float *vec1 = NULL;
+ float *previous_vec = NULL;
+
+
+ if (testFlipArc(iarc, inode_start)) {
+ node_start = (ReebNode *)earc->tail;
+ node_end = (ReebNode *)earc->head;
+ }
+ else {
+ node_start = (ReebNode *)earc->head;
+ node_end = (ReebNode *)earc->tail;
+ }
+
+ initArcIterator(iter, earc, node_start);
+
+ bucket = IT_next(iter);
+
+ vec0 = node_start->p;
+
+ while (bucket != NULL) {
+ vec1 = bucket->p;
+
+ embedding_length += len_v3v3(vec0, vec1);
+
+ vec0 = vec1;
+ bucket = IT_next(iter);
+ }
+
+ embedding_length += len_v3v3(node_end->p, vec1);
+
+ /* fit bones */
+ initArcIterator(iter, earc, node_start);
+
+ bucket = IT_next(iter);
+
+ vec0 = node_start->p;
+ previous_vec = vec0;
+ vec1 = bucket->p;
+
+ for (edge = iarc->edges.first; edge; edge = edge->next) {
+ float new_bone_length = edge->length / iarc->length * embedding_length;
+ float *no = NULL;
+ float length = 0;
+
+ while (bucket && new_bone_length > length) {
+ length += len_v3v3(previous_vec, vec1);
+ bucket = IT_next(iter);
+ previous_vec = vec1;
+ vec1 = bucket->p;
+ no = bucket->no;
+ }
+
+ if (bucket == NULL) {
+ vec1 = node_end->p;
+ no = node_end->no;
+ }
+
+ /* no need to move virtual edges (space between unconnected bones) */
+ if (edge->bone) {
+ repositionBone(C, rigg, edge, vec0, vec1, no);
+ }
+
+ vec0 = vec1;
+ previous_vec = vec1;
+ }
+}
+
+static void retargetArctoArc(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode *inode_start)
+{
+ RetargetParam *p = MEM_callocN(sizeof(RetargetParam), "RetargetParam");
+
+ p->rigg = rigg;
+ p->iarc = iarc;
+ p->inode_start = inode_start;
+ p->context = C;
+
+ BLI_task_pool_push(rigg->task_pool, exec_retargetArctoArc, p, true, TASK_PRIORITY_HIGH);
+}
+
+void exec_retargetArctoArc(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
+{
+ RetargetParam *p = (RetargetParam *)taskdata;
+ RigGraph *rigg = p->rigg;
+ RigArc *iarc = p->iarc;
+ bContext *C = p->context;
+ RigNode *inode_start = p->inode_start;
+ ReebArc *earc = iarc->link_mesh;
+
+ if (BLI_listbase_is_single(&iarc->edges)) {
+ RigEdge *edge = iarc->edges.first;
+
+ if (testFlipArc(iarc, inode_start)) {
+ repositionBone(C, rigg, edge, earc->tail->p, earc->head->p, earc->head->no);
+ }
+ else {
+ repositionBone(C, rigg, edge, earc->head->p, earc->tail->p, earc->tail->no);
+ }
+ }
+ else {
+ RetargetMode mode = detectArcRetargetMode(iarc);
+
+ if (mode == RETARGET_AGGRESSIVE) {
+ retargetArctoArcAggresive(C, rigg, iarc, inode_start);
+ }
+ else {
+ retargetArctoArcLength(C, rigg, iarc, inode_start);
+ }
+ }
+}
+
+static void matchMultiResolutionNode(RigGraph *rigg, RigNode *inode, ReebNode *top_node)
+{
+ ReebNode *enode = top_node;
+ ReebGraph *reebg = BIF_graphForMultiNode(rigg->link_mesh, enode);
+ int ishape, eshape;
+
+ ishape = BLI_subtreeShape((BGraph *)rigg, (BNode *)inode, NULL, 0) % SHAPE_LEVELS;
+ eshape = BLI_subtreeShape((BGraph *)reebg, (BNode *)enode, NULL, 0) % SHAPE_LEVELS;
+
+ inode->link_mesh = enode;
+
+ while (ishape == eshape && enode->link_down) {
+ inode->link_mesh = enode;
+
+ enode = enode->link_down;
+ reebg = BIF_graphForMultiNode(rigg->link_mesh, enode); /* replace with call to link_down once that exists */
+ eshape = BLI_subtreeShape((BGraph *)reebg, (BNode *)enode, NULL, 0) % SHAPE_LEVELS;
+ }
+}
+
+static void markMultiResolutionChildArc(ReebNode *end_enode, ReebNode *enode)
+{
+ int i;
+
+ for (i = 0; i < enode->degree; i++) {
+ ReebArc *earc = (ReebArc *)enode->arcs[i];
+
+ if (earc->flag == ARC_FREE) {
+ earc->flag = ARC_TAKEN;
+
+ if (earc->tail->degree > 1 && earc->tail != end_enode) {
+ markMultiResolutionChildArc(end_enode, earc->tail);
+ }
+ break;
+ }
+ }
+}
+
+static void markMultiResolutionArc(ReebArc *start_earc)
+{
+ if (start_earc->link_up) {
+ ReebArc *earc;
+ for (earc = start_earc->link_up; earc; earc = earc->link_up) {
+ earc->flag = ARC_TAKEN;
+
+ if (earc->tail->index != start_earc->tail->index) {
+ markMultiResolutionChildArc(earc->tail, earc->tail);
+ }
+ }
+ }
+}
+
+static void matchMultiResolutionArc(RigGraph *rigg, RigNode *start_node, RigArc *next_iarc, ReebArc *next_earc)
+{
+ ReebNode *enode = next_earc->head;
+ ReebGraph *reebg = BIF_graphForMultiNode(rigg->link_mesh, enode);
+ int ishape, eshape;
+
+ ishape = BLI_subtreeShape((BGraph *)rigg, (BNode *)start_node, (BArc *)next_iarc, 1) % SHAPE_LEVELS;
+ eshape = BLI_subtreeShape((BGraph *)reebg, (BNode *)enode, (BArc *)next_earc, 1) % SHAPE_LEVELS;
+
+ while (ishape != eshape && next_earc->link_up) {
+ next_earc->flag = ARC_TAKEN; // mark previous as taken, to prevent backtrack on lower levels
+
+ next_earc = next_earc->link_up;
+ reebg = reebg->link_up;
+ enode = next_earc->head;
+ eshape = BLI_subtreeShape((BGraph *)reebg, (BNode *)enode, (BArc *)next_earc, 1) % SHAPE_LEVELS;
+ }
+
+ next_earc->flag = ARC_USED;
+ next_iarc->link_mesh = next_earc;
+
+ /* mark all higher levels as taken too */
+ markMultiResolutionArc(next_earc);
+// while (next_earc->link_up)
+// {
+// next_earc = next_earc->link_up;
+// next_earc->flag = ARC_TAKEN;
+// }
+}
+
+static void matchMultiResolutionStartingNode(RigGraph *rigg, ReebGraph *reebg, RigNode *inode)
+{
+ ReebNode *enode;
+ int ishape, eshape;
+
+ enode = reebg->nodes.first;
+
+ ishape = BLI_subtreeShape((BGraph *)rigg, (BNode *)inode, NULL, 0) % SHAPE_LEVELS;
+ eshape = BLI_subtreeShape((BGraph *)rigg->link_mesh, (BNode *)enode, NULL, 0) % SHAPE_LEVELS;
+
+ while (ishape != eshape && reebg->link_up) {
+ reebg = reebg->link_up;
+
+ enode = reebg->nodes.first;
+
+ eshape = BLI_subtreeShape((BGraph *)reebg, (BNode *)enode, NULL, 0) % SHAPE_LEVELS;
+ }
+
+ inode->link_mesh = enode;
+}
+
+static void findCorrespondingArc(RigGraph *rigg, RigArc *start_arc, RigNode *start_node, RigArc *next_iarc, int root)
+{
+ ReebNode *enode = start_node->link_mesh;
+ ReebArc *next_earc;
+ int symmetry_level = next_iarc->symmetry_level;
+ int symmetry_group = next_iarc->symmetry_group;
+ int symmetry_flag = next_iarc->symmetry_flag;
+ int i;
+
+ next_iarc->link_mesh = NULL;
+
+// if (root)
+// {
+// printf("-----------------------\n");
+// printf("MATCHING LIMB\n");
+// RIG_printArcBones(next_iarc);
+// }
+
+ for (i = 0; i < enode->degree; i++) {
+ next_earc = (ReebArc *)enode->arcs[i];
+
+// if (next_earc->flag == ARC_FREE)
+// {
+// printf("candidate (level %i ?= %i) (flag %i ?= %i) (group %i ?= %i)\n",
+// symmetry_level, next_earc->symmetry_level,
+// symmetry_flag, next_earc->symmetry_flag,
+// symmetry_group, next_earc->symmetry_flag);
+// }
+
+ if (next_earc->flag == ARC_FREE &&
+ next_earc->symmetry_flag == symmetry_flag &&
+ next_earc->symmetry_group == symmetry_group &&
+ next_earc->symmetry_level == symmetry_level)
+ {
+// printf("CORRESPONDING ARC FOUND\n");
+// printf("flag %i -- level %i -- flag %i -- group %i\n", next_earc->flag, next_earc->symmetry_level, next_earc->symmetry_flag, next_earc->symmetry_group);
+
+ matchMultiResolutionArc(rigg, start_node, next_iarc, next_earc);
+ break;
+ }
+ }
+
+ /* not found, try at higher nodes (lower node might have filtered internal arcs, messing shape of tree */
+ if (next_iarc->link_mesh == NULL) {
+// printf("NO CORRESPONDING ARC FOUND - GOING TO HIGHER LEVELS\n");
+
+ if (enode->link_up) {
+ start_node->link_mesh = enode->link_up;
+ findCorrespondingArc(rigg, start_arc, start_node, next_iarc, 0);
+ }
+ }
+
+ /* still not found, print debug info */
+ if (root && next_iarc->link_mesh == NULL) {
+ start_node->link_mesh = enode; /* linking back with root node */
+
+// printf("NO CORRESPONDING ARC FOUND\n");
+// RIG_printArcBones(next_iarc);
+//
+// printf("ON NODE %i, multilevel %i\n", enode->index, enode->multi_level);
+//
+// printf("LOOKING FOR\n");
+// printf("flag %i -- level %i -- flag %i -- group %i\n", ARC_FREE, symmetry_level, symmetry_flag, symmetry_group);
+//
+// printf("CANDIDATES\n");
+// for (i = 0; i < enode->degree; i++)
+// {
+// next_earc = (ReebArc *)enode->arcs[i];
+// printf("flag %i -- level %i -- flag %i -- group %i\n", next_earc->flag, next_earc->symmetry_level, next_earc->symmetry_flag, next_earc->symmetry_group);
+// }
+
+ /* Emergency matching */
+ for (i = 0; i < enode->degree; i++) {
+ next_earc = (ReebArc *)enode->arcs[i];
+
+ if (next_earc->flag == ARC_FREE && next_earc->symmetry_level == symmetry_level) {
+// printf("USING:\n");
+// printf("flag %i -- level %i -- flag %i -- group %i\n", next_earc->flag, next_earc->symmetry_level, next_earc->symmetry_flag, next_earc->symmetry_group);
+ matchMultiResolutionArc(rigg, start_node, next_iarc, next_earc);
+ break;
+ }
+ }
+ }
+
+}
+
+static void retargetSubgraph(bContext *C, RigGraph *rigg, RigArc *start_arc, RigNode *start_node)
+{
+ RigNode *inode = start_node;
+ int i;
+
+ /* no start arc on first node */
+ if (start_arc) {
+ ReebNode *enode = start_node->link_mesh;
+ ReebArc *earc = start_arc->link_mesh;
+
+ retargetArctoArc(C, rigg, start_arc, start_node);
+
+ enode = BIF_otherNodeFromIndex(earc, enode);
+ inode = (RigNode *)BLI_otherNode((BArc *)start_arc, (BNode *)inode);
+
+ /* match with lowest node with correct shape */
+ matchMultiResolutionNode(rigg, inode, enode);
+ }
+
+ for (i = 0; i < inode->degree; i++) {
+ RigArc *next_iarc = (RigArc *)inode->arcs[i];
+
+ /* no back tracking */
+ if (next_iarc != start_arc) {
+ findCorrespondingArc(rigg, start_arc, inode, next_iarc, 1);
+ if (next_iarc->link_mesh) {
+ retargetSubgraph(C, rigg, next_iarc, inode);
+ }
+ }
+ }
+}
+
+static void finishRetarget(RigGraph *rigg)
+{
+ BLI_task_pool_work_and_wait(rigg->task_pool);
+}
+
+static void adjustGraphs(bContext *C, RigGraph *rigg)
+{
+ Main *bmain = CTX_data_main(C);
+ bArmature *arm = rigg->ob->data;
+ RigArc *arc;
+
+ for (arc = rigg->arcs.first; arc; arc = arc->next) {
+ if (arc->link_mesh) {
+ retargetArctoArc(C, rigg, arc, arc->head);
+ }
+ }
+
+ finishRetarget(rigg);
+
+ /* Turn the list into an armature */
+ arm->edbo = rigg->editbones;
+ ED_armature_from_edit(bmain, arm);
+
+ ED_undo_push(C, "Retarget Skeleton");
+}
+
+static void retargetGraphs(bContext *C, RigGraph *rigg)
+{
+ Main *bmain = CTX_data_main(C);
+ bArmature *arm = rigg->ob->data;
+ ReebGraph *reebg = rigg->link_mesh;
+ RigNode *inode;
+
+ /* flag all ReebArcs as free */
+ BIF_flagMultiArcs(reebg, ARC_FREE);
+
+ /* return to first level */
+ inode = rigg->head;
+
+ matchMultiResolutionStartingNode(rigg, reebg, inode);
+
+ retargetSubgraph(C, rigg, NULL, inode);
+
+ //generateMissingArcs(rigg);
+
+ finishRetarget(rigg);
+
+ /* Turn the list into an armature */
+ arm->edbo = rigg->editbones;
+ ED_armature_from_edit(bmain, arm);
+}
+
+const char *RIG_nameBone(RigGraph *rg, int arc_index, int bone_index)
+{
+ RigArc *arc = BLI_findlink(&rg->arcs, arc_index);
+ RigEdge *iedge;
+
+ if (arc == NULL) {
+ return "None";
+ }
+
+ if (bone_index == BLI_listbase_count(&arc->edges)) {
+ return "Last joint";
+ }
+
+ iedge = BLI_findlink(&arc->edges, bone_index);
+
+ if (iedge == NULL) {
+ return "Done";
+ }
+
+ if (iedge->bone == NULL) {
+ return "Bone offset";
+ }
+
+ return iedge->bone->name;
+}
+
+int RIG_nbJoints(RigGraph *rg)
+{
+ RigArc *arc;
+ int total = 0;
+
+ total += BLI_listbase_count(&rg->nodes);
+
+ for (arc = rg->arcs.first; arc; arc = arc->next) {
+ total += BLI_listbase_count(&arc->edges) - 1; /* -1 because end nodes are already counted */
+ }
+
+ return total;
+}
+
+static void BIF_freeRetarget(void)
+{
+ if (GLOBAL_RIGG) {
+ RIG_freeRigGraph((BGraph *)GLOBAL_RIGG);
+ GLOBAL_RIGG = NULL;
+ }
+}
+
+void BIF_retargetArmature(bContext *C)
+{
+ ReebGraph *reebg;
+ double start_time, end_time;
+ double gstart_time, gend_time;
+ double reeb_time, rig_time = 0.0, retarget_time = 0.0, total_time;
+
+ gstart_time = start_time = PIL_check_seconds_timer();
+
+ reebg = BIF_ReebGraphMultiFromEditMesh(C);
+
+ end_time = PIL_check_seconds_timer();
+ reeb_time = end_time - start_time;
+
+ printf("Reeb Graph created\n");
+
+ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
+ {
+ Object *ob = base->object;
+
+ if (ob->type == OB_ARMATURE) {
+ RigGraph *rigg;
+ bArmature *arm;
+
+ arm = ob->data;
+
+ /* Put the armature into editmode */
+
+
+ start_time = PIL_check_seconds_timer();
+
+ rigg = RIG_graphFromArmature(C, ob, arm);
+
+ end_time = PIL_check_seconds_timer();
+ rig_time = end_time - start_time;
+
+ printf("Armature graph created\n");
+
+ //RIG_printGraph(rigg);
+
+ rigg->link_mesh = reebg;
+
+ printf("retargetting %s\n", ob->id.name);
+
+ start_time = PIL_check_seconds_timer();
+
+ retargetGraphs(C, rigg);
+
+ end_time = PIL_check_seconds_timer();
+ retarget_time = end_time - start_time;
+
+ BIF_freeRetarget();
+
+ GLOBAL_RIGG = rigg;
+
+ break; /* only one armature at a time */
+ }
+ }
+ CTX_DATA_END;
+
+
+ gend_time = PIL_check_seconds_timer();
+
+ total_time = gend_time - gstart_time;
+
+ printf("-----------\n");
+ printf("runtime: \t%.3f\n", total_time);
+ printf("reeb: \t\t%.3f (%.1f%%)\n", reeb_time, reeb_time / total_time * 100);
+ printf("rig: \t\t%.3f (%.1f%%)\n", rig_time, rig_time / total_time * 100);
+ printf("retarget: \t%.3f (%.1f%%)\n", retarget_time, retarget_time / total_time * 100);
+ printf("-----------\n");
+
+ ED_undo_push(C, "Retarget Skeleton");
+
+ // XXX
+// allqueue(REDRAWVIEW3D, 0);
+}
+
+void BIF_retargetArc(bContext *C, ReebArc *earc, RigGraph *template_rigg)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ bArmature *armedit = obedit->data;
+ Object *ob;
+ RigGraph *rigg;
+ RigArc *iarc;
+ char *side_string = scene->toolsettings->skgen_side_string;
+ char *num_string = scene->toolsettings->skgen_num_string;
+ int free_template = 0;
+
+ if (template_rigg) {
+ ob = template_rigg->ob;
+ }
+ else {
+ free_template = 1;
+ ob = obedit;
+ template_rigg = armatureSelectedToGraph(C, ob, ob->data);
+ }
+
+ if (BLI_listbase_is_empty(&template_rigg->arcs)) {
+// XXX
+// error("No Template and no deforming bones selected");
+ return;
+ }
+
+ rigg = cloneRigGraph(template_rigg, armedit->edbo, obedit, side_string, num_string);
+
+ iarc = rigg->arcs.first;
+
+ iarc->link_mesh = earc;
+ iarc->head->link_mesh = earc->head;
+ iarc->tail->link_mesh = earc->tail;
+
+ retargetArctoArc(C, rigg, iarc, iarc->head);
+
+ finishRetarget(rigg);
+
+ /* free template if it comes from the edit armature */
+ if (free_template) {
+ RIG_freeRigGraph((BGraph *)template_rigg);
+ }
+ RIG_freeRigGraph((BGraph *)rigg);
+
+ ED_armature_edit_validate_active(armedit);
+
+// XXX
+// allqueue(REDRAWVIEW3D, 0);
+}
+
+void BIF_adjustRetarget(bContext *C)
+{
+ if (GLOBAL_RIGG) {
+ adjustGraphs(C, GLOBAL_RIGG);
+ }
+}
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index aa0e13a3e16..001c8ce215f 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -29,6 +29,7 @@
#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
#include "DNA_scene_types.h"
#include "BLI_math.h"
@@ -39,9 +40,10 @@
#include "BLT_translation.h"
-#include "BKE_DerivedMesh.h"
-#include "BKE_modifier.h"
+#include "BKE_bvhutils.h"
#include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
+#include "BKE_modifier.h"
#include "ED_mesh.h"
#include "ED_armature.h"
@@ -96,7 +98,7 @@ struct LaplacianSystem {
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;
@@ -107,7 +109,7 @@ struct LaplacianSystem {
/* Computation of these weights for the laplacian is based on:
* "Discrete Differential-Geometry Operators for Triangulated 2-Manifolds",
* Meyer et al, 2002. Section 3.5, formula (8).
- *
+ *
* We do it a bit different by going over faces instead of going over each
* vertex and adjacent faces, since we don't store this adjacency. Also, the
* formulas are tweaked a bit to work for non-manifold meshes. */
@@ -261,7 +263,7 @@ static void laplacian_system_construct_end(LaplacianSystem *sys)
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)
@@ -277,7 +279,7 @@ static void laplacian_system_construct_end(LaplacianSystem *sys)
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]);
@@ -405,7 +407,7 @@ static void heat_ray_tree_create(LaplacianSystem *sys)
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;
@@ -416,14 +418,14 @@ static void heat_ray_tree_create(LaplacianSystem *sys)
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);
+ BLI_bvhtree_balance(sys->heat.bvhtree);
}
static int heat_ray_source_visible(LaplacianSystem *sys, int vertex, int source)
@@ -459,7 +461,7 @@ static int heat_ray_source_visible(LaplacianSystem *sys, int vertex, int source)
static float heat_source_distance(LaplacianSystem *sys, int vertex, int source)
{
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]);
@@ -481,7 +483,7 @@ static int heat_source_closest(LaplacianSystem *sys, int vertex, int source)
if (dist <= sys->heat.mindist[vertex] * (1.0f + DISTANCE_EPSILON))
if (heat_ray_source_visible(sys, vertex, source))
return 1;
-
+
return 0;
}
@@ -516,7 +518,7 @@ static void heat_set_H(LaplacianSystem *sys, int vertex)
}
else
h = 0.0f;
-
+
sys->heat.H[vertex] = h;
}
@@ -533,7 +535,7 @@ static void heat_calc_vnormals(LaplacianSystem *sys)
v3 = (*face)[2];
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);
@@ -680,7 +682,7 @@ void heat_bone_weighting(
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])
@@ -718,7 +720,7 @@ void heat_bone_weighting(
continue;
solution = laplacian_system_get_solution(sys, a);
-
+
if (bbone) {
if (solution > 0.0f)
ED_vgroup_vert_add(ob, dgrouplist[j], a, solution,
@@ -853,7 +855,7 @@ typedef struct MeshDeformBind {
/* direct solver */
int *varidx;
-
+
BVHTree *bvhtree;
BVHTreeFromMesh bvhdata;
@@ -874,7 +876,7 @@ typedef struct MeshDeformIsect {
bool isect;
float u, v;
-
+
} MeshDeformIsect;
/* ray intersection */
@@ -894,9 +896,9 @@ static void harmonic_ray_callback(void *userdata, int index, const BVHTreeRay *r
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];
@@ -920,7 +922,7 @@ static void harmonic_ray_callback(void *userdata, int index, const BVHTreeRay *r
hit->index = index;
hit->dist = dist;
copy_v3_v3(hit->co, co);
-
+
isec->isect = (dot_v3v3(no, ray->direction) <= 0.0f);
isec->lambda = dist;
}
@@ -1003,7 +1005,7 @@ static int meshdeform_inside_cage(MeshDeformBind *mdb, float *co)
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;
@@ -1017,7 +1019,7 @@ static int meshdeform_inside_cage(MeshDeformBind *mdb, float *co)
BLI_INLINE int meshdeform_index(MeshDeformBind *mdb, int x, int y, int z, int n)
{
int size = mdb->size;
-
+
x += MESHDEFORM_OFFSET[n][0];
y += MESHDEFORM_OFFSET[n][1];
z += MESHDEFORM_OFFSET[n][2];
@@ -1121,7 +1123,7 @@ static void meshdeform_bind_floodfill(MeshDeformBind *mdb)
if (mdb->semibound[a])
ts++;
}
-
+
printf("interior %d exterior %d boundary %d semi-boundary %d\n", ti, te, tb, ts);
}
#endif
@@ -1230,7 +1232,7 @@ static void meshdeform_matrix_add_cell(MeshDeformBind *mdb, LinearSolver *contex
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);
@@ -1280,7 +1282,7 @@ static void meshdeform_matrix_add_semibound_phi(MeshDeformBind *mdb, int x, int
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);
@@ -1418,7 +1420,7 @@ static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind
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);
@@ -1504,7 +1506,7 @@ static void harmonic_coordinates_bind(Scene *UNUSED(scene), MeshDeformModifierDa
/* 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++)
@@ -1591,7 +1593,7 @@ void ED_mesh_deform_bind_callback(
/* 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");
diff --git a/source/blender/editors/armature/meshlaplacian.h b/source/blender/editors/armature/meshlaplacian.h
index 9c4ceacbee6..6758f9d16ac 100644
--- a/source/blender/editors/armature/meshlaplacian.h
+++ b/source/blender/editors/armature/meshlaplacian.h
@@ -71,4 +71,3 @@ void rigid_deform_end(int cancel);
/* ED_mesh_deform_bind_callback(...) defined in ED_armature.h */
#endif
-
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index d24848b4b76..ffe64cc24b0 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -46,6 +46,7 @@
#include "BKE_armature.h"
#include "BKE_context.h"
#include "BKE_deform.h"
+#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_layer.h"
@@ -91,7 +92,7 @@ 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;
@@ -178,72 +179,75 @@ static bool pose_has_protected_selected(Object *ob, short warn)
/* For the object with pose/action: update paths for those that have got them
* This should selectively update paths that exist...
*
- * To be called from various tools that do incremental updates
+ * To be called from various tools that do incremental updates
*/
void ED_pose_recalculate_paths(bContext *C, Scene *scene, Object *ob)
{
struct Main *bmain = CTX_data_main(C);
Depsgraph *depsgraph = CTX_data_depsgraph(C);
ListBase targets = {NULL, NULL};
-
+
/* 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 */
animviz_calc_motionpaths(depsgraph, bmain, scene, &targets);
BLI_freelistN(&targets);
+
+ /* tag armature object for copy on write - so paths will draw/redraw */
+ DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
}
/* 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));
-
+
if (ELEM(NULL, ob, ob->pose))
return OPERATOR_CANCELLED;
-
+
/* 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_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, 10 * UI_UNIT_X, 10 * UI_UNIT_Y);
}
-/* For the object with pose/action: create path curves for selected bones
+/* For the object with pose/action: create path curves for selected bones
* This recalculates the WHOLE path within the pchan->pathsf and pchan->pathef range
*/
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);
-
+
if (ELEM(NULL, ob, ob->pose))
return OPERATOR_CANCELLED;
-
+
/* 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");
-
+
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)
{
@@ -259,7 +263,7 @@ static int pose_calculate_paths_exec(bContext *C, wmOperator *op)
/* 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)
@@ -268,23 +272,23 @@ void POSE_OT_paths_calculate(wmOperatorType *ot)
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",
+ 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",
+ 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, 0,
- "Bake Location",
+
+ RNA_def_enum(ot->srna, "bake_location", rna_enum_motionpath_bake_location_items, 0,
+ "Bake Location",
"Which point on the bones is used when calculating paths");
}
@@ -296,7 +300,7 @@ static int pose_update_paths_poll(bContext *C)
Object *ob = CTX_data_active_object(C);
return (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
}
-
+
return false;
}
@@ -304,17 +308,17 @@ 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);
-
+
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);
-
+
/* notifiers for updates */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -324,11 +328,11 @@ void POSE_OT_paths_update(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -340,10 +344,10 @@ 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) {
@@ -356,7 +360,7 @@ static void ED_pose_clear_paths(Object *ob, bool only_selected)
}
}
}
-
+
/* if nothing was skipped, there should be no paths left! */
if (skipped == false)
ob->pose->avs.path_bakeflag &= ~MOTIONPATH_BAKE_HAS_PATHS;
@@ -367,18 +371,18 @@ 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");
-
+
/* 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);
-
+
/* notifiers for updates */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- return OPERATOR_FINISHED;
+
+ return OPERATOR_FINISHED;
}
/* operator callback/wrapper */
@@ -396,17 +400,17 @@ void POSE_OT_paths_clear(wmOperatorType *ot)
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",
+ 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);
}
@@ -421,13 +425,13 @@ static void pose_copy_menu(Scene *scene)
bPoseChannel *pchan, *pchanact;
short nr = 0;
int i = 0;
-
+
/* paranoia checks */
if (ELEM(NULL, ob, ob->pose)) return;
if ((ob == obedit) || (ob->mode & OB_MODE_POSE) == 0) return;
-
+
pchan = BKE_pose_channel_active(ob);
-
+
if (pchan == NULL) return;
pchanact = pchan;
arm = ob->data;
@@ -449,10 +453,10 @@ static void pose_copy_menu(Scene *scene)
else
nr = pupmenu("Copy Pose Attributes %t|Local Location %x1|Local Rotation %x2|Local Size %x3|%l|Visual Location %x9|Visual Rotation %x10|Visual Size %x11|%l|Constraints (All) %x4|%l|Transform Locks %x6|IK Limits %x7|Bone Shape %x8");
}
-
- if (nr <= 0)
+
+ if (nr <= 0)
return;
-
+
if (nr != 5) {
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
if ((arm->layer & pchan->bone->layer) &&
@@ -473,23 +477,23 @@ static void pose_copy_menu(Scene *scene)
case 4: /* All Constraints */
{
ListBase tmp_constraints = {NULL, NULL};
-
- /* copy constraints to tmpbase and apply 'local' tags before
+
+ /* copy constraints to tmpbase and apply 'local' tags before
* appending to list of constraints for this channel
*/
BKE_constraints_copy(&tmp_constraints, &pchanact->constraints, true);
if ((ob->proxy) && (pchan->bone->layer & arm->layer_protected)) {
bConstraint *con;
-
+
/* add proxy-local tags */
for (con = tmp_constraints.first; con; con = con->next)
con->flag |= CONSTRAINT_PROXY_LOCAL;
}
BLI_movelisttolist(&pchan->constraints, &tmp_constraints);
-
+
/* update flags (need to add here, not just copy) */
pchan->constflag |= pchanact->constflag;
-
+
if (ob->pose)
BKE_pose_tag_recalc(bmain, ob->pose);
}
@@ -520,12 +524,12 @@ static void pose_copy_menu(Scene *scene)
case 10: /* Visual Rotation */
{
float delta_mat[4][4];
-
+
BKE_armature_mat_pose_to_bone(pchan, pchanact->pose_mat, delta_mat);
-
+
if (pchan->rotmode == ROT_MODE_AXISANGLE) {
float tmp_quat[4];
-
+
/* need to convert to quat first (in temp var)... */
mat4_to_quat(tmp_quat, delta_mat);
quat_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, tmp_quat);
@@ -539,7 +543,7 @@ static void pose_copy_menu(Scene *scene)
case 11: /* Visual Size */
{
float delta_mat[4][4], size[4];
-
+
BKE_armature_mat_pose_to_bone(pchan, pchanact->pose_mat, delta_mat);
mat4_to_size(size, delta_mat);
copy_v3_v3(pchan->size, size);
@@ -552,20 +556,20 @@ static void pose_copy_menu(Scene *scene)
bConstraint *con, *con_back;
int const_toggle[24] = {0}; /* XXX, initialize as 0 to quiet errors */
ListBase const_copy = {NULL, NULL};
-
+
BLI_duplicatelist(&const_copy, &(pchanact->constraints));
-
+
/* build the puplist of constraints */
for (con = pchanact->constraints.first, i = 0; con; con = con->next, i++) {
const_toggle[i] = 1;
// add_numbut(i, UI_BTYPE_TOGGLE|INT, con->name, 0, 0, &(const_toggle[i]), "");
}
-
+
// if (!do_clever_numbuts("Select Constraints", i, REDRAW)) {
// BLI_freelistN(&const_copy);
// return;
// }
-
+
/* now build a new listbase from the options selected */
for (i = 0, con = const_copy.first; con; i++) {
/* if not selected, free/remove it from the list */
@@ -577,7 +581,7 @@ static void pose_copy_menu(Scene *scene)
else
con = con->next;
}
-
+
/* Copy the temo listbase to the selected posebones */
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
if ((arm->layer & pchan->bone->layer) &&
@@ -585,8 +589,8 @@ static void pose_copy_menu(Scene *scene)
(pchan != pchanact) )
{
ListBase tmp_constraints = {NULL, NULL};
-
- /* copy constraints to tmpbase and apply 'local' tags before
+
+ /* copy constraints to tmpbase and apply 'local' tags before
* appending to list of constraints for this channel
*/
BKE_constraints_copy(&tmp_constraints, &const_copy, true);
@@ -596,22 +600,22 @@ static void pose_copy_menu(Scene *scene)
con->flag |= CONSTRAINT_PROXY_LOCAL;
}
BLI_movelisttolist(&pchan->constraints, &tmp_constraints);
-
+
/* update flags (need to add here, not just copy) */
pchan->constflag |= pchanact->constflag;
}
}
BLI_freelistN(&const_copy);
BKE_pose_update_constraint_flags(ob->pose); /* we could work out the flags but its simpler to do this */
-
+
if (ob->pose)
BKE_pose_tag_recalc(bmain, ob->pose);
}
-
+
DEG_id_tag_update(&ob->id, OB_RECALC_DATA); // and all its relations
-
+
BIF_undo_push("Copy Pose Attributes");
-
+
}
#endif
@@ -619,9 +623,10 @@ static void pose_copy_menu(Scene *scene)
static int pose_flip_names_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
const bool do_strip_numbers = RNA_boolean_get(op->ptr, "do_strip_numbers");
-
+
FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, OB_MODE_POSE, ob)
{
bArmature *arm = ob->data;
@@ -633,10 +638,10 @@ static int pose_flip_names_exec(bContext *C, wmOperator *op)
}
FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
- ED_armature_bones_flip_names(arm, &bones_names, do_strip_numbers);
+ 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, OB_RECALC_DATA);
@@ -644,7 +649,7 @@ static int pose_flip_names_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
}
FOREACH_OBJECT_IN_MODE_END;
-
+
return OPERATOR_FINISHED;
}
@@ -654,11 +659,11 @@ void POSE_OT_flip_names(wmOperatorType *ot)
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;
@@ -671,31 +676,32 @@ void POSE_OT_flip_names(wmOperatorType *ot)
static int pose_autoside_names_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
bArmature *arm;
char newname[MAXBONENAME];
short axis = RNA_enum_get(op->ptr, "axis");
-
+
/* paranoia checks */
- if (ELEM(NULL, ob, ob->pose))
+ if (ELEM(NULL, ob, ob->pose))
return OPERATOR_CANCELLED;
arm = ob->data;
-
+
/* loop through selected bones, auto-naming them */
CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
{
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(arm, pchan->name, newname);
+ ED_armature_bone_rename(bmain, arm, pchan->name, newname);
}
CTX_DATA_END;
-
+
/* since we renamed stuff... */
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -707,20 +713,20 @@ void POSE_OT_autoside_names(wmOperatorType *ot)
{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");
}
@@ -731,18 +737,18 @@ static int pose_bone_rotmode_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
int mode = RNA_enum_get(op->ptr, "type");
-
+
/* set rotation mode of selected bones */
CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
{
pchan->rotmode = mode;
}
CTX_DATA_END;
-
+
/* notifiers and updates */
DEG_id_tag_update((ID *)ob, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -752,15 +758,15 @@ void POSE_OT_rotation_mode_set(wmOperatorType *ot)
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_posebone_rotmode_items, 0, "Rotation Mode", "");
}
@@ -802,26 +808,26 @@ static int pose_armature_layers_showall_exec(bContext *C, wmOperator *op)
int maxLayers = (RNA_boolean_get(op->ptr, "all")) ? 32 : 16;
int layers[32] = {0}; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
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, DEG_TAG_COPY_ON_WRITE);
-
+
/* done */
return OPERATOR_FINISHED;
}
@@ -832,14 +838,14 @@ void ARMATURE_OT_layers_show_all(wmOperatorType *ot)
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;
-
+
/* 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)");
}
@@ -853,16 +859,16 @@ static int armature_layers_invoke(bContext *C, wmOperator *op, const wmEvent *ev
bArmature *arm = armature_layers_get_data(&ob);
PointerRNA ptr;
int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
-
+
/* 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);
}
@@ -899,15 +905,15 @@ void ARMATURE_OT_armature_layers(wmOperatorType *ot)
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");
}
@@ -917,23 +923,23 @@ 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)
{
- int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
-
+ int layers[32] = {0}; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
+
/* 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);
}
@@ -974,15 +980,15 @@ void POSE_OT_bone_layers(wmOperatorType *ot)
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");
}
@@ -993,12 +999,12 @@ void POSE_OT_bone_layers(wmOperatorType *ot)
static int armature_bone_layers_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
int layers[32] = {0}; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
-
+
/* 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)) {
@@ -1007,10 +1013,10 @@ static int armature_bone_layers_invoke(bContext *C, wmOperator *op, const wmEven
}
}
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);
}
@@ -1021,10 +1027,10 @@ static int armature_bone_layers_exec(bContext *C, wmOperator *op)
Object *ob = CTX_data_edit_object(C);
PointerRNA ptr;
int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
-
+
/* 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)
{
@@ -1033,10 +1039,10 @@ static int armature_bone_layers_exec(bContext *C, wmOperator *op)
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;
}
@@ -1046,15 +1052,15 @@ void ARMATURE_OT_bone_layers(wmOperatorType *ot)
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");
}
@@ -1103,8 +1109,8 @@ static int pose_hide_exec(bContext *C, wmOperator *op)
bool changed = bone_looper(ob_iter, arm->bonebase.first, hide_select_p, hide_pose_bone_fn) != 0;
if (changed) {
changed_multi = true;
- /* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob_iter);
+ DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
}
}
MEM_freeN(objects);
@@ -1118,19 +1124,19 @@ void POSE_OT_hide(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* props */
RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "");
}
-static int show_pose_bone_cb(Object *ob, Bone *bone, void *data)
+static int show_pose_bone_cb(Object *ob, Bone *bone, void *data)
{
const bool select = GET_INT_FROM_POINTER(data);
@@ -1166,8 +1172,8 @@ static int pose_reveal_exec(bContext *C, wmOperator *op)
bool changed = bone_looper(ob_iter, arm->bonebase.first, select_p, show_pose_bone_cb);
if (changed) {
changed_multi = true;
- /* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob_iter);
+ DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
}
}
MEM_freeN(objects);
@@ -1181,11 +1187,11 @@ void POSE_OT_reveal(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1234,11 +1240,11 @@ void POSE_OT_quaternions_flip(wmOperatorType *ot)
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 449383fb0b8..aefca13d66c 100644
--- a/source/blender/editors/armature/pose_group.c
+++ b/source/blender/editors/armature/pose_group.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -68,13 +68,13 @@ static int pose_group_add_exec(bContext *C, wmOperator *UNUSED(op))
/* 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);
-
+
/* notifiers for updates */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -84,11 +84,11 @@ void POSE_OT_group_add(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -97,18 +97,18 @@ void POSE_OT_group_add(wmOperatorType *ot)
static int pose_group_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
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;
-
+
/* 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, DEG_TAG_COPY_ON_WRITE);
-
+
return OPERATOR_FINISHED;
}
@@ -118,11 +118,11 @@ void POSE_OT_group_remove(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -135,14 +135,14 @@ static int pose_groups_menu_invoke(bContext *C, wmOperator *op, const wmEvent *U
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))
+ if (ELEM(NULL, ob, ob->pose))
return OPERATOR_CANCELLED;
pose = ob->pose;
@@ -156,28 +156,28 @@ static int pose_groups_menu_invoke(bContext *C, wmOperator *op, const wmEvent *U
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
+
+ /* 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 {
@@ -199,14 +199,14 @@ static int pose_group_assign_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
pose = ob->pose;
-
- /* set the active group number to the one from operator props
+
+ /* 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)
{
@@ -218,7 +218,7 @@ static int pose_group_assign_exec(bContext *C, wmOperator *op)
/* notifiers for updates */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
-
+
/* report done status */
if (done)
return OPERATOR_FINISHED;
@@ -232,15 +232,15 @@ void POSE_OT_group_assign(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
RNA_def_int(ot->srna, "type", 0, 0, INT_MAX, "Bone Group Index", "", 0, 10);
}
@@ -250,11 +250,11 @@ 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)
{
@@ -264,11 +264,11 @@ static int pose_group_unassign_exec(bContext *C, wmOperator *UNUSED(op))
}
}
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, DEG_TAG_COPY_ON_WRITE);
-
+
/* report done status */
if (done)
return OPERATOR_FINISHED;
@@ -282,11 +282,11 @@ void POSE_OT_group_unassign(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -442,16 +442,16 @@ void POSE_OT_group_sort(wmOperatorType *ot)
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)
+ if (pchan->agrp_index == pose->active_group)
pchan->bone->flag |= BONE_SELECTED;
}
else {
- if (pchan->agrp_index == pose->active_group)
+ if (pchan->agrp_index == pose->active_group)
pchan->bone->flag &= ~BONE_SELECTED;
}
}
@@ -462,16 +462,16 @@ static void pose_group_select(Object *ob, bool select)
static int pose_group_select_exec(bContext *C, wmOperator *UNUSED(op))
{
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;
-
+
pose_group_select(ob, 1);
-
+
/* notifiers for updates */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -481,11 +481,11 @@ void POSE_OT_group_select(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -493,16 +493,16 @@ void POSE_OT_group_select(wmOperatorType *ot)
static int pose_group_deselect_exec(bContext *C, wmOperator *UNUSED(op))
{
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;
-
+
pose_group_select(ob, 0);
-
+
/* notifiers for updates */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -512,11 +512,11 @@ void POSE_OT_group_deselect(wmOperatorType *ot)
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;
-
+
/* 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 609281a7bf2..46663d7a771 100644
--- a/source/blender/editors/armature/pose_lib.c
+++ b/source/blender/editors/armature/pose_lib.c
@@ -48,6 +48,7 @@
#include "BKE_armature.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
+#include "BKE_main.h"
#include "BKE_library.h"
#include "BKE_object.h"
@@ -81,9 +82,9 @@
static void action_set_activemarker(void *UNUSED(a), void *UNUSED(b), void *UNUSED(c)) {}
/* ************************************************************* */
-/* == POSE-LIBRARY TOOL FOR BLENDER ==
- *
- * Overview:
+/* == POSE-LIBRARY TOOL FOR BLENDER ==
+ *
+ * Overview:
* This tool allows animators to store a set of frequently used poses to dump into
* the active action to help in "budget" productions to quickly block out new actions.
* It acts as a kind of "glorified clipboard for poses", allowing for naming of poses.
@@ -100,7 +101,7 @@ 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
+/* 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)
@@ -108,17 +109,17 @@ 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
+
+ /* 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
@@ -127,7 +128,7 @@ static int poselib_get_free_index(bAction *act)
low++;
changed = true;
}
-
+
/* value replaces high if it is the highest value encountered yet */
if (marker->frame > high) {
high = marker->frame;
@@ -135,19 +136,19 @@ static int poselib_get_free_index(bAction *act)
}
}
} 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 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)
+ if (low < high)
return (low + 1);
- else
+ 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
@@ -159,14 +160,14 @@ static TimeMarker *poselib_get_active_pose(bAction *act)
static Object *get_poselib_object(bContext *C)
{
ScrArea *sa;
-
+
/* sanity check */
if (C == NULL)
return NULL;
-
+
sa = CTX_wm_area(C);
-
- if (sa && (sa->spacetype == SPACE_BUTS))
+
+ if (sa && (sa->spacetype == SPACE_BUTS))
return ED_object_context(C);
else
return BKE_object_pose_armature_get(CTX_data_active_object(C));
@@ -191,29 +192,29 @@ static int has_poselib_pose_data_for_editing_poll(bContext *C)
/* ----------------------------------- */
/* Initialize a new poselib (whether it is needed or not) */
-static bAction *poselib_init_new(Object *ob)
+static bAction *poselib_init_new(Main *bmain, Object *ob)
{
/* 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);
-
- ob->poselib = BKE_action_add(G.main, "PoseLib");
+
+ ob->poselib = BKE_action_add(bmain, "PoseLib");
ob->poselib->idroot = ID_OB;
-
+
return ob->poselib;
}
/* Initialize a new poselib (checks if that needs to happen) */
-static bAction *poselib_validate(Object *ob)
+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(ob);
+ return poselib_init_new(bmain, ob);
else
return ob->poselib;
}
@@ -223,18 +224,19 @@ static bAction *poselib_validate(Object *ob)
static int poselib_new_exec(bContext *C, wmOperator *UNUSED(op))
{
+ Main *bmain = CTX_data_main(C);
Object *ob = get_poselib_object(C);
-
+
/* sanity checks */
if (ob == NULL)
return OPERATOR_CANCELLED;
-
+
/* new method here deals with the rest... */
- poselib_init_new(ob);
-
+ poselib_init_new(bmain, ob);
+
/* notifier here might evolve? */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -244,11 +246,11 @@ void POSELIB_OT_new(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -258,18 +260,18 @@ void POSELIB_OT_new(wmOperatorType *ot)
static int poselib_unlink_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = get_poselib_object(C);
-
+
/* 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;
-
+
/* notifier here might evolve? */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -279,11 +281,11 @@ void POSELIB_OT_unlink(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -291,7 +293,7 @@ void POSELIB_OT_unlink(wmOperatorType *ot)
/* ************************************************************* */
/* Pose Editing Operators */
-/* This tool automagically generates/validates poselib data so that it corresponds to the data
+/* This tool automagically generates/validates poselib data so that it corresponds to the data
* in the action. This is for use in making existing actions usable as poselibs.
*/
static int poselib_sanitize_exec(bContext *C, wmOperator *op)
@@ -301,13 +303,13 @@ static int poselib_sanitize_exec(bContext *C, wmOperator *op)
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, NULL);
@@ -323,39 +325,39 @@ static int poselib_sanitize_exec(bContext *C, wmOperator *op)
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
+
+ /* 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;
}
@@ -365,11 +367,11 @@ void POSELIB_OT_action_sanitize(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -400,14 +402,14 @@ static void poselib_add_menu_invoke__replacemenu(bContext *C, uiLayout *layout,
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;
@@ -427,30 +429,30 @@ static int poselib_add_menu_invoke(bContext *C, wmOperator *op, const wmEvent *U
bPose *pose = (ob) ? ob->pose : NULL;
uiPopupMenu *pup;
uiLayout *layout;
-
+
/* sanity check */
- if (ELEM(NULL, ob, pose))
+ 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;
}
@@ -458,21 +460,22 @@ static int poselib_add_menu_invoke(bContext *C, wmOperator *op, const wmEvent *U
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(ob);
+ 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))
+ 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
@@ -485,23 +488,24 @@ static int poselib_add_exec(bContext *C, wmOperator *op)
}
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 */
ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_WHOLE_CHARACTER_SELECTED_ID); /* this includes custom props :)*/
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, DEG_TAG_COPY_ON_WRITE);
+
/* done */
return OPERATOR_FINISHED;
}
@@ -512,15 +516,15 @@ void POSELIB_OT_pose_add(wmOperatorType *ot)
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");
@@ -541,7 +545,7 @@ static const EnumPropertyItem *poselib_stored_pose_itemf(bContext *C, PointerRNA
if (C == NULL) {
return DummyRNA_NULL_items;
}
-
+
/* check that the action exists */
if (act) {
/* add each marker to the list */
@@ -588,12 +592,12 @@ static int poselib_remove_exec(bContext *C, wmOperator *op)
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 */
@@ -604,18 +608,19 @@ static int poselib_remove_exec(bContext *C, wmOperator *op)
}
}
}
-
+
/* 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
+
+ /* 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, DEG_TAG_COPY_ON_WRITE);
+
/* done */
return OPERATOR_FINISHED;
}
@@ -623,20 +628,20 @@ static int poselib_remove_exec(bContext *C, wmOperator *op)
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);
@@ -649,13 +654,13 @@ static int poselib_rename_invoke(bContext *C, wmOperator *op, const wmEvent *eve
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) {
@@ -667,7 +672,7 @@ static int poselib_rename_invoke(bContext *C, wmOperator *op, const wmEvent *eve
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);
}
@@ -678,32 +683,32 @@ static int poselib_rename_exec(bContext *C, wmOperator *op)
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
+
+ /* 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;
}
@@ -711,20 +716,20 @@ static int poselib_rename_exec(bContext *C, wmOperator *op)
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");
@@ -823,10 +828,10 @@ void POSELIB_OT_pose_move(wmOperatorType *ot)
typedef struct tPoseLib_PreviewData {
ListBase backups; /* tPoseLib_Backup structs for restoring poses */
ListBase searchp; /* LinkData structs storing list of poses which match the current search-string */
-
+
Scene *scene; /* active scene */
ScrArea *sa; /* active area */
-
+
PointerRNA rna_ptr; /* RNA-Pointer to Object 'ob' */
Object *ob; /* object to work on */
bArmature *arm; /* object's armature data */
@@ -843,7 +848,7 @@ typedef struct tPoseLib_PreviewData {
short search_cursor; /* position of cursor in searchstr (cursor occurs before the item at the nominated index) */
char searchstr[64]; /* (Part of) Name to search for to filter poses that get shown */
char searchold[64]; /* Previously set searchstr (from last loop run), so that we can detected when to rebuild searchp */
-
+
char headerstr[UI_MAX_DRAW_STR]; /* Info-text to print in header */
} tPoseLib_PreviewData;
@@ -853,7 +858,7 @@ enum {
PL_PREVIEW_RUNNING,
PL_PREVIEW_CONFIRM,
PL_PREVIEW_CANCEL,
- PL_PREVIEW_RUNONCE
+ PL_PREVIEW_RUNONCE
};
/* defines for tPoseLib_PreviewData->redraw values */
@@ -875,9 +880,9 @@ enum {
/* simple struct for storing backup info */
typedef struct tPoseLib_Backup {
struct tPoseLib_Backup *next, *prev;
-
+
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) */
} tPoseLib_Backup;
@@ -905,22 +910,22 @@ static void poselib_backup_posecopy(tPoseLib_PreviewData *pld)
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++;
}
@@ -931,7 +936,7 @@ static void poselib_backup_posecopy(tPoseLib_PreviewData *pld)
static void poselib_backup_restore(tPoseLib_PreviewData *pld)
{
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));
@@ -957,7 +962,7 @@ static void poselib_backup_free_data(tPoseLib_PreviewData *pld)
IDP_FreeProperty(plb->oldprops);
MEM_freeN(plb->oldprops);
}
-
+
/* free backup element now */
BLI_freelinkN(&pld->backups, plb);
}
@@ -978,19 +983,19 @@ static void poselib_apply_pose(tPoseLib_PreviewData *pld)
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;
@@ -1002,10 +1007,10 @@ static void poselib_apply_pose(tPoseLib_PreviewData *pld)
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 */
@@ -1021,7 +1026,7 @@ static void poselib_apply_pose(tPoseLib_PreviewData *pld)
}
}
- if (ok)
+ if (ok)
animsys_evaluate_action_group(ptr, act, agrp, NULL, (float)frame);
}
}
@@ -1035,7 +1040,7 @@ static void poselib_keytag_pose(bContext *C, Scene *scene, tPoseLib_PreviewData
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);
@@ -1045,13 +1050,13 @@ static void poselib_keytag_pose(bContext *C, Scene *scene, tPoseLib_PreviewData
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);
-
+ ANIM_relative_keyingset_add_source(&dsources, &pld->ob->id, &RNA_PoseBone, pchan);
+
/* clear any unkeyed tags */
if (pchan->bone)
pchan->bone->flag &= ~BONE_UNKEYED;
@@ -1064,14 +1069,14 @@ static void poselib_keytag_pose(bContext *C, Scene *scene, tPoseLib_PreviewData
}
}
}
-
+
/* 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);
}
@@ -1080,7 +1085,7 @@ static void poselib_keytag_pose(bContext *C, Scene *scene, tPoseLib_PreviewData
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 */
@@ -1088,7 +1093,7 @@ static void poselib_preview_apply(bContext *C, wmOperator *op)
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));
@@ -1096,8 +1101,8 @@ static void poselib_preview_apply(bContext *C, wmOperator *op)
}
else
RNA_int_set(op->ptr, "pose_index", -2); /* -2 means don't apply any pose */
-
- /* old optimize trick... this enforces to bypass the depgraph
+
+ /* 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?
@@ -1106,23 +1111,21 @@ static void poselib_preview_apply(bContext *C, wmOperator *op)
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) {
- BLI_strncpy(pld->headerstr,
- IFACE_("PoseLib Previewing Pose: [Showing Original Pose] | Use Tab to start previewing poses again"),
- sizeof(pld->headerstr));
- ED_area_headerprint(pld->sa, pld->headerstr);
+ 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] = '|';
@@ -1131,26 +1134,26 @@ static void poselib_preview_apply(bContext *C, wmOperator *op)
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\" | "
- "Use ScrollWheel or PageUp/Down to change"),
+ "Current Pose - \"%s\""),
tempstr, markern);
- ED_area_headerprint(pld->sa, pld->headerstr);
+ 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\" | "
- "Use ScrollWheel or PageUp/Down to change"),
+ IFACE_("PoseLib Previewing Pose: \"%s\""),
pld->marker->name);
- ED_area_headerprint(pld->sa, pld->headerstr);
+ 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;
@@ -1158,7 +1161,7 @@ static void poselib_preview_apply(bContext *C, wmOperator *op)
/* ---------------------------- */
-/* This helper function is called during poselib_preview_poses to find the
+/* This helper function is called during poselib_preview_poses to find the
* pose to preview next (after a change event)
*/
static void poselib_preview_get_next(tPoseLib_PreviewData *pld, int step)
@@ -1166,20 +1169,20 @@ 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?
+ /* 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
*/
@@ -1190,17 +1193,17 @@ static void poselib_preview_get_next(tPoseLib_PreviewData *pld, int step)
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)
@@ -1208,8 +1211,8 @@ static void poselib_preview_get_next(tPoseLib_PreviewData *pld, int step)
}
if (ldc == NULL)
ldc = pld->searchp.first;
-
- /* Loop through the matches in a cyclic fashion, incrementing/decrementing step as appropriate
+
+ /* 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) {
@@ -1220,19 +1223,19 @@ static void poselib_preview_get_next(tPoseLib_PreviewData *pld, int step)
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
+
+ /* 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) {
@@ -1243,7 +1246,7 @@ static void poselib_preview_get_next(tPoseLib_PreviewData *pld, int step)
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;
@@ -1260,28 +1263,28 @@ static void poselib_preview_handle_search(tPoseLib_PreviewData *pld, unsigned sh
short len = strlen(pld->searchstr);
short index = pld->search_cursor;
short i;
-
- for (i = index; i <= len; 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++)
+ 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;
@@ -1289,23 +1292,23 @@ static void poselib_preview_handle_search(tPoseLib_PreviewData *pld, unsigned sh
}
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--)
+ 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;
}
@@ -1316,18 +1319,18 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con
{
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;
+ 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) {
@@ -1336,7 +1339,7 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con
case RIGHTMOUSE:
pld->state = PL_PREVIEW_CANCEL;
break;
-
+
/* exit - confirm */
case LEFTMOUSE:
case RETKEY:
@@ -1344,30 +1347,30 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con
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,
+ /* 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 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) {
@@ -1376,7 +1379,7 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con
case RIGHTMOUSE:
pld->state = PL_PREVIEW_CANCEL;
break;
-
+
/* exit - confirm */
case LEFTMOUSE:
case RETKEY:
@@ -1384,39 +1387,39 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con
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]) {
@@ -1431,7 +1434,7 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con
pld->redraw = PL_PREVIEW_REDRAWALL;
}
break;
-
+
/* change to next pose or searching cursor control */
case LEFTARROWKEY:
if (pld->searchstr[0]) {
@@ -1446,7 +1449,7 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con
pld->redraw = PL_PREVIEW_REDRAWALL;
}
break;
-
+
/* change to first pose or start of searching string */
case HOMEKEY:
if (pld->searchstr[0]) {
@@ -1457,11 +1460,11 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con
/* 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]) {
@@ -1472,20 +1475,20 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con
/* 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,
+ /* 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:
@@ -1500,13 +1503,13 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con
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;
}
@@ -1518,19 +1521,19 @@ 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);
@@ -1538,7 +1541,7 @@ static void poselib_preview_init_data(bContext *C, wmOperator *op)
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");
@@ -1554,7 +1557,7 @@ static void poselib_preview_init_data(bContext *C, wmOperator *op)
if (pld->act->markers.first) {
/* just use first one then... */
pld->marker = pld->act->markers.first;
- if (pose_index > -2)
+ if (pose_index > -2)
BKE_report(op->reports, RPT_WARNING, "Pose lib had no active pose");
}
else {
@@ -1563,23 +1566,23 @@ static void poselib_preview_init_data(bContext *C, wmOperator *op)
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;
@@ -1595,18 +1598,19 @@ static void poselib_preview_cleanup(bContext *C, wmOperator *op)
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_headerprint(pld->sa, NULL);
-
+ 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
+
+ /* old optimize trick... this enforces to bypass the depgraph
* - note: code copied from transform_generics.c -> recalcData()
*/
if ((arm->flag & ARM_DELAYDEFORM) == 0)
@@ -1617,14 +1621,14 @@ static void poselib_preview_cleanup(bContext *C, wmOperator *op)
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, OB_RECALC_DATA);
-
+
/* updates */
if (IS_AUTOKEY_MODE(scene, NORMAL)) {
//remake_action_ipos(ob->action);
@@ -1632,14 +1636,14 @@ static void poselib_preview_cleanup(bContext *C, wmOperator *op)
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;
@@ -1650,10 +1654,10 @@ static int poselib_preview_exit(bContext *C, wmOperator *op)
{
tPoseLib_PreviewData *pld = op->customdata;
int exit_state = pld->state;
-
+
/* finish up */
poselib_preview_cleanup(C, op);
-
+
if (ELEM(exit_state, PL_PREVIEW_CANCEL, PL_PREVIEW_ERROR))
return OPERATOR_CANCELLED;
else
@@ -1671,18 +1675,18 @@ static int poselib_preview_modal(bContext *C, wmOperator *op, const wmEvent *eve
{
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);
-
+
/* 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);
-
+
return ret;
}
@@ -1690,20 +1694,20 @@ static int poselib_preview_modal(bContext *C, wmOperator *op, const wmEvent *eve
static int poselib_preview_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
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;
-
+
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);
-
+
/* add temp handler if we're running as a modal operator */
WM_event_add_modal_handler(C, op);
@@ -1714,28 +1718,28 @@ static int poselib_preview_invoke(bContext *C, wmOperator *op, const wmEvent *UN
static int poselib_preview_exec(bContext *C, wmOperator *op)
{
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;
-
+
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;
-
+
/* apply the active pose */
poselib_preview_apply(C, op);
-
+
/* now, set the status to exit */
pld->state = PL_PREVIEW_CONFIRM;
-
+
/* cleanup */
return poselib_preview_exit(C, op);
}
@@ -1746,21 +1750,21 @@ void POSELIB_OT_browse_interactive(wmOperatorType *ot)
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 */
/* 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); */
@@ -1772,7 +1776,7 @@ void POSELIB_OT_apply_pose(wmOperatorType *ot)
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;
diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c
index 55fceba4368..cafebb6ae95 100644
--- a/source/blender/editors/armature/pose_select.c
+++ b/source/blender/editors/armature/pose_select.c
@@ -103,9 +103,9 @@ void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select)
// 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 */
@@ -117,19 +117,19 @@ void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select)
pchan->bone->flag &= ~BONE_SELECTED;
arm->act_bone = NULL;
}
-
+
// TODO: select and activate corresponding vgroup?
-
- /* tag necessary depsgraph updates
+
+ /* tag necessary depsgraph updates
* (see rna_Bone_select_update() in rna_armature.c for details)
*/
if (arm->flag & ARM_HAS_VIZ_DEPS) {
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
-
+
/* send necessary notifiers */
WM_main_add_notifier(NC_GEOM | ND_DATA, ob);
-
+
/* tag armature for copy-on-write update (since act_bone is in armature not object) */
DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
}
@@ -143,7 +143,7 @@ bool ED_armature_pose_select_pick_with_buffer(
{
Object *ob = base->object;
Bone *nearBone;
-
+
if (!ob || !ob->pose) return 0;
Object *ob_act = OBACT(view_layer);
@@ -152,11 +152,11 @@ bool ED_armature_pose_select_pick_with_buffer(
/* 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
@@ -176,7 +176,7 @@ bool ED_armature_pose_select_pick_with_buffer(
uint objects_len = 0;
Object **objects = BKE_object_pose_array_get_unique(view_layer, &objects_len);
ED_pose_deselect_all_multi(objects, objects_len, SEL_DESELECT, true);
- MEM_SAFE_FREE(objects);
+ MEM_freeN(objects);
}
nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
arm->act_bone = nearBone;
@@ -205,7 +205,7 @@ bool ED_armature_pose_select_pick_with_buffer(
}
}
}
-
+
if (ob_act) {
/* in weightpaint we select the associated vertex group too */
if (ob_act->mode & OB_MODE_WEIGHT_PAINT) {
@@ -214,21 +214,21 @@ bool ED_armature_pose_select_pick_with_buffer(
DEG_id_tag_update(&ob_act->id, OB_RECALC_DATA);
}
}
- /* if there are some dependencies for visualizing armature state
- * (e.g. Mask Modifier in 'Armature' mode), force update
+ /* 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
+ /* NOTE: ob not ob_act here is intentional - it's the source of the
* bones being selected [T37247]
*/
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
-
+
/* tag armature for copy-on-write update (since act_bone is in armature not object) */
DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
}
}
-
+
return nearBone != NULL;
}
@@ -238,12 +238,12 @@ void ED_pose_deselect_all(Object *ob, int select_mode, const bool ignore_visibil
{
bArmature *arm = ob->data;
bPoseChannel *pchan;
-
+
/* we call this from outliner too */
if (ob->pose == NULL) {
return;
}
-
+
/* Determine if we're selecting or deselecting */
if (select_mode == SEL_TOGGLE) {
select_mode = SEL_SELECT;
@@ -256,7 +256,7 @@ void ED_pose_deselect_all(Object *ob, int select_mode, const bool ignore_visibil
}
}
}
-
+
/* Set the flags accordingly */
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 */
@@ -299,7 +299,22 @@ void ED_pose_deselect_all_multi(Object **objects, uint objects_len, int select_m
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *ob_iter = objects[ob_index];
+ bArmature *arm = ob_iter->data;
+
ED_pose_deselect_all(ob_iter, select_mode, ignore_visibility);
+
+ /* if there are some dependencies for visualizing armature state
+ * (e.g. Mask Modifier in 'Armature' mode), force update
+ */
+ 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_iter->id, OB_RECALC_DATA);
+ }
+
+ /* need to tag armature for cow updates, or else selection doesn't update */
+ DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
}
}
@@ -308,16 +323,16 @@ void ED_pose_deselect_all_multi(Object **objects, uint objects_len, int select_m
static void selectconnected_posebonechildren(Object *ob, Bone *bone, int extend)
{
Bone *curBone;
-
+
/* 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;
-
+
for (curBone = bone->childbase.first; curBone; curBone = curBone->next)
selectconnected_posebonechildren(ob, curBone, extend);
}
@@ -338,7 +353,7 @@ static int pose_select_connected_invoke(bContext *C, wmOperator *op, const wmEve
return OPERATOR_CANCELLED;
bArmature *arm = base->object->data;
-
+
/* Select parents */
for (curBone = bone; curBone; curBone = next) {
/* ignore bone if cannot be selected */
@@ -347,7 +362,7 @@ static int pose_select_connected_invoke(bContext *C, wmOperator *op, const wmEve
curBone->flag &= ~BONE_SELECTED;
else
curBone->flag |= BONE_SELECTED;
-
+
if (curBone->flag & BONE_CONNECTED)
next = curBone->parent;
else
@@ -356,19 +371,22 @@ static int pose_select_connected_invoke(bContext *C, wmOperator *op, const wmEve
else
next = NULL;
}
-
+
/* Select children */
for (curBone = bone->childbase.first; curBone; curBone = next)
selectconnected_posebonechildren(base->object, curBone, extend);
-
+
/* updates */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, base->object);
-
+
if (arm->flag & ARM_HAS_VIZ_DEPS) {
/* mask modifier ('armature' mode), etc. */
DEG_id_tag_update(&base->object->id, OB_RECALC_DATA);
}
+ /* need to tag armature for cow updates, or else selection doesn't update */
+ DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
+
return OPERATOR_FINISHED;
}
@@ -383,15 +401,15 @@ void POSE_OT_select_linked(wmOperatorType *ot)
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");
}
@@ -401,7 +419,7 @@ void POSE_OT_select_linked(wmOperatorType *ot)
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;
@@ -410,7 +428,7 @@ static int pose_de_select_all_exec(bContext *C, wmOperator *op)
}
Object *ob_prev = NULL;
-
+
/* Set the flags */
CTX_DATA_BEGIN_WITH_ID(C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob)
{
@@ -440,14 +458,14 @@ void POSE_OT_select_all(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
WM_operator_properties_select_all(ot);
}
@@ -528,10 +546,10 @@ static int pose_select_constraint_target_exec(bContext *C, wmOperator *UNUSED(op
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) {
if ((ct->tar == ob) && (ct->subtarget[0])) {
bPoseChannel *pchanc = BKE_pose_channel_find_name(ob->pose, ct->subtarget);
@@ -546,12 +564,14 @@ static int pose_select_constraint_target_exec(bContext *C, wmOperator *UNUSED(op
/* mask modifier ('armature' mode), etc. */
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
+ /* tag armature for copy on write, since selection status is armature data */
+ DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
ob_prev = ob;
}
}
}
}
-
+
if (cti->flush_constraint_targets)
cti->flush_constraint_targets(con, &targets, 1);
}
@@ -559,10 +579,10 @@ static int pose_select_constraint_target_exec(bContext *C, wmOperator *UNUSED(op
}
}
CTX_DATA_END;
-
+
if (!found)
return OPERATOR_CANCELLED;
-
+
return OPERATOR_FINISHED;
}
@@ -572,11 +592,11 @@ void POSE_OT_select_constraint_target(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -591,7 +611,7 @@ static int pose_select_hierarchy_exec(bContext *C, wmOperator *op)
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;
@@ -648,10 +668,10 @@ static int pose_select_hierarchy_exec(bContext *C, wmOperator *op)
if (changed == false) {
return OPERATOR_CANCELLED;
}
-
+
/* updates */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
-
+
if (arm->flag & ARM_HAS_VIZ_DEPS) {
/* mask modifier ('armature' mode), etc. */
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
@@ -670,19 +690,19 @@ void POSE_OT_select_hierarchy(wmOperatorType *ot)
{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");
@@ -704,22 +724,22 @@ static bool pose_select_same_group(bContext *C, Object *ob, bool extend)
char *group_flags;
int numGroups = 0;
bool changed = false, tagged = false;
-
+
/* sanity checks */
if (ELEM(NULL, ob, pose, arm))
return 0;
-
+
/* count the number of groups */
numGroups = BLI_listbase_count(&pose->agroups);
if (numGroups == 0)
return 0;
-
- /* alloc a small array to keep track of the groups to use
+
+ /* 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 (numGroups + 1), since (index = 0) is used for no-group
*/
group_flags = MEM_callocN(numGroups + 1, "pose_select_same_group");
-
+
CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
{
/* keep track of group as group to use later? */
@@ -727,13 +747,13 @@ static bool pose_select_same_group(bContext *C, Object *ob, bool extend)
group_flags[pchan->agrp_index] = 1;
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) {
/* only if group matches (and is not selected or current bone) */
@@ -749,10 +769,10 @@ static bool pose_select_same_group(bContext *C, Object *ob, bool extend)
}
CTX_DATA_END;
}
-
+
/* free temp info */
MEM_freeN(group_flags);
-
+
return changed;
}
@@ -762,25 +782,25 @@ static bool pose_select_same_layer(bContext *C, Object *ob, bool extend)
bArmature *arm = (ob) ? ob->data : NULL;
bool changed = false;
int layers = 0;
-
+
if (ELEM(NULL, ob, pose, arm))
return 0;
-
+
/* figure out what bones are selected */
CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
{
/* 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;
- if (layers == 0)
+ if (layers == 0)
return 0;
-
+
/* select bones that are on same layers as layers flag */
CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
{
@@ -791,7 +811,7 @@ static bool pose_select_same_layer(bContext *C, Object *ob, bool extend)
}
}
CTX_DATA_END;
-
+
return changed;
}
@@ -799,11 +819,11 @@ static bool pose_select_same_keyingset(bContext *C, ReportList *reports, Object
{
KeyingSet *ks = ANIM_scene_get_active_keyingset(CTX_data_scene(C));
KS_Path *ksp;
-
+
bArmature *arm = (ob) ? ob->data : NULL;
bPose *pose = (ob) ? ob->pose : NULL;
bool changed = false;
-
+
/* sanity checks: validate Keying Set and object */
if (ks == NULL) {
BKE_report(reports, RPT_ERROR, "No active Keying Set to use");
@@ -812,7 +832,7 @@ static bool pose_select_same_keyingset(bContext *C, ReportList *reports, Object
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,
+ 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");
}
@@ -822,10 +842,10 @@ static bool pose_select_same_keyingset(bContext *C, ReportList *reports, Object
}
return false;
}
-
+
if (ELEM(NULL, ob, pose, arm))
return false;
-
+
/* if not extending selection, deselect all selected first */
if (extend == false) {
CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
@@ -835,8 +855,8 @@ static bool pose_select_same_keyingset(bContext *C, ReportList *reports, Object
}
CTX_DATA_END;
}
-
- /* iterate over elements in the Keying Set, setting selection depending on whether
+
+ /* 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) {
@@ -844,10 +864,10 @@ static bool pose_select_same_keyingset(bContext *C, ReportList *reports, Object
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)) {
@@ -855,14 +875,14 @@ static bool pose_select_same_keyingset(bContext *C, ReportList *reports, Object
changed = true;
}
}
-
+
/* free temp memory */
MEM_freeN(boneName);
}
}
}
}
-
+
return changed;
}
@@ -873,38 +893,41 @@ static int pose_select_grouped_exec(bContext *C, wmOperator *op)
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, ob, extend);
break;
-
+
case POSE_SEL_SAME_GROUP: /* group */
changed = pose_select_same_group(C, ob, extend);
break;
-
+
case POSE_SEL_SAME_KEYINGSET: /* Keying Set */
changed = pose_select_same_keyingset(C, op->reports, ob, extend);
break;
-
+
default:
printf("pose_select_grouped() - Unknown selection type %u\n", type);
break;
}
-
+
/* notifiers for updates */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
+
if (arm->flag & ARM_HAS_VIZ_DEPS) {
/* mask modifier ('armature' mode), etc. */
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
-
+
+ /* need to tag armature for cow updates, or else selection doesn't update */
+ DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
+
/* report done status */
if (changed)
return OPERATOR_FINISHED;
@@ -925,15 +948,15 @@ void POSE_OT_select_grouped(wmOperatorType *ot)
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", "");
@@ -999,6 +1022,9 @@ static int pose_select_mirror_exec(bContext *C, wmOperator *op)
}
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, DEG_TAG_COPY_ON_WRITE);
}
FOREACH_OBJECT_IN_MODE_END;
@@ -1011,11 +1037,11 @@ void POSE_OT_select_mirror(wmOperatorType *ot)
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;
@@ -1023,4 +1049,3 @@ void POSE_OT_select_mirror(wmOperatorType *ot)
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 e5331aff12b..0a07af4ab43 100644
--- a/source/blender/editors/armature/pose_slide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -63,7 +63,7 @@
#include "armature_intern.h"
/* **************************************************** */
-/* == POSE 'SLIDING' TOOLS ==
+/* == POSE 'SLIDING' TOOLS ==
*
* A) Push & Relax, Breakdowner
* These tools provide the animator with various capabilities
@@ -79,7 +79,7 @@
* C) Pose Sculpting
* This is yet to be implemented, but the idea here is to use
* sculpting techniques to make it easier to pose rigs by allowing
- * rigs to be manipulated using a familiar paint-based interface.
+ * rigs to be manipulated using a familiar paint-based interface.
*/
/* **************************************************** */
/* A) Push & Relax, Breakdowner */
@@ -96,21 +96,21 @@ typedef struct tPoseSlideOp {
DLRBT_Tree keys; /* binary tree for quicker searching for keyframes (when applicable) */
int cframe; /* current frame number - global time */
-
+
int prevFrame; /* frame before current frame (blend-from) - global time */
int nextFrame; /* frame after current frame (blend-to) - global time */
-
+
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) */
-
+
short mode; /* sliding mode (ePoseSlide_Modes) */
short flag; /* unused for now, but can later get used for storing runtime settings.... */
-
+
short channels; /* which transforms/channels are affected (ePoseSlide_Channels) */
short axislock; /* axis-limits for transforms (ePoseSlide_AxisLock) */
-
+
float percentage; /* 0-1 value for determining the influence of whatever is relevant */
-
+
NumInput num; /* numeric input */
} tPoseSlideOp;
@@ -125,19 +125,19 @@ typedef enum ePoseSlide_Modes {
/* Transforms/Channels to Affect */
typedef enum ePoseSlide_Channels {
PS_TFM_ALL = 0, /* All transforms and properties */
-
+
PS_TFM_LOC, /* Loc/Rot/Scale */
PS_TFM_ROT,
PS_TFM_SIZE,
-
+
PS_TFM_BBONE_SHAPE, /* Bendy Bones */
-
+
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",
+ {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"},
@@ -171,60 +171,60 @@ static int pose_slide_init(bContext *C, wmOperator *op, short mode)
{
tPoseSlideOp *pso;
bAction *act = NULL;
-
+
/* init slide-op data */
pso = op->customdata = MEM_callocN(sizeof(tPoseSlideOp), "tPoseSlideOp");
-
+
/* get info from context */
pso->scene = CTX_data_scene(C);
pso->ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
pso->arm = (pso->ob) ? pso->ob->data : NULL;
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");
-
+
/* ensure validity of the settings from the context */
if (ELEM(NULL, pso->ob, pso->arm, pso->ob->adt, pso->ob->adt->action))
return 0;
-
+
act = pso->ob->adt->action;
-
+
/* apply NLA mapping corrections so the frame lookups work */
pso->prevFrameF = BKE_nla_tweakedit_remap(pso->ob->adt, pso->prevFrame, NLATIME_CONVERT_UNMAP);
pso->nextFrameF = BKE_nla_tweakedit_remap(pso->ob->adt, pso->nextFrame, NLATIME_CONVERT_UNMAP);
-
- /* for each Pose-Channel which gets affected, get the F-Curves for that channel
+
+ /* 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, pso->ob, act);
-
+
/* set depsgraph flags */
/* make sure the lock is set OK, unlock can be accidentally saved? */
pso->ob->pose->flag |= POSE_LOCKED;
pso->ob->pose->flag &= ~POSE_DO_UNLOCK;
-
- /* do basic initialize of RB-BST used for finding keyframes, but leave the filling of it up
+
+ /* 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;
}
@@ -233,19 +233,19 @@ static int pose_slide_init(bContext *C, wmOperator *op, short mode)
static void pose_slide_exit(wmOperator *op)
{
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);
-
+
/* free RB-BST for keyframes (if it contained data) */
BLI_dlrbTree_free(&pso->keys);
-
+
/* free data itself */
MEM_freeN(pso);
}
-
+
/* cleanup */
op->customdata = NULL;
}
@@ -265,19 +265,19 @@ static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, float *val)
float cframe = (float)pso->cframe;
float sVal, eVal;
float w1, w2;
-
+
/* get keyframe values for endpoint poses to blend with */
/* previous/start */
sVal = evaluate_fcurve(fcu, pso->prevFrameF);
/* next/end */
eVal = evaluate_fcurve(fcu, pso->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 */
@@ -285,20 +285,20 @@ static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, float *val)
w2 = 1.0f - w1; /* this must come first */
}
else {
- /* - these weights are derived from the relative distance of these
+ /* - 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;
-
+ 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
@@ -311,7 +311,7 @@ static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, float *val)
* - perform this weighting a number of times given by the percentage...
*/
int iters = (int)ceil(10.0f * pso->percentage); /* TODO: maybe a sensitivity ctrl on top of this is needed */
-
+
while (iters-- > 0) {
(*val) = (-((sVal * w2) + (eVal * w1)) + ((*val) * 6.0f) ) / 5.0f;
}
@@ -324,7 +324,7 @@ static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, float *val)
* - perform this weighting a number of times given by the percentage...
*/
int iters = (int)ceil(10.0f * pso->percentage); /* TODO: maybe a sensitivity ctrl on top of this is needed */
-
+
while (iters-- > 0) {
(*val) = ( ((sVal * w2) + (eVal * w1)) + ((*val) * 5.0f) ) / 6.0f;
}
@@ -345,19 +345,19 @@ static void pose_slide_apply_vec3(tPoseSlideOp *pso, tPChanFCurveLink *pfl, floa
{
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)) ||
@@ -367,7 +367,7 @@ static void pose_slide_apply_vec3(tPoseSlideOp *pso, tPChanFCurveLink *pfl, floa
pose_slide_apply_val(pso, fcu, &vec[fcu->array_index]);
}
}
-
+
/* free the temp path we got */
MEM_freeN(path);
}
@@ -378,11 +378,11 @@ static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl, con
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,
+
+ /* - 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
@@ -390,23 +390,23 @@ static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl, con
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?
+
+ /* 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... */
@@ -424,7 +424,7 @@ static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl, con
RNA_property_int_set(&ptr, prop, (int)tval);
break;
}
-
+
/* values which can only take discrete values */
case PROP_BOOLEAN:
{
@@ -440,7 +440,7 @@ static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl, con
*/
break;
}
-
+
default:
/* cannot handle */
//printf("Cannot Pose Slide non-numerical property\n");
@@ -459,17 +459,17 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
LinkData *ld = NULL;
char *path = NULL;
float cframe;
-
+
/* 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 */
@@ -486,22 +486,22 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
break;
}
}
-
+
/* only if all channels exist, proceed */
if (fcu_w && fcu_x && fcu_y && fcu_z) {
float quat_prev[4], quat_next[4];
-
+
/* get 2 quats */
quat_prev[0] = evaluate_fcurve(fcu_w, pso->prevFrameF);
quat_prev[1] = evaluate_fcurve(fcu_x, pso->prevFrameF);
quat_prev[2] = evaluate_fcurve(fcu_y, pso->prevFrameF);
quat_prev[3] = evaluate_fcurve(fcu_z, pso->prevFrameF);
-
+
quat_next[0] = evaluate_fcurve(fcu_w, pso->nextFrameF);
quat_next[1] = evaluate_fcurve(fcu_x, pso->nextFrameF);
quat_next[2] = evaluate_fcurve(fcu_y, pso->nextFrameF);
quat_next[3] = evaluate_fcurve(fcu_z, pso->nextFrameF);
-
+
/* perform blending */
if (pso->mode == POSESLIDE_BREAKDOWN) {
/* just perform the interpol between quat_prev and quat_next using pso->percentage as a guide */
@@ -509,35 +509,35 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
}
else if (pso->mode == POSESLIDE_PUSH) {
float quat_diff[4], quat_orig[4];
-
+
/* calculate the delta transform from the previous to the current */
/* TODO: investigate ways to favour one transform more? */
sub_qt_qtqt(quat_diff, pchan->quat, quat_prev);
-
+
/* make a copy of the original rotation */
copy_qt_qt(quat_orig, pchan->quat);
-
+
/* increase the original by the delta transform, by an amount determined by percentage */
add_qt_qtqt(pchan->quat, quat_orig, quat_diff, pso->percentage);
}
else {
float quat_interp[4], quat_orig[4];
int iters = (int)ceil(10.0f * pso->percentage); /* TODO: maybe a sensitivity ctrl on top of this is needed */
-
+
/* 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));
-
+
/* make a copy of the original rotation */
copy_qt_qt(quat_orig, pchan->quat);
-
+
/* tricky interpolations - blending between original and new */
interp_qt_qtqt(pchan->quat, quat_orig, quat_interp, 1.0f / 6.0f);
}
}
}
-
+
/* free the path now */
MEM_freeN(path);
}
@@ -546,37 +546,37 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
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++;
-
+
/* apply NLA mapping corrections so the frame lookups work */
pso->prevFrameF = BKE_nla_tweakedit_remap(pso->ob->adt, pso->prevFrame, NLATIME_CONVERT_UNMAP);
pso->nextFrameF = BKE_nla_tweakedit_remap(pso->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
+ /* 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) {
@@ -591,12 +591,12 @@ static void pose_slide_apply(bContext *C, tPoseSlideOp *pso)
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_");
+ 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)
@@ -604,7 +604,7 @@ static void pose_slide_apply(bContext *C, tPoseSlideOp *pso)
pose_slide_apply_props(pso, pfl, "[\""); /* dummy " for texteditor bugs */
}
}
-
+
/* depsgraph updates + redraws */
pose_slide_refresh(C, pso);
}
@@ -633,7 +633,7 @@ static void pose_slide_draw_status(tPoseSlideOp *pso)
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");
@@ -644,13 +644,13 @@ static void pose_slide_draw_status(tPoseSlideOp *pso)
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));
@@ -661,7 +661,7 @@ static void pose_slide_draw_status(tPoseSlideOp *pso)
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));
@@ -671,7 +671,7 @@ static void pose_slide_draw_status(tPoseSlideOp *pso)
}
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);
@@ -692,20 +692,20 @@ static void pose_slide_draw_status(tPoseSlideOp *pso)
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_headerprint(pso->sa, status_str);
+
+ ED_area_status_text(pso->sa, status_str);
}
/* common code for invoke() methods */
@@ -714,34 +714,34 @@ static int pose_slide_invoke_common(bContext *C, wmOperator *op, tPoseSlideOp *p
tPChanFCurveLink *pfl;
AnimData *adt = pso->ob->adt;
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(adt, fcu, &pso->keys, NULL);
}
}
-
+
/* consolidate these keyframes, and figure out the nearest ones */
BLI_dlrbTree_linkedlist_sync(&pso->keys);
-
+
/* 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);
@@ -759,7 +759,7 @@ static int pose_slide_invoke_common(bContext *C, wmOperator *op, tPoseSlideOp *p
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 */
pso->prevFrameF = BKE_nla_tweakedit_remap(pso->ob->adt, pso->prevFrame, NLATIME_CONVERT_UNMAP);
pso->nextFrameF = BKE_nla_tweakedit_remap(pso->ob->adt, pso->nextFrame, NLATIME_CONVERT_UNMAP);
@@ -769,20 +769,20 @@ static int pose_slide_invoke_common(bContext *C, wmOperator *op, tPoseSlideOp *p
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;
@@ -810,8 +810,8 @@ static void pose_slide_toggle_channels_mode(wmOperator *op, tPoseSlideOp *pso, e
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);
@@ -826,7 +826,7 @@ static bool pose_slide_toggle_axis_locks(wmOperator *op, tPoseSlideOp *pso, ePos
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 */
@@ -837,7 +837,7 @@ static bool pose_slide_toggle_axis_locks(wmOperator *op, tPoseSlideOp *pso, ePos
pso->axislock = axis;
}
RNA_enum_set(op->ptr, "axis_lock", pso->axislock);
-
+
/* Setting changed, so pose update is needed */
return true;
}
@@ -848,46 +848,46 @@ 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_headerprint(pso->sa, NULL);
+ 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:
+ case RIGHTMOUSE:
{
/* return to normal cursor and header status */
- ED_area_headerprint(pso->sa, NULL);
+ 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 */
{
@@ -895,7 +895,7 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
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;
}
@@ -905,17 +905,17 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
if ((event->val == KM_PRESS) && handleNumInput(C, &pso->num, event)) {
float value;
-
- /* Grab percentage from numeric input, and store this new value for redo
+
+ /* 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;
@@ -954,8 +954,8 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
do_pose_update = true;
break;
}
-
-
+
+
/* Axis Locks */
/* XXX: Hardcoded... */
case XKEY:
@@ -979,8 +979,8 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
break;
}
-
-
+
+
default: /* Some other unhandled key... */
break;
}
@@ -992,20 +992,20 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
}
}
-
-
+
+
/* 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;
}
@@ -1022,13 +1022,13 @@ 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);
-
+
/* insert keyframes if needed */
pose_slide_autoKeyframe(C, pso);
-
+
/* cleanup and done */
pose_slide_exit(op);
-
+
return OPERATOR_FINISHED;
}
@@ -1037,10 +1037,10 @@ static int pose_slide_exec_common(bContext *C, wmOperator *op, tPoseSlideOp *pso
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");
}
@@ -1051,7 +1051,7 @@ static void pose_slide_opdef_properties(wmOperatorType *ot)
static int pose_slide_push_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
tPoseSlideOp *pso;
-
+
/* initialize data */
if (pose_slide_init(C, op, POSESLIDE_PUSH) == 0) {
pose_slide_exit(op);
@@ -1059,10 +1059,10 @@ static int pose_slide_push_invoke(bContext *C, wmOperator *op, const wmEvent *ev
}
else
pso = op->customdata;
-
+
/* initialise percentage so that it won't pop on first mouse move */
pose_slide_mouse_update_percentage(pso, op, event);
-
+
/* do common setup work */
return pose_slide_invoke_common(C, op, pso);
}
@@ -1071,7 +1071,7 @@ static int pose_slide_push_invoke(bContext *C, wmOperator *op, const wmEvent *ev
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);
@@ -1079,7 +1079,7 @@ static int pose_slide_push_exec(bContext *C, wmOperator *op)
}
else
pso = op->customdata;
-
+
/* do common exec work */
return pose_slide_exec_common(C, op, pso);
}
@@ -1090,17 +1090,17 @@ void POSE_OT_push(wmOperatorType *ot)
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);
}
@@ -1111,7 +1111,7 @@ void POSE_OT_push(wmOperatorType *ot)
static int pose_slide_relax_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
tPoseSlideOp *pso;
-
+
/* initialize data */
if (pose_slide_init(C, op, POSESLIDE_RELAX) == 0) {
pose_slide_exit(op);
@@ -1119,10 +1119,10 @@ static int pose_slide_relax_invoke(bContext *C, wmOperator *op, const wmEvent *e
}
else
pso = op->customdata;
-
+
/* initialise percentage so that it won't pop on first mouse move */
pose_slide_mouse_update_percentage(pso, op, event);
-
+
/* do common setup work */
return pose_slide_invoke_common(C, op, pso);
}
@@ -1131,7 +1131,7 @@ static int pose_slide_relax_invoke(bContext *C, wmOperator *op, const wmEvent *e
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);
@@ -1139,7 +1139,7 @@ static int pose_slide_relax_exec(bContext *C, wmOperator *op)
}
else
pso = op->customdata;
-
+
/* do common exec work */
return pose_slide_exec_common(C, op, pso);
}
@@ -1150,17 +1150,17 @@ void POSE_OT_relax(wmOperatorType *ot)
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);
}
@@ -1171,7 +1171,7 @@ void POSE_OT_relax(wmOperatorType *ot)
static int pose_slide_breakdown_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
tPoseSlideOp *pso;
-
+
/* initialize data */
if (pose_slide_init(C, op, POSESLIDE_BREAKDOWN) == 0) {
pose_slide_exit(op);
@@ -1179,10 +1179,10 @@ static int pose_slide_breakdown_invoke(bContext *C, wmOperator *op, const wmEven
}
else
pso = op->customdata;
-
+
/* initialise percentage so that it won't pop on first mouse move */
pose_slide_mouse_update_percentage(pso, op, event);
-
+
/* do common setup work */
return pose_slide_invoke_common(C, op, pso);
}
@@ -1191,7 +1191,7 @@ static int pose_slide_breakdown_invoke(bContext *C, wmOperator *op, const wmEven
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);
@@ -1199,7 +1199,7 @@ static int pose_slide_breakdown_exec(bContext *C, wmOperator *op)
}
else
pso = op->customdata;
-
+
/* do common exec work */
return pose_slide_exec_common(C, op, pso);
}
@@ -1210,17 +1210,17 @@ void POSE_OT_breakdown(wmOperatorType *ot)
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);
}
@@ -1240,7 +1240,7 @@ typedef enum ePosePropagate_Termination {
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 */
@@ -1251,14 +1251,14 @@ typedef enum ePosePropagate_Termination {
typedef union tPosePropagate_ModeData {
/* smart holds + before frame: frame number to stop on */
float end_frame;
-
+
/* selected markers: listbase for CfraElem's marking these frames */
ListBase sel_markers;
} tPosePropagate_ModeData;
/* --------------------------------- */
-/* get frame on which the "hold" for the bone ends
+/* get frame on which the "hold" for the bone ends
* XXX: this may not really work that well if a bone moves on some channels and not others
* if this happens to be a major issue, scrap this, and just make this happen
* independently per F-Curve
@@ -1267,47 +1267,47 @@ static float pose_propagate_get_boneHoldEndFrame(Object *ob, tPChanFCurveLink *p
{
DLRBT_Tree keys, blocks;
ActKeyBlock *ab;
-
+
AnimData *adt = ob->adt;
LinkData *ld;
float endFrame = startFrame;
-
+
/* set up optimized data-structures for searching for relevant keyframes + holds */
BLI_dlrbTree_init(&keys);
BLI_dlrbTree_init(&blocks);
-
+
for (ld = pfl->fcurves.first; ld; ld = ld->next) {
FCurve *fcu = (FCurve *)ld->data;
fcurve_to_keylist(adt, fcu, &keys, &blocks);
}
-
+
BLI_dlrbTree_linkedlist_sync(&keys);
BLI_dlrbTree_linkedlist_sync(&blocks);
-
- /* find the long keyframe (i.e. hold), and hence obtain the endFrame value
+
+ /* 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
*/
ab = (ActKeyBlock *)BLI_dlrbTree_search_exact(&blocks, compare_ab_cfraPtr, &startFrame);
-
+
if (actkeyblock_is_valid(ab, &keys) == 0) {
/* 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,
+ * 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 (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &startFrame) == NULL) {
/* we've got case 1, so try the one after */
ab = (ActKeyBlock *)BLI_dlrbTree_search_next(&blocks, compare_ab_cfraPtr, &startFrame);
-
+
if (actkeyblock_is_valid(ab, &keys) == 0) {
/* try the block before this frame then as last resort */
ab = (ActKeyBlock *)BLI_dlrbTree_search_prev(&blocks, compare_ab_cfraPtr, &startFrame);
-
+
/* whatever happens, stop searching now... */
if (actkeyblock_is_valid(ab, &keys) == 0) {
- /* restrict range to just the frame itself
+ /* restrict range to just the frame itself
* i.e. everything is in motion, so no holds to safely overwrite
*/
ab = NULL;
@@ -1319,13 +1319,13 @@ static float pose_propagate_get_boneHoldEndFrame(Object *ob, tPChanFCurveLink *p
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) {
ActKeyBlock *abn = (ActKeyBlock *)ab->next;
-
+
/* must be valid */
if (actkeyblock_is_valid(abn, &keys) == 0)
break;
@@ -1335,24 +1335,24 @@ static float pose_propagate_get_boneHoldEndFrame(Object *ob, tPChanFCurveLink *p
/* should have the same number of curves */
if (ab->totcurve != abn->totcurve)
break;
- /* should have the same value
+ /* should have the same value
* XXX: this may be a bit fuzzy on larger data sets, so be careful
*/
if (ab->val != abn->val)
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->end;
}
-
+
/* free temp memory */
BLI_dlrbTree_free(&keys);
BLI_dlrbTree_free(&blocks);
-
+
/* return the end frame we've found */
return endFrame;
}
@@ -1363,10 +1363,10 @@ 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)) {
@@ -1411,7 +1411,7 @@ static bool pose_propagate_get_refVal(Object *ob, FCurve *fcu, float *value)
}
}
}
-
+
return found;
}
@@ -1420,25 +1420,25 @@ 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
+ * 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
+
+ /* 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
@@ -1447,7 +1447,7 @@ static void pose_propagate_fcurve(wmOperator *op, Object *ob, FCurve *fcu,
*/
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
@@ -1457,13 +1457,13 @@ static void pose_propagate_fcurve(wmOperator *op, Object *ob, FCurve *fcu,
/* 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;
+ break;
}
else if (mode == POSE_PROPAGATE_NEXT_KEY) {
/* stop after the first keyframe has been processed */
@@ -1478,13 +1478,13 @@ static void pose_propagate_fcurve(wmOperator *op, Object *ob, FCurve *fcu,
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;
@@ -1494,11 +1494,11 @@ static void pose_propagate_fcurve(wmOperator *op, Object *ob, FCurve *fcu,
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;
@@ -1512,13 +1512,13 @@ static int pose_propagate_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
bAction *act = (ob && ob->adt) ? ob->adt->action : NULL;
-
+
ListBase pflinks = {NULL, NULL};
tPChanFCurveLink *pfl;
-
+
tPosePropagate_ModeData modeData;
const int mode = RNA_enum_get(op->ptr, "mode");
-
+
/* sanity checks */
if (ob == NULL) {
BKE_report(op->reports, RPT_ERROR, "No object to propagate poses for");
@@ -1528,10 +1528,10 @@ static int pose_propagate_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "No keyframed poses to propagate to");
return OPERATOR_CANCELLED;
}
-
+
/* isolate F-Curves related to the selected bones */
poseAnim_mapping_get(C, &pflinks, ob, act);
-
+
/* mode-specific data preprocessing (requiring no access to curves) */
if (mode == POSE_PROPAGATE_SELECTED_MARKERS) {
/* get a list of selected markers */
@@ -1541,11 +1541,11 @@ static int pose_propagate_exec(bContext *C, wmOperator *op)
/* 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
@@ -1553,21 +1553,21 @@ static int pose_propagate_exec(bContext *C, wmOperator *op)
*/
modeData.end_frame = pose_propagate_get_boneHoldEndFrame(ob, 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, 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 */
poseAnim_mapping_refresh(C, scene, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -1591,19 +1591,19 @@ void POSE_OT_propagate(wmOperatorType *ot)
{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");
diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c
index deed786944b..22c710dcda5 100644
--- a/source/blender/editors/armature/pose_transform.c
+++ b/source/blender/editors/armature/pose_transform.c
@@ -53,6 +53,7 @@
#include "BKE_report.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -75,17 +76,18 @@
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 = G.main->object.first; ob; ob = ob->id.next) {
+ for (ob = bmain->object.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),
+ /* 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);
}
@@ -95,9 +97,11 @@ static void applyarmature_fix_boneparents(const bContext *C, Scene *scene, Objec
/* 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);
Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); // must be active object, not edit-object
+ const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
bArmature *arm = BKE_armature_from_object(ob);
bPose *pose;
bPoseChannel *pchan;
@@ -120,17 +124,18 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
/* 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->pose_head);
- copy_v3_v3(curbone->tail, pchan->pose_tail);
-
+ 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
@@ -138,69 +143,72 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
{
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->pose_mat);
-
+ 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) {
- curbone->curveInX += pchan->curveInX;
- curbone->curveInY += pchan->curveInY;
- curbone->curveOutX += pchan->curveOutX;
- curbone->curveOutY += pchan->curveOutY;
- curbone->roll1 += pchan->roll1;
- curbone->roll2 += pchan->roll2;
- curbone->ease1 += pchan->ease1;
- curbone->ease2 += pchan->ease2;
- curbone->scaleIn += pchan->scaleIn;
- curbone->scaleOut += pchan->scaleOut;
-
+ /* 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(arm);
+ 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, DEG_TAG_COPY_ON_WRITE);
+
return OPERATOR_FINISHED;
}
@@ -210,11 +218,11 @@ void POSE_OT_armature_apply(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -224,35 +232,38 @@ void POSE_OT_armature_apply(wmOperatorType *ot)
static int pose_visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op))
{
ViewLayer *view_layer = CTX_data_view_layer(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
- FOREACH_OBJECT_IN_MODE_BEGIN(view_layer, OB_MODE_POSE, ob_iter)
+ FOREACH_OBJECT_IN_MODE_BEGIN(view_layer, 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_iter, pchan)
+ 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
+ * 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, pchan->pose_mat, delta_mat);
-
+ 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_iter->id, OB_RECALC_DATA);
+
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
/* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob_iter);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
}
FOREACH_OBJECT_IN_MODE_END;
@@ -265,11 +276,11 @@ void POSE_OT_visual_transform_apply(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -277,7 +288,7 @@ void POSE_OT_visual_transform_apply(wmOperatorType *ot)
/* ********************************************** */
/* Copy/Paste */
-/* This function is used to indicate that a bone is selected
+/* This function is used to indicate that a bone is selected
* and needs to be included in copy buffer (used to be for inserting keys)
*/
static void set_pose_keys(Object *ob)
@@ -310,33 +321,33 @@ static bPoseChannel *pose_bone_do_paste(Object *ob, bPoseChannel *chan, const bo
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
+ /* 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 */
@@ -372,29 +383,29 @@ static bPoseChannel *pose_bone_do_paste(Object *ob, bPoseChannel *chan, const bo
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;
@@ -402,7 +413,7 @@ static bPoseChannel *pose_bone_do_paste(Object *ob, bPoseChannel *chan, const bo
}
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;
@@ -410,7 +421,7 @@ static bPoseChannel *pose_bone_do_paste(Object *ob, bPoseChannel *chan, const bo
}
else {
float eul[3];
-
+
normalize_qt(pchan->quat);
quat_to_eul(eul, pchan->quat);
eul[1] *= -1;
@@ -418,12 +429,12 @@ static bPoseChannel *pose_bone_do_paste(Object *ob, bPoseChannel *chan, const bo
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
+ /* 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);
@@ -434,7 +445,7 @@ static bPoseChannel *pose_bone_do_paste(Object *ob, bPoseChannel *chan, const bo
}
}
}
-
+
/* return whether paste went ahead */
return pchan;
}
@@ -492,11 +503,11 @@ void POSE_OT_copy(wmOperatorType *ot)
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;
-
+
/* flag */
ot->flag = OPTYPE_REGISTER;
}
@@ -510,15 +521,15 @@ static int pose_paste_exec(bContext *C, wmOperator *op)
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();
@@ -534,7 +545,7 @@ static int pose_paste_exec(bContext *C, wmOperator *op)
BKE_main_free(tmp_bmain);
return OPERATOR_CANCELLED;
}
-
+
Object *object_from = tmp_bmain->object.first;
bPose *pose_from = object_from->pose;
if (pose_from == NULL) {
@@ -542,7 +553,7 @@ static int pose_paste_exec(bContext *C, wmOperator *op)
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.
@@ -552,7 +563,7 @@ static int pose_paste_exec(bContext *C, wmOperator *op)
selOnly = false;
}
}
-
+
/* Safely merge all of the channels in the buffer pose into any
* existing pose.
*/
@@ -567,15 +578,15 @@ static int pose_paste_exec(bContext *C, wmOperator *op)
}
}
BKE_main_free(tmp_bmain);
-
+
/* Update event for pose and deformation children. */
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
-
+
/* 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);
}
-
+
/* Notifiers for updates, */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
@@ -590,14 +601,14 @@ void POSE_OT_paste(wmOperatorType *ot)
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);
@@ -617,9 +628,9 @@ static void pchan_clear_scale(bPoseChannel *pchan)
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->ease2 = 0.0f;
pchan->scaleIn = 1.0f;
pchan->scaleOut = 1.0f;
}
@@ -651,7 +662,7 @@ static void pchan_clear_rot(bPoseChannel *pchan)
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;
@@ -680,7 +691,7 @@ static void pchan_clear_rot(bPoseChannel *pchan)
/* 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);
@@ -691,22 +702,22 @@ static void pchan_clear_rot(bPoseChannel *pchan)
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);
@@ -732,11 +743,11 @@ static void pchan_clear_rot(bPoseChannel *pchan)
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;
@@ -754,7 +765,7 @@ static void pchan_clear_transforms(bPoseChannel *pchan)
/* --------------- */
/* generic exec for clear-pose operators */
-static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op,
+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);
@@ -770,6 +781,7 @@ static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op,
ViewLayer *view_layer = CTX_data_view_layer(C);
FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, 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;
@@ -787,6 +799,11 @@ static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op,
}
/* 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 */
@@ -829,7 +846,7 @@ static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op,
/* --------------- */
-static int pose_clear_scale_exec(bContext *C, wmOperator *op)
+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);
}
@@ -840,17 +857,17 @@ void POSE_OT_scale_clear(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int pose_clear_rot_exec(bContext *C, wmOperator *op)
+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);
}
@@ -861,17 +878,17 @@ void POSE_OT_rot_clear(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int pose_clear_loc_exec(bContext *C, wmOperator *op)
+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);
}
@@ -882,17 +899,17 @@ void POSE_OT_loc_clear(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int pose_clear_transforms_exec(bContext *C, wmOperator *op)
+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);
}
@@ -903,11 +920,11 @@ void POSE_OT_transforms_clear(wmOperatorType *ot)
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;
}
@@ -921,7 +938,7 @@ static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op)
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, OB_MODE_POSE, ob)
{
if ((ob->adt) && (ob->adt->action)) {
@@ -931,23 +948,23 @@ static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op)
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(scene, &workob.id, workob.adt, cframe, ADT_RECALC_ANIM);
-
+
+ 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) {
@@ -955,7 +972,7 @@ static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op)
MEM_freeN(pchan->prop);
}
}
-
+
/* was copied without constraints */
BLI_freelistN(&dummyPose->chanbase);
MEM_freeN(dummyPose);
@@ -966,13 +983,13 @@ static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op)
*/
BKE_pose_rest(ob->pose);
}
-
+
/* notifiers and updates */
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
}
FOREACH_OBJECT_IN_MODE_END;
-
+
return OPERATOR_FINISHED;
}
@@ -982,11 +999,11 @@ void POSE_OT_user_transforms_clear(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/armature/pose_utils.c b/source/blender/editors/armature/pose_utils.c
index 0dc89aa4716..e280284a9ce 100644
--- a/source/blender/editors/armature/pose_utils.c
+++ b/source/blender/editors/armature/pose_utils.c
@@ -40,6 +40,7 @@
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_idprop.h"
+#include "BKE_main.h"
#include "BKE_context.h"
@@ -59,11 +60,11 @@
/* Contents of this File:
*
* This file contains methods shared between Pose Slide and Pose Lib;
- * primarily the functions in question concern Animato <-> Pose
+ * primarily the functions in question concern Animato <-> Pose
* convenience functions, such as applying/getting pose values
* and/or inserting keyframes for these.
*/
-/* *********************************************** */
+/* *********************************************** */
/* FCurves <-> PoseChannels Links */
/* helper for poseAnim_mapping_get() -> get the relevant F-Curves per PoseChannel */
@@ -71,25 +72,25 @@ static void fcurves_to_pchan_links_get(ListBase *pfLinks, Object *ob, bAction *a
{
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->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;
@@ -99,7 +100,7 @@ static void fcurves_to_pchan_links_get(ListBase *pfLinks, Object *ob, bAction *a
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);
@@ -107,7 +108,7 @@ static void fcurves_to_pchan_links_get(ListBase *pfLinks, Object *ob, bAction *a
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;
@@ -119,18 +120,18 @@ static void fcurves_to_pchan_links_get(ListBase *pfLinks, Object *ob, bAction *a
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);
}
-}
+}
/* get sets of F-Curves providing transforms for the bones in the Pose */
void poseAnim_mapping_get(bContext *C, ListBase *pfLinks, Object *ob, bAction *act)
-{
- /* for each Pose-Channel which gets affected, get the F-Curves for that channel
+{
+ /* for each Pose-Channel which gets affected, get the F-Curves for that channel
* and set the relevant transform flags...
*/
CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
@@ -138,7 +139,7 @@ void poseAnim_mapping_get(bContext *C, ListBase *pfLinks, Object *ob, bAction *a
fcurves_to_pchan_links_get(pfLinks, ob, act, 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
*/
@@ -148,7 +149,7 @@ void poseAnim_mapping_get(bContext *C, ListBase *pfLinks, Object *ob, bAction *a
fcurves_to_pchan_links_get(pfLinks, ob, act, pchan);
}
CTX_DATA_END;
-
+
}
}
@@ -156,23 +157,23 @@ void poseAnim_mapping_get(bContext *C, ListBase *pfLinks, Object *ob, bAction *a
void poseAnim_mapping_free(ListBase *pfLinks)
{
tPChanFCurveLink *pfl, *pfln = NULL;
-
+
/* 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 list of F-Curve reference links */
BLI_freelistN(&pfl->fcurves);
-
+
/* free pchan RNA Path */
MEM_freeN(pfl->pchan_path);
-
+
/* free link itself */
BLI_freelinkN(pfLinks, pfl);
}
@@ -185,8 +186,8 @@ 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
+
+ /* 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? */
@@ -194,8 +195,8 @@ void poseAnim_mapping_refresh(bContext *C, Scene *scene, Object *ob)
DEG_id_tag_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */
else
BKE_pose_where_is(depsgraph, scene, ob);
-
- /* note, notifier might evolve */
+
+ DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE); /* otherwise animation doesn't get updated */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
}
@@ -203,11 +204,11 @@ void poseAnim_mapping_refresh(bContext *C, Scene *scene, Object *ob)
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);
@@ -215,7 +216,7 @@ void poseAnim_mapping_reset(ListBase *pfLinks)
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;
@@ -227,7 +228,7 @@ void poseAnim_mapping_reset(ListBase *pfLinks)
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);
@@ -242,26 +243,26 @@ void poseAnim_mapping_autoKeyframe(bContext *C, Scene *scene, Object *ob, ListBa
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
+ /* 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;
-
+
/* add datasource override for the PoseChannel, to be used later */
- ANIM_relative_keyingset_add_source(&dsources, &ob->id, &RNA_PoseBone, pchan);
-
+ ANIM_relative_keyingset_add_source(&dsources, &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...
@@ -275,25 +276,25 @@ void poseAnim_mapping_autoKeyframe(bContext *C, Scene *scene, Object *ob, ListBa
/* ------------------------- */
-/* find the next F-Curve for a PoseChannel with matching path...
+/* find the next F-Curve for a PoseChannel with matching path...
* - path is not just the pfl rna_path, since that path doesn't have property info yet
*/
LinkData *poseAnim_mapping_getNextFCurve(ListBase *fcuLinks, LinkData *prev, const char *path)
{
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 if paths match */
if (STREQ(path, fcu->rna_path))
return ld;
}
-
+
/* none found */
return NULL;
}
-/* *********************************************** */
+/* *********************************************** */
diff --git a/source/blender/editors/curve/curve_intern.h b/source/blender/editors/curve/curve_intern.h
index 020d34f2767..01047d4badd 100644
--- a/source/blender/editors/curve/curve_intern.h
+++ b/source/blender/editors/curve/curve_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c
index 71cccdfa33d..fbdc4219d02 100644
--- a/source/blender/editors/curve/curve_ops.c
+++ b/source/blender/editors/curve/curve_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -73,10 +73,10 @@ void ED_operatortypes_curve(void)
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);
@@ -98,20 +98,20 @@ void ED_operatortypes_curve(void)
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);
@@ -168,10 +168,10 @@ void ED_keymap_curve(wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
wmKeyMapItem *kmi;
-
+
keymap = WM_keymap_find(keyconf, "Font", 0, 0);
keymap->poll = ED_operator_editfont;
-
+
/* only set in editmode font, by space_view3d listener */
RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_style_toggle", BKEY, KM_PRESS, KM_CTRL, 0)->ptr, "style", CU_CHINFO_BOLD);
RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_style_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "style", CU_CHINFO_ITALIC);
@@ -233,7 +233,7 @@ void ED_keymap_curve(wmKeyConfig *keyconf)
keymap->poll = ED_operator_editsurfcurve;
WM_keymap_add_menu(keymap, "INFO_MT_edit_curve_add", AKEY, KM_PRESS, KM_SHIFT, 0);
-
+
WM_keymap_add_item(keymap, "CURVE_OT_handle_type_set", VKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "CURVE_OT_vertex_add", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0);
@@ -269,10 +269,14 @@ void ED_keymap_curve(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "CURVE_OT_make_segment", FKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "CURVE_OT_cyclic_toggle", CKEY, KM_PRESS, KM_ALT, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_curve_delete", XKEY, KM_PRESS, 0, 0);
+#endif
WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_curve_delete", DELKEY, KM_PRESS, 0, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "CURVE_OT_dissolve_verts", XKEY, KM_PRESS, KM_CTRL, 0);
+#endif
WM_keymap_add_item(keymap, "CURVE_OT_dissolve_verts", DELKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "CURVE_OT_tilt_clear", TKEY, KM_PRESS, KM_ALT, 0);
@@ -286,10 +290,14 @@ void ED_keymap_curve(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "CURVE_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "unselected", true);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "CURVE_OT_normals_make_consistent", NKEY, KM_PRESS, KM_CTRL, 0);
+#else
+ WM_keymap_add_item(keymap, "CURVE_OT_normals_make_consistent", NKEY, KM_PRESS, KM_SHIFT, 0);
+#endif
WM_keymap_add_item(keymap, "OBJECT_OT_vertex_parent_set", PKEY, KM_PRESS, KM_CTRL, 0);
-
+
WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_curve_specials", WKEY, KM_PRESS, 0, 0);
/* menus */
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index f97ac98107c..aa50916f5e0 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -1105,7 +1105,7 @@ static int *initialize_index_map(Object *obedit, int *r_old_totvert)
return old_to_new_map;
}
-static void remap_hooks_and_vertex_parents(Object *obedit)
+static void remap_hooks_and_vertex_parents(Main *bmain, Object *obedit)
{
Object *object;
Curve *curve = (Curve *) obedit->data;
@@ -1121,7 +1121,7 @@ static void remap_hooks_and_vertex_parents(Object *obedit)
return;
}
- for (object = G.main->object.first; object; object = object->id.next) {
+ for (object = bmain->object.first; object; object = object->id.next) {
ModifierData *md;
int index;
if ((object->parent) &&
@@ -1184,7 +1184,7 @@ static void remap_hooks_and_vertex_parents(Object *obedit)
}
/* load editNurb in object */
-void ED_curve_editnurb_load(Object *obedit)
+void ED_curve_editnurb_load(Main *bmain, Object *obedit)
{
ListBase *editnurb = object_editcurve_get(obedit);
@@ -1195,7 +1195,7 @@ void ED_curve_editnurb_load(Object *obedit)
Nurb *nu, *newnu;
ListBase newnurb = {NULL, NULL}, oldnurb = cu->nurb;
- remap_hooks_and_vertex_parents(obedit);
+ remap_hooks_and_vertex_parents(bmain, obedit);
for (nu = editnurb->first; nu; nu = nu->next) {
newnu = BKE_nurb_duplicate(nu);
@@ -1325,7 +1325,7 @@ static int separate_exec(bContext *C, wmOperator *op)
BLI_movelisttolist(&newedit->nurbs, &newnurb);
/* 4. put old object out of editmode and delete separated geometry */
- ED_curve_editnurb_load(newob);
+ ED_curve_editnurb_load(bmain, newob);
ED_curve_editnurb_free(newob);
curve_delete_segments(oldob, true);
@@ -1346,12 +1346,12 @@ void CURVE_OT_separate(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1856,7 +1856,7 @@ bool ed_editnurb_extrude_flag(EditNurb *editnurb, const short flag)
while (a--) {
select_bpoint(bp, SELECT, flag, HIDDEN);
select_bpoint(newbp, DESELECT, flag, HIDDEN);
- bp++;
+ bp++;
newbp++;
}
@@ -2336,7 +2336,7 @@ void CURVE_OT_switch_direction(wmOperatorType *ot)
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;
@@ -2356,7 +2356,7 @@ static int set_goal_weight_exec(bContext *C, wmOperator *op)
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++) {
@@ -2384,7 +2384,7 @@ void CURVE_OT_spline_weight_set(wmOperatorType *ot)
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;
@@ -2408,7 +2408,7 @@ static int set_radius_exec(bContext *C, wmOperator *op)
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++) {
@@ -2436,7 +2436,7 @@ void CURVE_OT_radius_set(wmOperatorType *ot)
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;
@@ -2588,7 +2588,7 @@ void CURVE_OT_smooth(wmOperatorType *ot)
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;
@@ -2792,7 +2792,7 @@ static int curve_smooth_radius_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *obedit = CTX_data_edit_object(C);
ListBase *editnurb = object_editcurve_get(obedit);
-
+
curve_smooth_value(editnurb, offsetof(BezTriple, radius), offsetof(BPoint, radius));
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
@@ -2807,11 +2807,11 @@ void CURVE_OT_smooth_radius(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -2896,7 +2896,7 @@ static int hide_exec(bContext *C, wmOperator *op)
}
}
- DEG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
BKE_curve_nurb_vert_active_validate(obedit->data);
@@ -2909,14 +2909,14 @@ void CURVE_OT_hide(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* props */
RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
}
@@ -2959,7 +2959,7 @@ static int reveal_exec(bContext *C, wmOperator *op)
}
}
- DEG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -2971,11 +2971,11 @@ void CURVE_OT_reveal(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -3231,7 +3231,7 @@ static void subdividenurb(Object *obedit, int number_cuts)
for (b = 0; b < nu->pntsu; b++) {
*bpn = *bp;
keyIndex_updateBP(editnurb, bp, bpn, 1);
- bpn++;
+ bpn++;
bp++;
if (b < nu->pntsu - 1) {
prevbp = bp - 1;
@@ -3259,7 +3259,7 @@ static void subdividenurb(Object *obedit, int number_cuts)
interp_v4_v4v4(tmp->vec, prevbp->vec, bp->vec, factor);
tmp += countu;
}
- bp++;
+ bp++;
prevbp++;
bpn++;
}
@@ -3335,7 +3335,7 @@ static void subdividenurb(Object *obedit, int number_cuts)
for (b = 0; b < nu->pntsu; b++) {
*bpn = *bp;
keyIndex_updateBP(editnurb, bp, bpn, 1);
- bpn++;
+ bpn++;
bp++;
if ( (b < nu->pntsu - 1) && usel[b] == nu->pntsv && usel[b + 1] == nu->pntsv) {
/*
@@ -3362,7 +3362,7 @@ static void subdividenurb(Object *obedit, int number_cuts)
}
}
}
- MEM_freeN(usel);
+ MEM_freeN(usel);
MEM_freeN(vsel);
} /* End of 'if (nu->type == CU_NURBS)' */
@@ -3371,16 +3371,29 @@ static void subdividenurb(Object *obedit, int number_cuts)
static int subdivide_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- int number_cuts = RNA_int_get(op->ptr, "number_cuts");
+ const int number_cuts = RNA_int_get(op->ptr, "number_cuts");
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
- subdividenurb(obedit, number_cuts);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &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_updateAnimPaths(obedit->data))
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+ if (!ED_curve_select_check(cu, cu->editnurb)) {
+ continue;
+ }
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
+ subdividenurb(obedit, number_cuts);
+
+ if (ED_curve_updateAnimPaths(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);
return OPERATOR_FINISHED;
}
@@ -3393,11 +3406,11 @@ void CURVE_OT_subdivide(wmOperatorType *ot)
ot->name = "Subdivide";
ot->description = "Subdivide selected segments";
ot->idname = "CURVE_OT_subdivide";
-
+
/* api callbacks */
ot->exec = subdivide_exec;
ot->poll = ED_operator_editsurfcurve;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -3555,7 +3568,7 @@ static int set_spline_type_exec(bContext *C, wmOperator *op)
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(obedit->data, nu)) {
const int pntsu_prev = nu->pntsu;
@@ -3605,12 +3618,12 @@ void CURVE_OT_spline_type_set(wmOperatorType *ot)
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;
@@ -3650,12 +3663,12 @@ void CURVE_OT_handle_type_set(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -3705,9 +3718,9 @@ 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;
@@ -3716,7 +3729,7 @@ static void switchdirection_knots(float *base, int tot)
while (fp1 != fp2 && a > 0) {
SWAP(float, *fp1, *fp2);
a--;
- fp1++;
+ fp1++;
fp2--;
}
@@ -3748,15 +3761,15 @@ static void rotate_direction_nurb(Nurb *nu)
{
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(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++) {
@@ -3773,7 +3786,7 @@ static bool is_u_selected(Nurb *nu, int u)
{
BPoint *bp;
int v;
-
+
/* what about resolu == 2? */
bp = &nu->bp[u];
for (v = 0; v < nu->pntsv - 1; v++, bp += nu->pntsu) {
@@ -3781,7 +3794,7 @@ static bool is_u_selected(Nurb *nu, int u)
return true;
}
}
-
+
return false;
}
@@ -3802,14 +3815,14 @@ static void make_selection_list_nurb(Curve *cu, ListBase *editnurb)
BPoint *bp;
float dist, headdist, taildist;
int a;
-
+
for (nu = editnurb->first; nu; nu = nu->next) {
if (ED_curve_nurb_select_check(cu, nu)) {
-
+
nus = (NurbSort *)MEM_callocN(sizeof(NurbSort), "sort");
BLI_addhead(&nbase, nus);
nus->nu = nu;
-
+
bp = nu->bp;
a = nu->pntsu;
while (a--) {
@@ -3817,8 +3830,8 @@ static void make_selection_list_nurb(Curve *cu, ListBase *editnurb)
bp++;
}
mul_v3_fl(nus->vec, 1.0f / (float)nu->pntsu);
-
-
+
+
}
}
@@ -3826,10 +3839,10 @@ static void make_selection_list_nurb(Curve *cu, ListBase *editnurb)
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;
@@ -3849,7 +3862,7 @@ static void make_selection_list_nurb(Curve *cu, ListBase *editnurb)
}
nustest = nustest->next;
}
-
+
if (headdist < taildist) {
BLI_remlink(&nbase, headdo);
BLI_addhead(&nsortbase, headdo);
@@ -3866,12 +3879,12 @@ static void merge_2_nurb(wmOperator *op, Curve *cu, ListBase *editnurb, Nurb *nu
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 */
}
@@ -3902,7 +3915,7 @@ static void merge_2_nurb(wmOperator *op, Curve *cu, ListBase *editnurb, Nurb *nu
}
}
}
-
+
/* 2nd nurbs: u = 0 selected */
if (is_u_selected(nu2, 0)) {
/* pass */
@@ -3932,19 +3945,19 @@ static void merge_2_nurb(wmOperator *op, Curve *cu, ListBase *editnurb, Nurb *nu
}
}
}
-
+
if (nu1->pntsv != nu2->pntsv) {
BKE_report(op->reports, RPT_ERROR, "Resolution does not match");
return;
}
-
+
/* 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);
}
@@ -3952,7 +3965,7 @@ static void merge_2_nurb(wmOperator *op, Curve *cu, ListBase *editnurb, Nurb *nu
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);
}
@@ -3964,12 +3977,12 @@ static void merge_2_nurb(wmOperator *op, Curve *cu, ListBase *editnurb, Nurb *nu
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];
@@ -3990,11 +4003,11 @@ static void merge_2_nurb(wmOperator *op, Curve *cu, ListBase *editnurb, Nurb *nu
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);
@@ -4007,15 +4020,15 @@ static int merge_nurb(bContext *C, wmOperator *op)
ListBase *editnurb = object_editcurve_get(obedit);
NurbSort *nus1, *nus2;
bool ok = true;
-
+
make_selection_list_nurb(cu, editnurb);
-
+
if (nsortbase.first == nsortbase.last) {
BLI_freelistN(&nsortbase);
BKE_report(op->reports, RPT_ERROR, "Too few selections to merge");
return OPERATOR_CANCELLED;
}
-
+
nus1 = nsortbase.first;
nus2 = nus1->next;
@@ -4045,7 +4058,7 @@ static int merge_nurb(bContext *C, wmOperator *op)
else {
ok = 0;
}
-
+
if (ok == 0) {
BKE_report(op->reports, RPT_ERROR, "Resolution does not match");
BLI_freelistN(&nsortbase);
@@ -4056,14 +4069,14 @@ static int merge_nurb(bContext *C, wmOperator *op)
merge_2_nurb(op, cu, editnurb, nus1->nu, nus2->nu);
nus2 = nus2->next;
}
-
+
BLI_freelistN(&nsortbase);
-
+
BKE_curve_nurb_active_set(obedit->data, NULL);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
DEG_id_tag_update(obedit->data, 0);
-
+
return OPERATOR_FINISHED;
}
@@ -4081,7 +4094,7 @@ static int make_segment_exec(bContext *C, wmOperator *op)
/* 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(cu, nu);
if (nu_select_num) {
@@ -4110,7 +4123,7 @@ static int make_segment_exec(bContext *C, wmOperator *op)
if (nu)
return merge_nurb(C, op);
-
+
/* find both nurbs and points, nu1 will be put behind nu2 */
for (nu = nubase->first; nu; nu = nu->next) {
if (nu->pntsu == 1)
@@ -4280,7 +4293,7 @@ void CURVE_OT_make_segment(wmOperatorType *ot)
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;
@@ -4303,10 +4316,10 @@ bool ED_curve_editnurb_select_pick(bContext *C, const int mval[2], bool extend,
const void *vert = BKE_curve_vert_active_get(cu);
int location[2];
short hand;
-
+
view3d_operator_needs_opengl(C);
ED_view3d_viewcontext_init(C, &vc);
-
+
location[0] = mval[0];
location[1] = mval[1];
@@ -4400,11 +4413,12 @@ bool ED_curve_editnurb_select_pick(bContext *C, const int mval[2], bool extend,
BKE_curve_nurb_active_set(cu, nu);
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return true;
}
-
+
return false;
}
@@ -4429,7 +4443,7 @@ bool ed_editnurb_spin(float viewmat[4][4], Object *obedit, const float axis[3],
/* 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);
@@ -4492,18 +4506,18 @@ static int spin_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
RegionView3D *rv3d = ED_view3d_context_rv3d(C);
float cent[3], axis[3], viewmat[4][4];
-
+
RNA_float_get_array(op->ptr, "center", cent);
RNA_float_get_array(op->ptr, "axis", axis);
-
+
invert_m4_m4(obedit->imat, obedit->obmat);
mul_m4_v3(obedit->imat, cent);
-
+
if (rv3d)
copy_m4_m4(viewmat, rv3d->viewmat);
else
unit_m4(viewmat);
-
+
if (!ed_editnurb_spin(viewmat, obedit, axis, cent)) {
BKE_report(op->reports, RPT_ERROR, "Cannot spin");
return OPERATOR_CANCELLED;
@@ -4524,13 +4538,13 @@ static int spin_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)
View3D *v3d = CTX_wm_view3d(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]);
-
+
RNA_float_set_array(op->ptr, "center", ED_view3d_cursor3d_get(scene, v3d)->location);
RNA_float_set_array(op->ptr, "axis", axis);
-
+
return spin_exec(C, op);
}
@@ -4540,7 +4554,7 @@ void CURVE_OT_spin(wmOperatorType *ot)
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;
@@ -4548,7 +4562,7 @@ void CURVE_OT_spin(wmOperatorType *ot)
/* 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);
@@ -5013,16 +5027,16 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const float mval[2] = {UNPACK2(event->mval)};
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), vc.scene, CTX_data_depsgraph(C), 0, vc.ar, vc.v3d);
+ vc.bmain, vc.scene, vc.depsgraph, 0, vc.ar, vc.v3d);
- ED_transform_snap_object_project_view3d_mixed(
+ ED_transform_snap_object_project_view3d(
snap_context,
- SCE_SELECT_FACE,
+ SCE_SNAP_MODE_FACE,
&(const struct SnapObjectParams){
.snap_select = (vc.obedit != NULL) ? SNAP_NOT_ACTIVE : SNAP_ALL,
.use_object_edit_cage = false,
},
- mval, NULL, true,
+ mval, NULL,
location, NULL);
@@ -5072,7 +5086,7 @@ void CURVE_OT_vertex_add(wmOperatorType *ot)
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;
@@ -5095,7 +5109,7 @@ static int curve_extrude_exec(bContext *C, wmOperator *UNUSED(op))
EditNurb *editnurb = cu->editnurb;
bool changed = false;
bool as_curve = false;
-
+
/* first test: curve? */
if (obedit->type != OB_CURVE) {
Nurb *nu;
@@ -5134,7 +5148,7 @@ void CURVE_OT_extrude(wmOperatorType *ot)
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;
@@ -5201,7 +5215,7 @@ static int toggle_cyclic_exec(bContext *C, wmOperator *op)
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;
@@ -5215,7 +5229,7 @@ static int toggle_cyclic_exec(bContext *C, wmOperator *op)
}
bp++;
}
-
+
}
}
}
@@ -5263,7 +5277,7 @@ void CURVE_OT_cyclic_toggle(wmOperatorType *ot)
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;
@@ -5287,6 +5301,7 @@ static int duplicate_exec(bContext *C, wmOperator *op)
if (BLI_listbase_is_empty(&newnurb) == false) {
BLI_movelisttolist(object_editcurve_get(obedit), &newnurb);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
else {
@@ -5303,11 +5318,11 @@ void CURVE_OT_duplicate(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -5778,19 +5793,19 @@ void CURVE_OT_delete(wmOperatorType *ot)
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;
-
+
/* 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;
}
@@ -5992,17 +6007,17 @@ static int shade_smooth_exec(bContext *C, wmOperator *op)
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;
-
+
for (nu = editnurb->first; nu; nu = nu->next) {
if (ED_curve_nurb_select_check(obedit->data, 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);
@@ -6015,11 +6030,11 @@ void CURVE_OT_shade_smooth(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -6030,11 +6045,11 @@ void CURVE_OT_shade_flat(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -6071,21 +6086,21 @@ int join_curve_exec(bContext *C, wmOperator *op)
}
BLI_listbase_clear(&tempbase);
-
+
/* trasnform all selected curves inverse in obact */
invert_m4_m4(imat, ob->obmat);
-
+
CTX_DATA_BEGIN(C, Base *, base, selected_editable_bases)
{
if (base->object->type == ob->type) {
if (base->object != ob) {
-
+
cu = base->object->data;
-
+
if (cu->nurb.first) {
/* watch it: switch order here really goes wrong */
mul_m4_m4m4(cmat, imat, base->object->obmat);
-
+
nu = cu->nurb.first;
while (nu) {
newnu = BKE_nurb_duplicate(nu);
@@ -6096,7 +6111,7 @@ int join_curve_exec(bContext *C, wmOperator *op)
newnu->mat_nr = 0;
}
BLI_addtail(&tempbase, newnu);
-
+
if ((bezt = newnu->bezt)) {
a = newnu->pntsu;
while (a--) {
@@ -6117,16 +6132,16 @@ int join_curve_exec(bContext *C, wmOperator *op)
nu = nu->next;
}
}
-
+
ED_object_base_free_and_unlink(bmain, scene, base->object);
}
}
}
CTX_DATA_END;
-
+
cu = ob->data;
BLI_movelisttolist(&cu->nurb, &tempbase);
-
+
if (ob->type == OB_CURVE) {
/* Account for mixed 2D/3D curves when joining */
BKE_curve_curve_dimension_update(cu);
@@ -6135,6 +6150,7 @@ int join_curve_exec(bContext *C, wmOperator *op)
DEG_relations_tag_update(bmain); // because we removed object(s), call before editmode!
DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
@@ -6185,11 +6201,11 @@ void CURVE_OT_tilt_clear(wmOperatorType *ot)
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;
-
+
/* 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 f269799973f..7f788b447f6 100644
--- a/source/blender/editors/curve/editcurve_add.c
+++ b/source/blender/editors/curve/editcurve_add.c
@@ -517,10 +517,6 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf)
}
}
- /* ED_object_add_type doesnt do an undo, is needed for redo operator on primitive */
- if (newob && enter_editmode)
- ED_undo_push(C, "Enter Editmode");
-
ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
dia = RNA_float_get(op->ptr, "radius");
mul_mat3_m4_fl(mat, dia);
diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c
index 05425fbcd6a..e679b04f25d 100644
--- a/source/blender/editors/curve/editcurve_paint.c
+++ b/source/blender/editors/curve/editcurve_paint.c
@@ -34,6 +34,7 @@
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_fcurve.h"
+#include "BKE_main.h"
#include "BKE_report.h"
#include "DEG_depsgraph.h"
@@ -52,6 +53,7 @@
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "curve_intern.h"
@@ -432,15 +434,15 @@ static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), ARegion *UNUS
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- glEnable(GL_BLEND);
- glEnable(GL_LINE_SMOOTH);
+ GPU_blend(true);
+ GPU_line_smooth(true);
imm_cpack(0x0);
immBegin(GWN_PRIM_LINE_STRIP, stroke_len);
- glLineWidth(3.0f);
+ GPU_line_width(3.0f);
if (v3d->zbuf) {
- glDisable(GL_DEPTH_TEST);
+ GPU_depth_test(false);
}
for (int i = 0; i < stroke_len; i++) {
@@ -451,7 +453,7 @@ static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), ARegion *UNUS
imm_cpack(0xffffffff);
immBegin(GWN_PRIM_LINE_STRIP, stroke_len);
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
for (int i = 0; i < stroke_len; i++) {
immVertex3fv(pos, coord_array[i]);
@@ -460,11 +462,11 @@ static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), ARegion *UNUS
immEnd();
if (v3d->zbuf) {
- glEnable(GL_DEPTH_TEST);
+ GPU_depth_test(true);
}
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
+ GPU_blend(false);
+ GPU_line_smooth(false);
immUnbindProgram();
}
@@ -616,6 +618,7 @@ static bool curve_draw_init(bContext *C, wmOperator *op, bool is_invoke)
}
}
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);
@@ -1007,9 +1010,16 @@ static int curve_draw_exec(bContext *C, wmOperator *op)
const struct StrokeElem *selem;
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;
+
BPoint *bp = nu->bp;
BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c
index 4d87503fd69..0fae39776a9 100644
--- a/source/blender/editors/curve/editcurve_select.c
+++ b/source/blender/editors/curve/editcurve_select.c
@@ -42,6 +42,7 @@
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_fcurve.h"
+#include "BKE_layer.h"
#include "BKE_report.h"
#include "WM_api.h"
@@ -54,10 +55,10 @@
#include "curve_intern.h"
-
#include "RNA_access.h"
#include "RNA_define.h"
+#include "DEG_depsgraph.h"
/* returns 1 in case (de)selection was successful */
bool select_beztriple(BezTriple *bezt, bool selstatus, short flag, eVisible_Types hidden)
@@ -403,6 +404,7 @@ static int de_select_first_exec(bContext *C, wmOperator *UNUSED(op))
Object *obedit = CTX_data_edit_object(C);
selectend_nurb(obedit, FIRST, true, DESELECT);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
BKE_curve_nurb_vert_active_validate(obedit->data);
@@ -429,6 +431,7 @@ static int de_select_last_exec(bContext *C, wmOperator *UNUSED(op))
Object *obedit = CTX_data_edit_object(C);
selectend_nurb(obedit, LAST, true, DESELECT);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
BKE_curve_nurb_vert_active_validate(obedit->data);
@@ -452,32 +455,47 @@ void CURVE_OT_de_select_last(wmOperatorType *ot)
static int de_select_all_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- Curve *cu = obedit->data;
int action = RNA_enum_get(op->ptr, "action");
+ 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, &objects_len);
+
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
- if (ED_curve_select_check(cu, cu->editnurb)) {
- action = SEL_DESELECT;
+ 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(cu, cu->editnurb)) {
+ action = SEL_DESELECT;
+ break;
+ }
}
}
- switch (action) {
- case SEL_SELECT:
- ED_curve_select_all(cu->editnurb);
- break;
- case SEL_DESELECT:
- ED_curve_deselect_all(cu->editnurb);
- break;
- case SEL_INVERT:
- ED_curve_select_swap(cu->editnurb, (cu->drawflag & CU_HIDE_HANDLES) != 0);
- break;
- }
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ Curve *cu = obedit->data;
+
+ switch (action) {
+ case SEL_SELECT:
+ ED_curve_select_all(cu->editnurb);
+ break;
+ case SEL_DESELECT:
+ ED_curve_deselect_all(cu->editnurb);
+ break;
+ case SEL_INVERT:
+ ED_curve_select_swap(cu->editnurb, (cu->drawflag & CU_HIDE_HANDLES) != 0);
+ break;
+ }
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- BKE_curve_nurb_vert_active_validate(cu);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ BKE_curve_nurb_vert_active_validate(cu);
+ }
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -505,19 +523,31 @@ void CURVE_OT_select_all(wmOperatorType *ot)
static int select_linked_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *obedit = CTX_data_edit_object(C);
- Curve *cu = (Curve *)obedit->data;
- EditNurb *editnurb = cu->editnurb;
- ListBase *nurbs = &editnurb->nurbs;
- Nurb *nu;
+ 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, &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(cu, nu)) {
+ ED_curve_nurb_select_all(nu);
+ changed = true;
+ }
+ }
- for (nu = nurbs->first; nu; nu = nu->next) {
- if (ED_curve_nurb_select_check(cu, nu)) {
- ED_curve_nurb_select_all(nu);
+ if (changed) {
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
}
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -532,7 +562,7 @@ 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 active one";
+ ot->description = "Select all control points linked to the current selection";
/* api callbacks */
ot->exec = select_linked_exec;
@@ -582,6 +612,7 @@ static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent
}
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
if (!select) {
BKE_curve_nurb_vert_active_validate(obedit->data);
@@ -644,6 +675,7 @@ static int select_row_exec(bContext *C, wmOperator *UNUSED(op))
}
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -672,6 +704,7 @@ static int select_next_exec(bContext *C, wmOperator *UNUSED(op))
ListBase *editnurb = object_editcurve_get(obedit);
select_adjacent_cp(editnurb, 1, 0, SELECT);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -700,6 +733,7 @@ static int select_previous_exec(bContext *C, wmOperator *UNUSED(op))
ListBase *editnurb = object_editcurve_get(obedit);
select_adjacent_cp(editnurb, -1, 0, SELECT);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -788,6 +822,7 @@ static int select_more_exec(bContext *C, wmOperator *UNUSED(op))
select_adjacent_cp(editnurb, -1, 0, SELECT);
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -975,6 +1010,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
}
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
BKE_curve_nurb_vert_active_validate(obedit->data);
@@ -1040,17 +1076,32 @@ static void curve_select_random(ListBase *editnurb, float randfac, int seed, boo
static int curve_select_random_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
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);
- curve_select_random(editnurb, randfac, seed, select);
- BKE_curve_nurb_vert_active_validate(obedit->data);
+ 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, &objects_len);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ 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, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -1157,6 +1208,7 @@ static int select_nth_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -1463,6 +1515,7 @@ static int curve_select_similar_exec(bContext *C, wmOperator *op)
}
if (changed) {
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
}
@@ -1704,6 +1757,7 @@ static int edcu_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE
BKE_curve_nurb_vert_active_set(cu, nu_dst, vert_dst_p);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index a9a8901acc6..75efdec3dd2 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -82,7 +82,7 @@ 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;
@@ -214,7 +214,7 @@ static char findaccent(char char1, unsigned int code)
else if (char1 == '+') {
if (code == '-') new = 177;
}
-
+
if (new) return new;
else return char1;
}
@@ -223,7 +223,7 @@ 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;
@@ -233,7 +233,7 @@ static int insert_into_textbuf(Object *obedit, uintptr_t 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';
@@ -246,7 +246,6 @@ static int insert_into_textbuf(Object *obedit, uintptr_t c)
static void text_update_edited(bContext *C, Object *obedit, int mode)
{
- struct Main *bmain = CTX_data_main(C);
Curve *cu = obedit->data;
EditFont *ef = cu->editfont;
@@ -259,7 +258,7 @@ static void text_update_edited(bContext *C, Object *obedit, int mode)
}
else {
/* depsgraph runs above, but since we're not tagging for update, call direct */
- BKE_vfont_to_curve(bmain, obedit, mode);
+ BKE_vfont_to_curve(obedit, mode);
}
cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0];
@@ -378,7 +377,7 @@ static int paste_from_file_exec(bContext *C, wmOperator *op)
{
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);
@@ -391,7 +390,7 @@ static int paste_from_file_invoke(bContext *C, wmOperator *op, const wmEvent *UN
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;
}
@@ -402,12 +401,12 @@ void FONT_OT_text_paste_from_file(wmOperatorType *ot)
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;
@@ -433,7 +432,7 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const
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;
@@ -506,12 +505,12 @@ void ED_text_to_object(bContext *C, Text *text, const bool split_lines)
linenum++;
continue;
}
-
+
/* do the translation */
offset[0] = 0;
offset[1] = -linenum;
offset[2] = 0;
-
+
if (rv3d)
mul_mat3_m4_v3(rv3d->viewinv, offset);
@@ -607,11 +606,11 @@ void FONT_OT_style_set(wmOperatorType *ot)
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;
@@ -630,7 +629,7 @@ static int toggle_style_exec(bContext *C, wmOperator *op)
if (!BKE_vfont_select_get(obedit, &selstart, &selend))
return OPERATOR_CANCELLED;
-
+
style = RNA_enum_get(op->ptr, "style");
cu->curinfo.flag ^= style;
@@ -645,11 +644,11 @@ void FONT_OT_style_toggle(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -703,7 +702,7 @@ void FONT_OT_select_all(wmOperatorType *ot)
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;
@@ -740,7 +739,7 @@ void FONT_OT_text_copy(wmOperatorType *ot)
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;
@@ -770,7 +769,7 @@ void FONT_OT_text_cut(wmOperatorType *ot)
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;
@@ -871,7 +870,7 @@ void FONT_OT_text_paste(wmOperatorType *ot)
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;
@@ -915,7 +914,7 @@ static int move_cursor(bContext *C, int type, const bool select)
}
cursmove = FO_CURS;
break;
-
+
case LINE_END:
while (ef->pos < ef->len) {
if (ef->textbuf[ef->pos] == 0) break;
@@ -958,7 +957,7 @@ static int move_cursor(bContext *C, int type, const bool select)
case PREV_LINE:
cursmove = FO_CURSUP;
break;
-
+
case NEXT_LINE:
cursmove = FO_CURSDOWN;
break;
@@ -971,7 +970,7 @@ static int move_cursor(bContext *C, int type, const bool select)
cursmove = FO_PAGEDOWN;
break;
}
-
+
if (cursmove == -1)
return OPERATOR_CANCELLED;
@@ -982,16 +981,14 @@ static int move_cursor(bContext *C, int type, const bool select)
/* apply virtical cursor motion to position immediately
* otherwise the selection will lag behind */
if (FO_CURS_IS_MOTION(cursmove)) {
- struct Main *bmain = CTX_data_main(C);
- BKE_vfont_to_curve(bmain, obedit, cursmove);
+ BKE_vfont_to_curve(obedit, cursmove);
cursmove = FO_CURS;
}
if (select == 0) {
if (ef->selstart) {
- struct Main *bmain = CTX_data_main(C);
ef->selstart = ef->selend = 0;
- BKE_vfont_to_curve(bmain, obedit, FO_SELCHANGE);
+ BKE_vfont_to_curve(obedit, FO_SELCHANGE);
}
}
@@ -1016,7 +1013,7 @@ void FONT_OT_move(wmOperatorType *ot)
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;
@@ -1043,7 +1040,7 @@ void FONT_OT_move_select(wmOperatorType *ot)
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;
@@ -1084,7 +1081,7 @@ void FONT_OT_change_spacing(wmOperatorType *ot)
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;
@@ -1128,7 +1125,7 @@ void FONT_OT_change_character(wmOperatorType *ot)
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;
@@ -1163,7 +1160,7 @@ void FONT_OT_line_break(wmOperatorType *ot)
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;
@@ -1289,7 +1286,7 @@ void FONT_OT_delete(wmOperatorType *ot)
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;
@@ -1312,7 +1309,7 @@ static int insert_text_exec(bContext *C, wmOperator *op)
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);
@@ -1350,7 +1347,7 @@ static int insert_text_invoke(bContext *C, wmOperator *op, const wmEvent *event)
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)
@@ -1358,7 +1355,7 @@ static int insert_text_invoke(bContext *C, wmOperator *op, const wmEvent *event)
else
ascii = 9;
}
-
+
if (event_type == BACKSPACEKEY) {
if (alt && ef->len != 0 && ef->pos > 0)
accentcode = 1;
@@ -1394,7 +1391,7 @@ static int insert_text_invoke(bContext *C, wmOperator *op, const wmEvent *event)
else {
BLI_assert(0);
}
-
+
kill_selection(obedit, 1);
text_update_edited(C, obedit, FO_EDIT);
}
@@ -1418,7 +1415,7 @@ static int insert_text_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* reset property? */
if (event_val == 0)
accentcode = 0;
-
+
return OPERATOR_FINISHED;
}
@@ -1428,12 +1425,12 @@ void FONT_OT_text_insert(wmOperatorType *ot)
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_REGISTER | OPTYPE_UNDO;
@@ -1449,14 +1446,14 @@ 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++;
}
-
+
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
}
@@ -1467,15 +1464,15 @@ void FONT_OT_textbox_add(wmOperatorType *ot)
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;
-
-
+
+
}
@@ -1490,17 +1487,17 @@ static int textbox_remove_exec(bContext *C, wmOperator *op)
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--;
}
-
+
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
-
+
return OPERATOR_FINISHED;
}
@@ -1510,14 +1507,14 @@ void FONT_OT_textbox_remove(wmOperatorType *ot)
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;
-
+
/* 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);
}
@@ -1530,14 +1527,14 @@ void ED_curve_editfont_make(Object *obedit)
Curve *cu = obedit->data;
EditFont *ef = cu->editfont;
int len_wchar;
-
+
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");
}
-
+
/* 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);
@@ -1576,7 +1573,7 @@ void ED_curve_editfont_load(Object *obedit)
/* 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");
@@ -1608,7 +1605,7 @@ static int set_case(bContext *C, int ccase)
wchar_t *str;
int len;
int selstart, selend;
-
+
if (BKE_vfont_select_get(obedit, &selstart, &selend)) {
len = (selend - selstart) + 1;
str = &ef->textbuf[selstart];
@@ -1648,7 +1645,7 @@ void FONT_OT_case_set(wmOperatorType *ot)
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;
@@ -1669,7 +1666,7 @@ static int toggle_case_exec(bContext *C, wmOperator *UNUSED(op))
EditFont *ef = cu->editfont;
wchar_t *str;
int len, ccase = CASE_UPPER;
-
+
len = wcslen(ef->textbuf);
str = ef->textbuf;
while (len) {
@@ -1681,7 +1678,7 @@ static int toggle_case_exec(bContext *C, wmOperator *UNUSED(op))
len--;
str++;
}
-
+
return set_case(C, ccase);
}
@@ -1691,7 +1688,7 @@ void FONT_OT_case_toggle(wmOperatorType *ot)
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;
@@ -1705,7 +1702,7 @@ void FONT_OT_case_toggle(wmOperatorType *ot)
static void font_ui_template_init(bContext *C, wmOperator *op)
{
PropertyPointerRNA *pprop;
-
+
op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop);
}
@@ -1734,7 +1731,7 @@ static int font_open_exec(bContext *C, wmOperator *op)
if (!op->customdata)
font_ui_template_init(C, op);
-
+
/* hook into UI */
pprop = op->customdata;
@@ -1742,7 +1739,7 @@ static int font_open_exec(bContext *C, wmOperator *op)
/* 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);
@@ -1777,7 +1774,7 @@ static int open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)
return font_open_exec(C, op);
RNA_string_set(op->ptr, "filepath", path);
- WM_event_add_fileselect(C, op);
+ WM_event_add_fileselect(C, op);
return OPERATOR_RUNNING_MODAL;
}
@@ -1788,15 +1785,15 @@ void FONT_OT_open(wmOperatorType *ot)
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,
@@ -1813,7 +1810,7 @@ static int font_unlink_exec(bContext *C, wmOperator *op)
PropertyPointerRNA pprop;
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;
@@ -1834,7 +1831,7 @@ void FONT_OT_unlink(wmOperatorType *ot)
ot->name = "Unlink";
ot->idname = "FONT_OT_unlink";
ot->description = "Unlink active font data-block";
-
+
/* api callbacks */
ot->exec = font_unlink_exec;
}
diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt
index 23b328aa8e0..640239ccc60 100644
--- a/source/blender/editors/datafiles/CMakeLists.txt
+++ b/source/blender/editors/datafiles/CMakeLists.txt
@@ -202,6 +202,10 @@ set(ICON_NAMES
group_uvs
rna
rna_add
+ mouse_lmb
+ mouse_mmb
+ mouse_rmb
+ mouse_drag
outliner_ob_empty
outliner_ob_mesh
outliner_ob_curve
@@ -681,32 +685,6 @@ if(WITH_BLENDER)
data_to_c_simple(../../../../release/datafiles/brushicons/twist.png SRC)
data_to_c_simple(../../../../release/datafiles/brushicons/vertexdraw.png SRC)
- # matcap
- data_to_c_simple(../../../../release/datafiles/matcaps/mc01.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc02.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc03.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc04.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc05.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc06.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc07.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc08.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc09.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc10.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc11.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc12.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc13.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc14.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc15.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc16.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc17.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc18.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc19.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc20.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc21.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc22.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc23.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc24.jpg SRC)
-
endif()
data_to_c_simple(../../../../release/datafiles/startup.blend SRC)
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index 50a6e9125a0..a79a5052eb8 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -64,6 +64,7 @@
#include "GPU_immediate.h"
#include "GPU_draw.h"
+#include "GPU_state.h"
#include "ED_gpencil.h"
#include "ED_screen.h"
@@ -215,7 +216,7 @@ static void gp_draw_stroke_buffer(const tGPspoint *points, int totpoints, short
if (totpoints == 1) {
/* if drawing a single point, draw it larger */
- glPointSize((float)(thickness + 2) * points->pressure);
+ GPU_point_size((float)(thickness + 2) * points->pressure);
immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR);
immBegin(GWN_PRIM_POINTS, 1);
gp_set_tpoint_varying_color(pt, ink, color);
@@ -225,7 +226,7 @@ static void gp_draw_stroke_buffer(const tGPspoint *points, int totpoints, short
float oldpressure = points[0].pressure;
/* draw stroke curve */
- glLineWidth(max_ff(oldpressure * thickness, 1.0));
+ GPU_line_width(max_ff(oldpressure * thickness, 1.0));
immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
immBeginAtMost(GWN_PRIM_LINE_STRIP, totpoints);
@@ -245,11 +246,11 @@ static void gp_draw_stroke_buffer(const tGPspoint *points, int totpoints, short
immEnd();
draw_points = 0;
- glLineWidth(max_ff(pt->pressure * thickness, 1.0f));
+ GPU_line_width(max_ff(pt->pressure * thickness, 1.0f));
immBeginAtMost(GWN_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) {
+ if (i != 0) {
gp_set_tpoint_varying_color(pt - 1, ink, color);
immVertex2iv(pos, &(pt - 1)->x);
++draw_points;
@@ -389,7 +390,7 @@ static void gp_draw_stroke_volumetric_3d(
const bGPDspoint *pt = points;
for (int i = 0; i < totpoints && pt; i++, pt++) {
- gp_set_point_varying_color(pt, ink, color);
+ gp_set_point_varying_color(pt, ink, color);
immAttrib1f(size, pt->pressure * thickness); /* TODO: scale based on view transform */
immVertex3fv(pos, &pt->x); /* we can adjust size in vertex shader based on view/projection! */
}
@@ -625,7 +626,7 @@ static void gp_draw_stroke_3d(const bGPDspoint *points, int totpoints, short thi
/* TODO: implement this with a geometry shader to draw one continuous tapered stroke */
/* draw stroke curve */
- glLineWidth(max_ff(curpressure * thickness, 1.0f));
+ GPU_line_width(max_ff(curpressure * thickness, 1.0f));
immBeginAtMost(GWN_PRIM_LINE_STRIP, totpoints + cyclic_add);
const bGPDspoint *pt = points;
for (int i = 0; i < totpoints; i++, pt++) {
@@ -646,11 +647,11 @@ static void gp_draw_stroke_3d(const bGPDspoint *points, int totpoints, short thi
draw_points = 0;
curpressure = pt->pressure;
- glLineWidth(max_ff(curpressure * thickness, 1.0f));
+ GPU_line_width(max_ff(curpressure * thickness, 1.0f));
immBeginAtMost(GWN_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) {
+ if (i != 0) {
const bGPDspoint *pt2 = pt - 1;
mul_v3_m4v3(fpt, diff_mat, &pt2->x);
gp_set_point_varying_color(pt2, ink, color);
@@ -941,7 +942,7 @@ static void gp_draw_strokes(
if (no_xray) {
glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig);
glDepthMask(0);
- glEnable(GL_DEPTH_TEST);
+ GPU_depth_test(true);
/* first arg is normally rv3d->dist, but this isn't
* available here and seems to work quite well without */
@@ -1005,7 +1006,7 @@ static void gp_draw_strokes(
}
if (no_xray) {
glDepthMask(mask_orig);
- glDisable(GL_DEPTH_TEST);
+ GPU_depth_test(false);
bglPolygonOffset(0.0, 0.0);
}
@@ -1090,7 +1091,7 @@ static void gp_draw_strokes_edit(
if (no_xray) {
glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig);
glDepthMask(0);
- glEnable(GL_DEPTH_TEST);
+ GPU_depth_test(true);
/* first arg is normally rv3d->dist, but this isn't
* available here and seems to work quite well without */
@@ -1215,7 +1216,7 @@ static void gp_draw_strokes_edit(
if (dflag & GP_DRAWDATA_ONLY3D) {
if (no_xray) {
glDepthMask(mask_orig);
- glDisable(GL_DEPTH_TEST);
+ GPU_depth_test(false);
bglPolygonOffset(0.0, 0.0);
#if 0
@@ -1322,14 +1323,14 @@ void ED_gp_draw_interpolation(tGPDinterpolate *tgpi, const int type)
UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, color);
color[3] = 0.6f;
- int dflag = 0;
+ int dflag = 0;
/* if 3d stuff, enable flags */
if (type == REGION_DRAW_POST_VIEW) {
dflag |= (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_NOSTATUS);
}
/* turn on alpha-blending */
- glEnable(GL_BLEND);
+ GPU_blend(true);
for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
/* calculate parent position */
ED_gpencil_parent_location(tgpil->gpl, diff_mat);
@@ -1338,7 +1339,7 @@ void ED_gp_draw_interpolation(tGPDinterpolate *tgpi, const int type)
tgpil->gpl->thickness, 1.0f, color, true, true, diff_mat);
}
}
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
/* loop over gpencil data layers, drawing them */
@@ -1365,8 +1366,8 @@ static void gp_draw_data_layers(
continue;
/* set basic stroke thickness */
- glLineWidth(lthick);
-
+ 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
@@ -1386,7 +1387,7 @@ static void gp_draw_data_layers(
GP_DRAWFLAG_APPLY((gpl->flag & GP_LAYER_HQ_FILL), GP_DRAWDATA_HQ_FILL);
#undef GP_DRAWFLAG_APPLY
-
+
/* Draw 'onionskins' (frame left + right)
* - It is only possible to show these if the option is enabled
* - The "no onions" flag prevents ghosts from appearing during animation playback/scrubbing
@@ -1394,8 +1395,8 @@ static void gp_draw_data_layers(
* - The per-layer "always show" flag however overrides the playback/render restriction,
* allowing artists to selectively turn onionskins on/off during playback
*/
- if ((gpl->flag & GP_LAYER_ONIONSKIN) &&
- ((dflag & GP_DRAWDATA_NO_ONIONS) == 0 || (gpl->flag & GP_LAYER_GHOST_ALWAYS)))
+ if ((gpl->flag & GP_LAYER_ONIONSKIN) &&
+ ((dflag & GP_DRAWDATA_NO_ONIONS) == 0 || (gpl->flag & GP_LAYER_GHOST_ALWAYS)))
{
/* Drawing method - only immediately surrounding (gstep = 0),
* or within a frame range on either side (gstep > 0)
@@ -1430,7 +1431,7 @@ static void gp_draw_data_layers(
{
/* 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
*/
@@ -1465,7 +1466,7 @@ static void gp_draw_status_text(const bGPdata *gpd, ARegion *ar)
int font_id = BLF_default();
BLF_width_and_height(font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
-
+
int xco = (rect.xmax - U.widget_unit) - (int)printable_size[0];
int yco = (rect.ymax - U.widget_unit);
@@ -1479,15 +1480,15 @@ static void gp_draw_status_text(const bGPdata *gpd, ARegion *ar)
/* grease pencil icon... */
// XXX: is this too intrusive?
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
xco -= U.widget_unit;
yco -= (int)printable_size[1] / 2;
UI_icon_draw(xco, yco, ICON_GREASEPENCIL);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
}
@@ -1497,23 +1498,23 @@ static void gp_draw_data(
int offsx, int offsy, int winx, int winy, int cfra, int dflag)
{
/* turn on smooth lines (i.e. anti-aliasing) */
- glEnable(GL_LINE_SMOOTH);
+ GPU_line_smooth(true);
- /* XXX: turn on some way of ensuring that the polygon edges get smoothed
+ /* XXX: turn on some way of ensuring that the polygon edges get smoothed
* GL_POLYGON_SMOOTH is nasty and shouldn't be used, as it ends up
* creating internal white rays due to the ways it accumulates stuff
*/
/* turn on alpha-blending */
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
+ 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(brush, alpha, gpd, offsx, offsy, winx, winy, cfra, dflag);
/* turn off alpha blending, then smooth lines */
- glDisable(GL_BLEND); // alpha blending
- glDisable(GL_LINE_SMOOTH); // 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)
@@ -1643,7 +1644,7 @@ void ED_gpencil_draw_view2d(const bContext *C, bool onlyv2d)
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
@@ -1725,7 +1726,7 @@ void ED_gpencil_draw_view3d(wmWindowManager *wm,
}
/* draw it! */
- gp_draw_data_all(scene, gpd, offsx, offsy, winx, winy, CFRA, dflag, v3d->spacetype);
+ gp_draw_data_all(scene, gpd, offsx, offsy, winx, winy, CFRA, dflag, v3d->spacetype);
}
void ED_gpencil_draw_ex(Scene *scene, bGPdata *gpd, int winx, int winy, const int cfra, const char spacetype)
diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c
index 90d44503013..5e62a87caf3 100644
--- a/source/blender/editors/gpencil/editaction_gpencil.c
+++ b/source/blender/editors/gpencil/editaction_gpencil.c
@@ -66,18 +66,18 @@
bool ED_gplayer_frames_looper(bGPDlayer *gpl, Scene *scene, short (*gpf_cb)(bGPDframe *, Scene *))
{
bGPDframe *gpf;
-
+
/* error checker */
if (gpl == NULL)
return false;
-
+
/* do loop */
for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
/* execute callback */
if (gpf_cb(gpf, scene))
return true;
}
-
+
/* nothing to return */
return false;
}
@@ -90,19 +90,19 @@ void ED_gplayer_make_cfra_list(bGPDlayer *gpl, ListBase *elems, bool onlysel)
{
bGPDframe *gpf;
CfraElem *ce;
-
+
/* 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");
-
+
ce->cfra = (float)gpf->framenum;
ce->sel = (gpf->flag & GP_FRAME_SELECT) ? 1 : 0;
-
+
BLI_addtail(elems, ce);
}
}
@@ -115,17 +115,17 @@ void ED_gplayer_make_cfra_list(bGPDlayer *gpl, ListBase *elems, bool onlysel)
bool ED_gplayer_frame_select_check(bGPDlayer *gpl)
{
bGPDframe *gpf;
-
+
/* error checking */
if (gpl == NULL)
return false;
-
+
/* stop at the first one found */
for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
if (gpf->flag & GP_FRAME_SELECT)
return true;
}
-
+
/* not found */
return false;
}
@@ -135,7 +135,7 @@ static void gpframe_select(bGPDframe *gpf, short select_mode)
{
if (gpf == NULL)
return;
-
+
switch (select_mode) {
case SELECT_ADD:
gpf->flag |= GP_FRAME_SELECT;
@@ -153,11 +153,11 @@ static void gpframe_select(bGPDframe *gpf, short select_mode)
void ED_gpencil_select_frames(bGPDlayer *gpl, short select_mode)
{
bGPDframe *gpf;
-
+
/* error checking */
if (gpl == NULL)
return;
-
+
/* handle according to mode */
for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
gpframe_select(gpf, select_mode);
@@ -170,7 +170,7 @@ void ED_gplayer_frame_select_set(bGPDlayer *gpl, short mode)
/* error checking */
if (gpl == NULL)
return;
-
+
/* now call the standard function */
ED_gpencil_select_frames(gpl, mode);
}
@@ -179,12 +179,12 @@ void ED_gplayer_frame_select_set(bGPDlayer *gpl, short mode)
void ED_gpencil_select_frame(bGPDlayer *gpl, int selx, short select_mode)
{
bGPDframe *gpf;
-
+
if (gpl == NULL)
return;
-
+
gpf = BKE_gpencil_layer_find_frame(gpl, selx);
-
+
if (gpf) {
gpframe_select(gpf, select_mode);
}
@@ -194,10 +194,10 @@ void ED_gpencil_select_frame(bGPDlayer *gpl, int selx, short select_mode)
void ED_gplayer_frames_select_border(bGPDlayer *gpl, float min, float max, short select_mode)
{
bGPDframe *gpf;
-
+
if (gpl == NULL)
return;
-
+
/* only select those frames which are in bounds */
for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
if (IN_RANGE(gpf->framenum, min, max))
@@ -209,21 +209,21 @@ void ED_gplayer_frames_select_border(bGPDlayer *gpl, float min, float max, short
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 */
+ /* Lasso */
if (keyframe_region_lasso_test(ked->data, pt))
gpframe_select(gpf, select_mode);
}
@@ -243,21 +243,21 @@ bool ED_gplayer_frames_delete(bGPDlayer *gpl)
{
bGPDframe *gpf, *gpfn;
bool changed = false;
-
+
/* error checking */
if (gpl == NULL)
return false;
-
+
/* 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;
}
}
-
+
return changed;
}
@@ -265,23 +265,23 @@ bool ED_gplayer_frames_delete(bGPDlayer *gpl)
void ED_gplayer_frames_duplicate(bGPDlayer *gpl)
{
bGPDframe *gpf, *gpfn;
-
+
/* error checking */
if (gpl == NULL)
return;
-
+
/* duplicate selected frames */
for (gpf = gpl->frames.first; gpf; gpf = gpfn) {
gpfn = gpf->next;
-
+
/* 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;
-
+
BLI_insertlinkafter(&gpl->frames, gpf, gpfd);
}
}
@@ -293,10 +293,10 @@ void ED_gplayer_frames_duplicate(bGPDlayer *gpl)
void ED_gplayer_frames_keytype_set(bGPDlayer *gpl, short type)
{
bGPDframe *gpf;
-
+
if (gpl == NULL)
return;
-
+
for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
if (gpf->flag & GP_FRAME_SELECT) {
gpf->key_type = type;
@@ -327,7 +327,7 @@ void ED_gpencil_anim_copybuf_free(void)
{
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;
@@ -344,23 +344,23 @@ 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 */
@@ -368,41 +368,41 @@ bool ED_gpencil_anim_copybuf_copy(bAnimContext *ac)
/* 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;
+ 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;
}
@@ -414,22 +414,22 @@ 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:
@@ -446,19 +446,19 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode)
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 */
@@ -466,21 +466,21 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode)
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, 1);
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
@@ -495,19 +495,19 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode)
/* duplicate triangle information */
gpsn->triangles = MEM_dupallocN(gps->triangles);
/* append stroke to frame */
- BLI_addtail(&gpf->strokes, gpsn);
+ 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;
@@ -574,37 +574,37 @@ void ED_gplayer_snap_frames(bGPDlayer *gpl, Scene *scene, short mode)
static short mirror_gpf_cframe(bGPDframe *gpf, Scene *scene)
{
int diff;
-
+
if (gpf->flag & GP_FRAME_SELECT) {
diff = CFRA - gpf->framenum;
gpf->framenum = CFRA + diff;
}
-
+
return 0;
}
static short mirror_gpf_yaxis(bGPDframe *gpf, Scene *UNUSED(scene))
{
int diff;
-
+
if (gpf->flag & GP_FRAME_SELECT) {
diff = -gpf->framenum;
gpf->framenum = diff;
}
-
+
return 0;
}
static short mirror_gpf_xaxis(bGPDframe *gpf, Scene *UNUSED(scene))
{
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;
}
-
+
return 0;
}
@@ -613,7 +613,7 @@ 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
@@ -621,7 +621,7 @@ static short mirror_gpf_marker(bGPDframe *gpf, Scene *scene)
* 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)) {
@@ -644,7 +644,7 @@ static short mirror_gpf_marker(bGPDframe *gpf, Scene *scene)
}
}
}
-
+
return 0;
}
diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c
index 1cb882e9a43..d877ea03c5d 100644
--- a/source/blender/editors/gpencil/gpencil_brush.c
+++ b/source/blender/editors/gpencil/gpencil_brush.c
@@ -44,6 +44,8 @@
#include "BLI_rand.h"
#include "BLI_utildefines.h"
+#include "PIL_time.h"
+
#include "BLT_translation.h"
#include "DNA_scene_types.h"
@@ -76,6 +78,7 @@
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
+#include "GPU_state.h"
#include "gpencil_intern.h"
@@ -87,57 +90,59 @@ typedef struct tGP_BrushEditData {
/* Current editor/region/etc. */
/* NOTE: This stuff is mainly needed to handle 3D view projection stuff... */
Scene *scene;
-
+
ScrArea *sa;
ARegion *ar;
-
+
/* Current GPencil datablock */
bGPdata *gpd;
-
+
/* Brush Settings */
GP_BrushEdit_Settings *settings;
GP_EditBrush_Data *brush;
-
+
eGP_EditBrush_Types brush_type;
eGP_EditBrush_Flag flag;
-
+
/* Space Conversion Data */
GP_SpaceConversion gsc;
-
-
+
+
/* Is the brush currently painting? */
bool is_painting;
-
+
/* Start of new sculpt stroke */
bool first;
-
+
/* Current frame */
int cfra;
-
-
+
+
/* Brush Runtime Data: */
/* - position and pressure
* - the *_prev variants are the previous values
*/
int mval[2], mval_prev[2];
float pressure, pressure_prev;
-
+
/* - effect vector (e.g. 2D/3D translation for grab brush) */
float dvec[3];
-
+
/* 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;
-
-
+
+
/* Timer for in-place accumulation of brush effect */
wmTimer *timer;
bool timerTick; /* is this event from a timer */
+
+ RNG *rng;
} tGP_BrushEditData;
@@ -170,12 +175,12 @@ static bool gp_brush_invert_check(tGP_BrushEditData *gso)
{
/* The basic setting is the brush's setting (from the panel) */
bool invert = ((gso->brush->flag & GP_EDITBRUSH_FLAG_INVERT) != 0);
-
+
/* During runtime, the user can hold down the Ctrl key to invert the basic behaviour */
if (gso->flag & GP_EDITBRUSH_FLAG_INVERT) {
invert ^= true;
}
-
+
return invert;
}
@@ -183,26 +188,26 @@ static bool gp_brush_invert_check(tGP_BrushEditData *gso)
static float gp_brush_influence_calc(tGP_BrushEditData *gso, const int radius, const int co[2])
{
GP_EditBrush_Data *brush = gso->brush;
-
+
/* basic strength factor from brush settings */
float influence = brush->strength;
-
+
/* use pressure? */
if (brush->flag & GP_EDITBRUSH_FLAG_USE_PRESSURE) {
influence *= gso->pressure;
}
-
+
/* distance fading */
if (brush->flag & GP_EDITBRUSH_FLAG_USE_FALLOFF) {
float distance = (float)len_v2v2_int(gso->mval, co);
float fac;
-
+
CLAMP(distance, 0.0f, (float)radius);
fac = 1.0f - (distance / (float)radius);
-
+
influence *= fac;
}
-
+
/* return influence */
return influence;
}
@@ -241,7 +246,7 @@ static bool gp_brush_smooth_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i
if (gso->settings->flag & GP_BRUSHEDIT_FLAG_APPLY_THICKNESS) {
gp_smooth_stroke_thickness(gps, i, inf);
}
-
+
return true;
}
@@ -254,13 +259,13 @@ static bool gp_brush_thickness_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in
{
bGPDspoint *pt = gps->points + i;
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)) {
@@ -271,7 +276,7 @@ static bool gp_brush_thickness_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in
/* 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
@@ -279,7 +284,7 @@ static bool gp_brush_thickness_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in
*/
if (pt->pressure < 0.0f)
pt->pressure = 0.0f;
-
+
return true;
}
@@ -333,7 +338,7 @@ typedef struct tGPSB_Grab_StrokeData {
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 */
@@ -344,9 +349,9 @@ typedef struct tGPSB_Grab_StrokeData {
static void gp_brush_grab_stroke_init(tGP_BrushEditData *gso, bGPDstroke *gps)
{
tGPSB_Grab_StrokeData *data = NULL;
-
+
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
@@ -355,25 +360,25 @@ static void gp_brush_grab_stroke_init(tGP_BrushEditData *gso, bGPDstroke *gps)
*/
data = BLI_ghash_lookup(gso->stroke_customdata, gps);
BLI_assert(data != NULL);
-
+
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");
-
+
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");
-
+
/* hook up to the cache */
BLI_ghash_insert(gso->stroke_customdata, gps, data);
- }
+ }
}
/* store references to stroke points in the initial stage */
@@ -382,15 +387,15 @@ static bool gp_brush_grab_store_points(tGP_BrushEditData *gso, bGPDstroke *gps,
{
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);
-
+
/* insert this point into the set of affected points */
data->points[data->size] = i;
data->weights[data->size] = inf;
data->size++;
-
+
/* done */
return true;
}
@@ -406,13 +411,13 @@ static void gp_brush_grab_calc_dvec(tGP_BrushEditData *gso)
RegionView3D *rv3d = gso->ar->regiondata;
float *rvec = ED_view3d_cursor3d_get(gso->scene, v3d)->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 {
@@ -435,7 +440,7 @@ static void gp_brush_grab_apply_cached(
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]);
if (!parented) {
@@ -454,7 +459,7 @@ static void gp_brush_grab_apply_cached(
invert_m4_m4(inverse_diff_mat, diff_mat);
mul_m4_v3(inverse_diff_mat, &pt->x);
}
-
+
}
}
@@ -462,11 +467,11 @@ static void gp_brush_grab_apply_cached(
static void gp_brush_grab_stroke_free(void *ptr)
{
tGPSB_Grab_StrokeData *data = (tGPSB_Grab_StrokeData *)ptr;
-
+
/* free arrays */
MEM_freeN(data->points);
MEM_freeN(data->weights);
-
+
/* ... and this item itself, since it was also allocated */
MEM_freeN(data);
}
@@ -481,10 +486,10 @@ static bool gp_brush_push_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i,
bGPDspoint *pt = gps->points + i;
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);
-
+
/* apply */
add_v3_v3(&pt->x, delta);
@@ -506,12 +511,12 @@ static void gp_brush_calc_midpoint(tGP_BrushEditData *gso)
RegionView3D *rv3d = gso->ar->regiondata;
float *rvec = ED_view3d_cursor3d_get(gso->scene, v3d)->location;
float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL);
-
+
float mval_f[2] = {UNPACK2(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);
@@ -537,17 +542,17 @@ static bool gp_brush_pinch_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i,
bGPDspoint *pt = gps->points + i;
float fac, inf;
float vec[3];
-
+
/* 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
@@ -562,10 +567,10 @@ static bool gp_brush_pinch_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i,
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);
-
+
/* done */
return true;
}
@@ -582,16 +587,16 @@ static bool gp_brush_twist_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i,
{
bGPDspoint *pt = gps->points + i;
float angle, inf;
-
+
/* 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... */
@@ -599,13 +604,13 @@ static bool gp_brush_twist_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i,
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);
@@ -615,20 +620,20 @@ static bool gp_brush_twist_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i,
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;
@@ -639,7 +644,7 @@ static bool gp_brush_twist_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i,
copy_v2_v2(&pt->x, vec);
}
}
-
+
/* done */
return true;
}
@@ -653,12 +658,12 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in
const int radius, const int co[2])
{
bGPDspoint *pt = gps->points + i;
-
+
/* 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_frand() * inf;
+ const float fac = BLI_rng_get_float(gso->rng) * inf;
/* need one flag enabled by default */
if ((gso->settings->flag & (GP_BRUSHEDIT_FLAG_APPLY_POSITION |
GP_BRUSHEDIT_FLAG_APPLY_STRENGTH |
@@ -685,7 +690,7 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in
svec[1] = mvec[0];
/* scale the displacement by the random displacement, and apply */
- if (BLI_frand() > 0.5f) {
+ if (BLI_rng_get_float(gso->rng) > 0.5f) {
mul_v2_fl(svec, -fac);
}
else {
@@ -724,7 +729,7 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in
}
/* apply random to strength */
if (gso->settings->flag & GP_BRUSHEDIT_FLAG_APPLY_STRENGTH) {
- if (BLI_frand() > 0.5f) {
+ if (BLI_rng_get_float(gso->rng) > 0.5f) {
pt->strength += fac;
}
else {
@@ -735,7 +740,7 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in
}
/* apply random to thickness (use pressure) */
if (gso->settings->flag & GP_BRUSHEDIT_FLAG_APPLY_THICKNESS) {
- if (BLI_frand() > 0.5f) {
+ if (BLI_rng_get_float(gso->rng) > 0.5f) {
pt->pressure += fac;
}
else {
@@ -766,13 +771,13 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in
typedef struct tGPSB_CloneBrushData {
/* 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;
-
+
/* 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;
} tGPSB_CloneBrushData;
@@ -782,43 +787,43 @@ 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 colour(names)
* and the final colours that will be used here instead...
*/
@@ -829,19 +834,19 @@ static void gp_brush_clone_init(bContext *C, tGP_BrushEditData *gso)
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;
@@ -851,44 +856,44 @@ static void gp_brush_clone_free(tGP_BrushEditData *gso)
static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso)
{
tGPSB_CloneBrushData *data = gso->customdata;
-
+
Scene *scene = gso->scene;
bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, true);
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);
new_stroke->triangles = MEM_dupallocN(gps->triangles);
-
+
new_stroke->next = new_stroke->prev = NULL;
BLI_addtail(&gpf->strokes, new_stroke);
-
+
/* Fix color references */
BLI_assert(new_stroke->colorname[0] != '\0');
new_stroke->palcolor = BLI_ghash_lookup(data->new_colors, new_stroke->colorname);
-
+
BLI_assert(new_stroke->palcolor != NULL);
BLI_strncpy(new_stroke->colorname, new_stroke->palcolor->info, sizeof(new_stroke->colorname));
-
+
/* Adjust all the stroke's points, so that the strokes
* get pasted relative to where the cursor is now
*/
@@ -896,7 +901,7 @@ static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso)
/* 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;
@@ -911,31 +916,31 @@ 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->brush->flag & GP_EDITBRUSH_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->brush->size, sco);
-
+
/* adjust the amount of displacement to apply */
mul_v3_v3fl(delta, gso->dvec, influence);
-
+
/* apply */
add_v3_v3(&pt->x, delta);
}
@@ -967,7 +972,7 @@ static bool gpsculpt_brush_apply_clone(bContext *C, tGP_BrushEditData *gso)
gp_brush_clone_add(C, gso);
}
}
-
+
return true;
}
@@ -984,8 +989,8 @@ static void gp_brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customda
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
+ GPU_line_smooth(true);
+ GPU_blend(true);
/* Inner Ring: Light color for action of the brush */
/* TODO: toggle between add and remove? */
@@ -998,8 +1003,8 @@ static void gp_brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customda
immUnbindProgram();
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
+ GPU_blend(false);
+ GPU_line_smooth(false);
}
}
@@ -1007,7 +1012,7 @@ static void gp_brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customda
static void gpencil_toggle_brush_cursor(bContext *C, bool enable)
{
GP_BrushEdit_Settings *gset = gpsculpt_get_settings(CTX_data_scene(C));
-
+
if (gset->paintcursor && !enable) {
/* clear cursor */
WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor);
@@ -1015,8 +1020,8 @@ static void gpencil_toggle_brush_cursor(bContext *C, bool enable)
}
else if (enable) {
/* enable cursor */
- gset->paintcursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- NULL,
+ gset->paintcursor = WM_paint_cursor_activate(CTX_wm_manager(C),
+ NULL,
gp_brush_drawcursor, NULL);
}
}
@@ -1029,16 +1034,16 @@ static void gpsculpt_brush_header_set(bContext *C, tGP_BrushEditData *gso)
{
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);
-
+
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_area_headerprint(CTX_wm_area(C), str);
+
+ ED_workspace_status_text(C, str);
}
/* ************************************************ */
@@ -1050,36 +1055,40 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
tGP_BrushEditData *gso;
-
+
/* setup operator data */
gso = MEM_callocN(sizeof(tGP_BrushEditData), "tGP_BrushEditData");
op->customdata = gso;
-
+
/* store state */
gso->settings = gpsculpt_get_settings(scene);
gso->brush = gpsculpt_get_brush(scene);
-
+
gso->brush_type = gso->settings->brushtype;
-
-
+
+ /* Random generator, only init once. */
+ uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
+ rng_seed ^= GET_UINT_FROM_POINTER(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() */
-
+
gso->scene = scene;
-
+
gso->sa = CTX_wm_area(C);
gso->ar = CTX_wm_region(C);
-
+
/* initialise custom data for brushes */
switch (gso->brush_type) {
case GP_EDITBRUSH_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)) {
@@ -1087,12 +1096,12 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op)
break;
}
}
-
+
if (found == false) {
/* STOP HERE! Nothing to paste! */
- BKE_report(op->reports, RPT_ERROR,
+ 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;
@@ -1103,30 +1112,30 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op)
}
break;
}
-
+
case GP_EDITBRUSH_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);
gpencil_toggle_brush_cursor(C, true);
-
+
return true;
}
@@ -1134,7 +1143,7 @@ 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_EDITBRUSH_TYPE_GRAB:
@@ -1146,28 +1155,32 @@ static void gpsculpt_brush_exit(bContext *C, wmOperator *op)
BLI_ghash_free(gso->stroke_customdata, NULL, gp_brush_grab_stroke_free);
break;
}
-
+
case GP_EDITBRUSH_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_area_headerprint(CTX_wm_area(C), NULL);
+ ED_workspace_status_text(C, NULL);
WM_cursor_modal_restore(win);
gpencil_toggle_brush_cursor(C, false);
-
+
/* free operator data */
MEM_freeN(gso);
op->customdata = NULL;
@@ -1188,18 +1201,18 @@ static void gpsculpt_brush_init_stroke(tGP_BrushEditData *gso)
bGPdata *gpd = gso->gpd;
bGPDlayer *gpl;
int cfra = CFRA;
-
+
/* only try to add a new frame if this is the first stroke, or the frame has changed */
if ((gpd == NULL) || (cfra == 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
+
+ /* 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...
*/
@@ -1209,7 +1222,7 @@ static void gpsculpt_brush_init_stroke(tGP_BrushEditData *gso)
}
}
}
-
+
/* save off new current frame, so that next update works fine */
gso->cfra = cfra;
}
@@ -1224,7 +1237,7 @@ static bool gpsculpt_brush_do_stroke(
GP_SpaceConversion *gsc = &gso->gsc;
rcti *rect = &gso->brush_rect;
const int radius = gso->brush->size;
-
+
bGPDspoint *pt1, *pt2;
int pc1[2] = {0};
int pc2[2] = {0};
@@ -1241,7 +1254,7 @@ static bool gpsculpt_brush_do_stroke(
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 */
@@ -1252,14 +1265,14 @@ static bool gpsculpt_brush_do_stroke(
}
}
else {
- /* Loop over the points in the stroke, checking for intersections
+ /* 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_BRUSHEDIT_FLAG_SELECT_MASK) {
if (!(pt1->flag & GP_SPOINT_SELECT) && !(pt2->flag & GP_SPOINT_SELECT)) {
@@ -1292,14 +1305,14 @@ static bool gpsculpt_brush_do_stroke(
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.
- *
+ * 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!
@@ -1311,13 +1324,13 @@ static bool gpsculpt_brush_do_stroke(
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)
+ * previous step (but wasn't added then, to avoid double-ups)
*/
changed |= apply(gso, gps, i, radius, pc1);
include_last = false;
@@ -1325,7 +1338,7 @@ static bool gpsculpt_brush_do_stroke(
}
}
}
-
+
return changed;
}
@@ -1333,7 +1346,7 @@ static bool gpsculpt_brush_do_stroke(
static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso)
{
bool changed = false;
-
+
/* Calculate brush-specific data which applies equally to all points */
switch (gso->brush_type) {
case GP_EDITBRUSH_TYPE_GRAB: /* Grab points */
@@ -1343,7 +1356,7 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso)
gp_brush_grab_calc_dvec(gso);
break;
}
-
+
case GP_EDITBRUSH_TYPE_PINCH: /* Pinch points */
case GP_EDITBRUSH_TYPE_TWIST: /* Twist points around midpoint */
{
@@ -1351,19 +1364,19 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso)
gp_brush_calc_midpoint(gso);
break;
}
-
+
case GP_EDITBRUSH_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 */
float diff_mat[4][4];
bool parented = false;
@@ -1373,7 +1386,7 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso)
bGPDframe *gpf = gpl->actframe;
if (gpf == NULL)
continue;
-
+
/* calculate difference matrix if parent object */
if (gpl->parent != NULL) {
ED_gpencil_parent_location(gpl, diff_mat);
@@ -1382,7 +1395,7 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso)
else {
parented = false;
}
-
+
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)
@@ -1477,34 +1490,34 @@ static void gpsculpt_brush_apply(bContext *C, wmOperator *op, PointerRNA *itempt
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_EDITBRUSH_FLAG_INVERT;
else
gso->flag &= ~GP_EDITBRUSH_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_EDITBRUSH_TYPE_CLONE) {
changed = gpsculpt_brush_apply_clone(C, gso);
@@ -1512,13 +1525,13 @@ static void gpsculpt_brush_apply(bContext *C, wmOperator *op, PointerRNA *itempt
else {
changed = gpsculpt_brush_apply_standard(C, gso);
}
-
-
+
+
/* Updates */
if (changed) {
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];
@@ -1535,24 +1548,24 @@ static void gpsculpt_brush_apply_event(bContext *C, wmOperator *op, const wmEven
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
*/
@@ -1564,7 +1577,7 @@ static void gpsculpt_brush_apply_event(bContext *C, wmOperator *op, const wmEven
else {
RNA_float_set(&itemptr, "pressure", 1.0f);
}
-
+
/* apply */
gpsculpt_brush_apply(C, op, &itemptr);
}
@@ -1574,15 +1587,15 @@ static int gpsculpt_brush_exec(bContext *C, wmOperator *op)
{
if (!gpsculpt_brush_init(C, op))
return OPERATOR_CANCELLED;
-
- RNA_BEGIN(op->ptr, itemptr, "stroke")
+
+ RNA_BEGIN(op->ptr, itemptr, "stroke")
{
gpsculpt_brush_apply(C, op, &itemptr);
}
RNA_END;
-
+
gpsculpt_brush_exit(C, op);
-
+
return OPERATOR_FINISHED;
}
@@ -1594,13 +1607,13 @@ static int gpsculpt_brush_invoke(bContext *C, wmOperator *op, const wmEvent *eve
const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input");
bool needs_timer = false;
float brush_rate = 0.0f;
-
+
/* 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... */
@@ -1608,7 +1621,7 @@ static int gpsculpt_brush_invoke(bContext *C, wmOperator *op, const wmEvent *eve
brush_rate = 0.01f; // XXX: hardcoded
needs_timer = true;
break;
-
+
case GP_EDITBRUSH_TYPE_STRENGTH:
brush_rate = 0.01f; // XXX: hardcoded
needs_timer = true;
@@ -1618,39 +1631,39 @@ static int gpsculpt_brush_invoke(bContext *C, wmOperator *op, const wmEvent *eve
brush_rate = 0.001f; // XXX: hardcoded
needs_timer = true;
break;
-
+
case GP_EDITBRUSH_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;
}
@@ -1661,7 +1674,7 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even
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 */
@@ -1671,11 +1684,11 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even
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) {
@@ -1684,7 +1697,7 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even
gso->timerTick = false;
}
break;
-
+
/* Adjust brush settings */
/* FIXME: Step increments and modifier keys are hardcoded here! */
case WHEELUPMOUSE:
@@ -1699,12 +1712,12 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even
gso->brush->size += 3;
CLAMP_MAX(gso->brush->size, 300);
}
-
+
redraw_region = true;
redraw_toolsettings = true;
break;
-
- case WHEELDOWNMOUSE:
+
+ case WHEELDOWNMOUSE:
case PADMINUS:
if (event->shift) {
/* decrease strength */
@@ -1716,11 +1729,11 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even
gso->brush->size -= 3;
CLAMP_MIN(gso->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);
@@ -1731,12 +1744,12 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even
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:
@@ -1748,34 +1761,34 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even
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:
@@ -1790,12 +1803,12 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even
gso->brush->size += 3;
CLAMP_MAX(gso->brush->size, 300);
}
-
+
redraw_region = true;
redraw_toolsettings = true;
break;
-
- case WHEELDOWNMOUSE:
+
+ case WHEELDOWNMOUSE:
case PADMINUS:
if (event->shift) {
/* decrease strength */
@@ -1807,41 +1820,41 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even
gso->brush->size -= 3;
CLAMP_MIN(gso->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 Manipulations - 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) {
WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
}
-
+
return OPERATOR_RUNNING_MODAL;
}
@@ -1854,7 +1867,7 @@ void GPENCIL_OT_brush_paint(wmOperatorType *ot)
ot->name = "Stroke Sculpt";
ot->idname = "GPENCIL_OT_brush_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;
@@ -1869,7 +1882,7 @@ void GPENCIL_OT_brush_paint(wmOperatorType *ot)
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_SKIP_SAVE);
diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c
index 6dfe17f227a..d2301337c0e 100644
--- a/source/blender/editors/gpencil/gpencil_convert.c
+++ b/source/blender/editors/gpencil/gpencil_convert.c
@@ -48,6 +48,7 @@
#include "DNA_anim_types.h"
#include "DNA_curve_types.h"
+#include "DNA_group_types.h"
#include "DNA_object_types.h"
#include "DNA_node_types.h"
#include "DNA_scene_types.h"
@@ -65,6 +66,7 @@
#include "BKE_gpencil.h"
#include "BKE_layer.h"
#include "BKE_library.h"
+#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_scene.h"
@@ -178,7 +180,7 @@ static void gp_strokepoint_convertcoords(
else {
const float *fp = ED_view3d_cursor3d_get(scene, v3d)->location;
float mvalf[2];
-
+
/* get screen coordinate */
if (gps->flag & GP_STROKE_2DSPACE) {
View2D *v2d = &ar->v2d;
@@ -194,7 +196,7 @@ static void gp_strokepoint_convertcoords(
mvalf[1] = (float)pt->y / 100.0f * ar->winy;
}
}
-
+
ED_view3d_win_to_3d(v3d, ar, fp, mvalf, p3d);
}
}
@@ -210,19 +212,19 @@ typedef struct tGpTimingData {
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;
@@ -233,9 +235,9 @@ 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__);
@@ -243,7 +245,7 @@ static void gp_timing_data_set_nbr(tGpTimingData *gtd, const int nbr)
memcpy(gtd->dists, tmp, sizeof(float) * gtd->num_points);
MEM_freeN(tmp);
}
-
+
/* times */
tmp = gtd->times;
gtd->times = MEM_callocN(sizeof(float) * nbr, __func__);
@@ -251,7 +253,7 @@ static void gp_timing_data_set_nbr(tGpTimingData *gtd, const int nbr)
memcpy(gtd->times, tmp, sizeof(float) * gtd->num_points);
MEM_freeN(tmp);
}
-
+
gtd->num_points = nbr;
}
@@ -261,7 +263,7 @@ static void gp_timing_data_add_point(tGpTimingData *gtd, const double stroke_ini
{
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;
@@ -271,18 +273,18 @@ static void gp_timing_data_add_point(tGpTimingData *gtd, const double stroke_ini
/* 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++;
}
@@ -297,7 +299,7 @@ static int gp_find_end_of_stroke_idx(tGpTimingData *gtd, RNG *rng, const int idx
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];
@@ -316,16 +318,16 @@ static int gp_find_end_of_stroke_idx(tGpTimingData *gtd, RNG *rng, const int idx
}
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);
@@ -340,7 +342,7 @@ static int gp_find_end_of_stroke_idx(tGpTimingData *gtd, RNG *rng, const int idx
break;
}
}
-
+
return j - 1;
}
@@ -348,7 +350,7 @@ static void gp_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, RNG *rn
{
int i;
float delta_time = 0.0f;
-
+
for (i = 0; i < gtd->num_points; i++) {
if (gtd->times[i] < 0 && i) {
(*nbr_gaps)++;
@@ -361,7 +363,7 @@ static void gp_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, RNG *rn
}
}
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) {
@@ -372,24 +374,24 @@ static void gp_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, RNG *rn
}
}
-static void gp_stroke_path_animation_add_keyframes(ReportList *reports, PointerRNA ptr, PropertyRNA *prop, FCurve *fcu,
+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!
@@ -405,11 +407,11 @@ static void gp_stroke_path_animation_add_keyframes(ReportList *reports, PointerR
/* 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
@@ -421,7 +423,7 @@ static void gp_stroke_path_animation_add_keyframes(ReportList *reports, PointerR
if ((cfra - last_valid_time) < MIN_TIME_DELTA) {
cfra = last_valid_time + MIN_TIME_DELTA;
}
- insert_keyframe_direct(reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
+ insert_keyframe_direct(depsgraph, reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
last_valid_time = cfra;
}
else if (G.debug & G_DEBUG) {
@@ -433,7 +435,7 @@ static void gp_stroke_path_animation_add_keyframes(ReportList *reports, PointerR
if ((cfra - last_valid_time) < MIN_TIME_DELTA) {
cfra = last_valid_time + MIN_TIME_DELTA;
}
- insert_keyframe_direct(reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
+ insert_keyframe_direct(depsgraph, reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
last_valid_time = cfra;
}
else {
@@ -441,7 +443,7 @@ static void gp_stroke_path_animation_add_keyframes(ReportList *reports, PointerR
* 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(reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_BREAKDOWN, INSERTKEY_FAST);
+ insert_keyframe_direct(depsgraph, reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_BREAKDOWN, INSERTKEY_FAST);
last_valid_time = cfra;
}
else if (G.debug & G_DEBUG) {
@@ -454,49 +456,51 @@ static void gp_stroke_path_animation_add_keyframes(ReportList *reports, PointerR
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((ID *)cu, true);
+ act = verify_adt_action(bmain, (ID *)cu, true);
fcu = verify_fcurve(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(reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
-
+ insert_keyframe_direct(depsgraph, reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
+
cu->ctime = cu->pathlen;
if (gtd->realtime) {
cfra += (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */
@@ -504,41 +508,41 @@ static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu
else {
cfra = (float)gtd->end_frame;
}
- insert_keyframe_direct(reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
+ insert_keyframe_direct(depsgraph, reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, 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(reports, ptr, prop, fcu, cu, gtd, rng, time_range,
+
+ 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++) {
@@ -546,9 +550,9 @@ static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu
}
printf("\n\n");
}
-
+
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
-
+
/* send updates */
DEG_id_tag_update(&cu->id, 0);
}
@@ -568,7 +572,7 @@ static void gp_stroke_to_path_add_point(tGpTimingData *gtd, BPoint *bp, const fl
{
copy_v3_v3(bp->vec, p);
bp->vec[3] = 1.0f;
-
+
/* set settings */
bp->f1 = SELECT;
bp->radius = width * rad_fac;
@@ -580,7 +584,7 @@ static void gp_stroke_to_path_add_point(tGpTimingData *gtd, BPoint *bp, const fl
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));
@@ -597,7 +601,7 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
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;
@@ -609,7 +613,7 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
}
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! */
@@ -618,16 +622,16 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
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
@@ -640,16 +644,16 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
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, gpl, gps, gps->points, p, subrect);
if (prev_bp) {
@@ -668,7 +672,7 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
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) {
@@ -686,13 +690,13 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
}
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, gpl, gps, gps->points, p, subrect);
if (gps->totpoints > 1) {
gp_strokepoint_convertcoords(C, gpl, gps, gps->points + 1, next_p, subrect);
@@ -710,14 +714,14 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
* 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;
@@ -725,20 +729,20 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
{
float p[3];
float width = pt->pressure * (gps->thickness + gpl->thickness) * WIDTH_CORR_FAC;
-
+
/* get coordinates to add at */
gp_strokepoint_convertcoords(C, 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) {
@@ -754,7 +758,7 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
/* 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);
@@ -762,7 +766,7 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
if (curnu) {
*curnu = nu;
}
-
+
BKE_nurb_knot_calc_u(nu);
}
@@ -777,7 +781,7 @@ static void gp_stroke_to_bezier_add_point(tGpTimingData *gtd, BezTriple *bezt,
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;
@@ -790,7 +794,7 @@ static void gp_stroke_to_bezier_add_point(tGpTimingData *gtd, BezTriple *bezt,
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));
@@ -808,7 +812,7 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
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;
@@ -820,22 +824,22 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
}
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) {
@@ -847,11 +851,11 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
gp_strokepoint_convertcoords(C, 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];
@@ -859,7 +863,7 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
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
@@ -872,14 +876,14 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
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);
@@ -894,7 +898,7 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
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) {
@@ -909,25 +913,25 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
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);
}
@@ -935,7 +939,7 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
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) {
@@ -952,51 +956,51 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
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->thickness) * 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, 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) {
@@ -1009,11 +1013,11 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
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);
@@ -1021,10 +1025,10 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
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);
}
@@ -1054,7 +1058,7 @@ static void gp_stroke_finalize_curve_endpoints(Curve *cu)
bp[i].weight = bp[i].radius = 0.0f;
}
}
-
+
/* end */
nu = cu->nurb.last;
i = nu->pntsu - 1;
@@ -1078,13 +1082,13 @@ static void gp_stroke_norm_curve_weights(Curve *cu, const float minmax_weights[2
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;
@@ -1105,10 +1109,10 @@ 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);
@@ -1117,7 +1121,7 @@ static int gp_camera_view_subrect(bContext *C, rctf *subrect)
return 1;
}
}
-
+
return 0;
}
@@ -1128,7 +1132,7 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
struct Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- SceneCollection *sc = CTX_data_scene_collection(C);
+ Collection *collection = CTX_data_collection(C);
bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0);
bGPDstroke *gps, *prev_gps = NULL;
Object *ob;
@@ -1136,56 +1140,56 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
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(&scene->id, sc, ob);
+ BKE_collection_object_add(bmain, collection, ob);
base_new = BKE_view_layer_base_find(view_layer, ob);
-
+
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, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch,
@@ -1202,26 +1206,26 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
}
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);
@@ -1241,17 +1245,17 @@ static bool gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOpe
double base_time, cur_time, prev_time = -1.0;
int i;
bool valid = true;
-
+
if (!gpl || !(gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0)) || !(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;
@@ -1264,12 +1268,12 @@ static bool gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOpe
}
prev_time = cur_time;
}
-
+
if (!valid) {
break;
}
} while ((gps = gps->next));
-
+
if (op) {
RNA_boolean_set(op->ptr, "use_timing_data", valid);
}
@@ -1281,7 +1285,7 @@ static void gp_convert_set_end_frame(struct Main *UNUSED(main), struct Scene *UN
{
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);
}
@@ -1295,7 +1299,7 @@ static int gp_convert_poll(bContext *C)
ScrArea *sa = CTX_wm_area(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(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!
*/
@@ -1318,19 +1322,19 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op)
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)) {
@@ -1340,7 +1344,7 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op)
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");
@@ -1355,10 +1359,10 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op)
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);
@@ -1368,11 +1372,12 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op)
MEM_freeN(gtd.times);
gtd.times = NULL;
}
-
+
/* notifiers */
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
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;
}
@@ -1386,7 +1391,7 @@ static bool gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
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") ||
@@ -1395,16 +1400,16 @@ static bool gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
{
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") ||
@@ -1412,31 +1417,31 @@ static bool gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
{
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;
}
@@ -1446,9 +1451,9 @@ static void gp_convert_ui(bContext *C, wmOperator *op)
uiLayout *layout = op->layout;
wmWindowManager *wm = CTX_wm_manager(C);
PointerRNA ptr;
-
+
RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
-
+
/* Main auto-draw call */
uiDefAutoButsRNA(layout, &ptr, gp_convert_draw_check_prop, UI_BUT_LABEL_ALIGN_NONE, false);
}
@@ -1456,35 +1461,35 @@ static void gp_convert_ui(bContext *C, wmOperator *op)
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->ui = gp_convert_ui;
-
+
/* 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", true, "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",
@@ -1494,7 +1499,7 @@ void GPENCIL_OT_convert(wmOperatorType *ot)
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);
@@ -1502,7 +1507,7 @@ void GPENCIL_OT_convert(wmOperatorType *ot)
"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)");
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index 9d183222c2d..9f437f28f0f 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -52,14 +52,15 @@
#include "DNA_view3d_types.h"
#include "DNA_gpencil_types.h"
+#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_gpencil.h"
#include "BKE_library.h"
+#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
-#include "BKE_colortools.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -83,6 +84,7 @@
/* add new datablock - wrapper around API */
static int gp_data_add_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
ToolSettings *ts = CTX_data_tool_settings(C);
@@ -93,9 +95,9 @@ static int gp_data_add_exec(bContext *C, wmOperator *op)
else {
/* decrement user count and add new datablock */
bGPdata *gpd = (*gpd_ptr);
-
+
id_us_min(&gpd->id);
- *gpd_ptr = BKE_gpencil_data_addnew(DATA_("GPencil"));
+ *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil"));
/* if not exist brushes, create a new set */
if (ts) {
@@ -106,10 +108,10 @@ static int gp_data_add_exec(bContext *C, wmOperator *op)
}
}
-
+
/* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -120,7 +122,7 @@ void GPENCIL_OT_data_add(wmOperatorType *ot)
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_add_poll;
@@ -132,7 +134,7 @@ void GPENCIL_OT_data_add(wmOperatorType *ot)
static int gp_data_unlink_poll(bContext *C)
{
bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
-
+
/* if we have access to some active data, make sure there's a datablock before enabling this */
return (gpd_ptr && *gpd_ptr);
}
@@ -142,7 +144,7 @@ static int gp_data_unlink_poll(bContext *C)
static int gp_data_unlink_exec(bContext *C, wmOperator *op)
{
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;
@@ -154,10 +156,10 @@ static int gp_data_unlink_exec(bContext *C, wmOperator *op)
id_us_min(&gpd->id);
*gpd_ptr = NULL;
}
-
+
/* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -168,7 +170,7 @@ void GPENCIL_OT_data_unlink(wmOperatorType *ot)
ot->idname = "GPENCIL_OT_data_unlink";
ot->description = "Unlink active Grease Pencil data-block";
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* callbacks */
ot->exec = gp_data_unlink_exec;
ot->poll = gp_data_unlink_poll;
@@ -183,6 +185,7 @@ void GPENCIL_OT_data_unlink(wmOperatorType *ot)
/* add new layer - wrapper around API */
static int gp_layer_add_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
ToolSettings *ts = CTX_data_tool_settings(C);
@@ -192,8 +195,8 @@ static int gp_layer_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
if (*gpd_ptr == NULL)
- *gpd_ptr = BKE_gpencil_data_addnew(DATA_("GPencil"));
-
+ *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil"));
+
/* if not exist brushes, create a new set */
if (ts) {
if (BLI_listbase_is_empty(&ts->gp_brushes)) {
@@ -204,10 +207,10 @@ static int gp_layer_add_exec(bContext *C, wmOperator *op)
/* add new layer now */
BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("GP_Layer"), true);
-
+
/* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -217,9 +220,9 @@ void GPENCIL_OT_layer_add(wmOperatorType *ot)
ot->name = "Add New Layer";
ot->idname = "GPENCIL_OT_layer_add";
ot->description = "Add new Grease Pencil layer for the active Grease Pencil data-block";
-
+
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* callbacks */
ot->exec = gp_layer_add_exec;
ot->poll = gp_add_poll;
@@ -231,16 +234,16 @@ 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);
-
+
/* 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;
}
-
+
/* 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
@@ -249,13 +252,13 @@ static int gp_layer_remove_exec(bContext *C, wmOperator *op)
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);
-
+
/* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -265,9 +268,9 @@ void GPENCIL_OT_layer_remove(wmOperatorType *ot)
ot->name = "Remove Layer";
ot->idname = "GPENCIL_OT_layer_remove";
ot->description = "Remove active Grease Pencil layer";
-
+
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* callbacks */
ot->exec = gp_layer_remove_exec;
ot->poll = gp_active_layer_poll;
@@ -284,18 +287,18 @@ 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);
-
+
int direction = RNA_enum_get(op->ptr, "type");
-
+
/* 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)) {
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
-
+
return OPERATOR_FINISHED;
}
@@ -306,19 +309,19 @@ void GPENCIL_OT_layer_move(wmOperatorType *ot)
{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";
-
+
/* api callbacks */
ot->exec = gp_layer_move_exec;
ot->poll = gp_active_layer_poll;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
ot->prop = RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
}
@@ -329,22 +332,22 @@ 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;
-
+
/* 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);
-
+
/* 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 */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -354,11 +357,11 @@ void GPENCIL_OT_layer_duplicate(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -370,14 +373,14 @@ 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");
-
+
/* sanity checks */
if (ELEM(NULL, gpd, layer))
return OPERATOR_CANCELLED;
-
+
if (unselected) {
bGPDlayer *gpl;
-
+
/* hide unselected */
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
if (gpl != layer) {
@@ -389,10 +392,10 @@ static int gp_hide_exec(bContext *C, wmOperator *op)
/* hide selected/active */
layer->flag |= GP_LAYER_HIDE;
}
-
+
/* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -402,14 +405,14 @@ void GPENCIL_OT_hide(wmOperatorType *ot)
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 */
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* props */
RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected layers");
}
@@ -452,7 +455,7 @@ static int gp_reveal_exec(bContext *C, wmOperator *op)
/* sanity checks */
if (gpd == NULL)
return OPERATOR_CANCELLED;
-
+
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
if (gpl->flag & GP_LAYER_HIDE) {
@@ -476,10 +479,10 @@ static int gp_reveal_exec(bContext *C, wmOperator *op)
}
}
}
-
+
/* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -489,11 +492,11 @@ void GPENCIL_OT_reveal(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -507,19 +510,19 @@ static int gp_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
bGPDlayer *gpl;
-
+
/* sanity checks */
if (gpd == NULL)
return OPERATOR_CANCELLED;
-
+
/* make all layers non-editable */
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
gpl->flag |= GP_LAYER_LOCKED;
}
-
+
/* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -529,11 +532,11 @@ void GPENCIL_OT_lock_all(wmOperatorType *ot)
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 */
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -544,19 +547,19 @@ static int gp_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
bGPDlayer *gpl;
-
+
/* sanity checks */
if (gpd == NULL)
return OPERATOR_CANCELLED;
-
+
/* make all layers editable again */
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
gpl->flag &= ~GP_LAYER_LOCKED;
}
-
+
/* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -566,11 +569,11 @@ void GPENCIL_OT_unlock_all(wmOperatorType *ot)
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 */
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -584,21 +587,21 @@ static int gp_isolate_layer_exec(bContext *C, wmOperator *op)
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
*/
@@ -607,7 +610,7 @@ static int gp_isolate_layer_exec(bContext *C, wmOperator *op)
break;
}
}
-
+
/* Set/Clear flags as appropriate */
/* TODO: Include onionskinning on this list? */
if (isolate) {
@@ -625,10 +628,10 @@ static int gp_isolate_layer_exec(bContext *C, wmOperator *op)
gpl->flag &= ~flags;
}
}
-
+
/* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -638,14 +641,14 @@ void GPENCIL_OT_layer_isolate(wmOperatorType *ot)
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;
-
+
/* 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");
@@ -712,13 +715,13 @@ static int gp_layer_change_invoke(bContext *C, wmOperator *op, const wmEvent *UN
{
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);
-
+
return OPERATOR_INTERFACE;
}
@@ -727,7 +730,7 @@ 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");
-
+
/* Get layer or create new one */
if (layer_num == -1) {
/* Create layer */
@@ -736,19 +739,19 @@ static int gp_layer_change_exec(bContext *C, wmOperator *op)
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;
}
}
-
+
/* Set active layer */
BKE_gpencil_layer_setactive(gpd, gpl);
-
+
/* updates */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -758,15 +761,15 @@ void GPENCIL_OT_layer_change(wmOperatorType *ot)
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;
-
+
/* 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);
@@ -1376,6 +1379,7 @@ void GPENCIL_OT_brush_select(wmOperatorType *ot)
/* add new palette - wrapper around API */
static int gp_palette_add_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
/* if there's no existing Grease-Pencil data there, add some */
@@ -1384,7 +1388,7 @@ static int gp_palette_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
if (*gpd_ptr == NULL)
- *gpd_ptr = BKE_gpencil_data_addnew(DATA_("GPencil"));
+ *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil"));
/* add new palette now */
BKE_gpencil_palette_addnew(*gpd_ptr, DATA_("GP_Palette"), true);
@@ -1588,6 +1592,7 @@ void GPENCIL_OT_palette_lock_layer(wmOperatorType *ot)
/* add new palette - wrapper around API */
static int gp_palettecolor_add_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
/* if there's no existing Grease-Pencil data there, add some */
@@ -1596,7 +1601,7 @@ static int gp_palettecolor_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
if (*gpd_ptr == NULL)
- *gpd_ptr = BKE_gpencil_data_addnew(DATA_("GPencil"));
+ *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil"));
/* verify palette */
bGPDpalette *palette = BKE_gpencil_palette_getactive(*gpd_ptr);
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index d2f291f69fb..45caadf3742 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -57,6 +57,7 @@
#include "BKE_context.h"
#include "BKE_gpencil.h"
#include "BKE_library.h"
+#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_screen.h"
@@ -93,10 +94,10 @@ static int gpencil_editmode_toggle_poll(bContext *C)
static int gpencil_editmode_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
-
+
if (gpd == NULL)
return OPERATOR_CANCELLED;
-
+
/* Just toggle editmode flag... */
gpd->flag ^= GP_DATA_STROKE_EDITMODE;
/* recalculate parent matrix */
@@ -107,7 +108,7 @@ static int gpencil_editmode_toggle_exec(bContext *C, wmOperator *UNUSED(op))
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;
}
@@ -117,11 +118,11 @@ void GPENCIL_OT_editmode_toggle(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
}
@@ -182,10 +183,10 @@ static void gp_duplicate_points(const bGPDstroke *gps, ListBase *new_strokes, co
{
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
@@ -200,7 +201,7 @@ static void gp_duplicate_points(const bGPDstroke *gps, ListBase *new_strokes, co
}
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
@@ -212,29 +213,29 @@ static void gp_duplicate_points(const bGPDstroke *gps, ListBase *new_strokes, co
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);
BLI_strncpy(gpsd->tmp_layerinfo, layername, sizeof(gpsd->tmp_layerinfo)); /* saves original layer name */
-
+
/* initialize triangle memory - will be calculated on next redraw */
gpsd->triangles = NULL;
gpsd->flag |= GP_STROKE_RECALC_CACHES;
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;
-
+
/* add to temp buffer */
gpsd->next = gpsd->prev = NULL;
BLI_addtail(new_strokes, gpsd);
-
+
/* cleanup + reset for next */
start_idx = -1;
}
@@ -245,12 +246,12 @@ static void gp_duplicate_points(const bGPDstroke *gps, ListBase *new_strokes, co
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;
}
-
+
/* for each visible (and editable) layer's selected strokes,
* copy the strokes into a temporary buffer, then append
* once all done
@@ -260,22 +261,22 @@ static int gp_duplicate_exec(bContext *C, wmOperator *op)
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->tmp_layerinfo, gpl->info, sizeof(gpsd->tmp_layerinfo));
@@ -284,7 +285,7 @@ static int gp_duplicate_exec(bContext *C, wmOperator *op)
/* triangle information - will be calculated on next redraw */
gpsd->flag |= GP_STROKE_RECALC_CACHES;
gpsd->triangles = NULL;
-
+
/* add to temp buffer */
gpsd->next = gpsd->prev = NULL;
BLI_addtail(&new_strokes, gpsd);
@@ -293,23 +294,23 @@ static int gp_duplicate_exec(bContext *C, wmOperator *op)
/* 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 */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -319,11 +320,11 @@ void GPENCIL_OT_duplicate(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -352,7 +353,7 @@ static GHash *gp_strokes_copypastebuf_colors = NULL;
void ED_gpencil_strokes_copybuf_free(void)
{
bGPDstroke *gps, *gpsn;
-
+
/* Free the palettes buffer
* NOTE: This is done before the strokes so that the name ptrs (keys) are still safe
*/
@@ -360,17 +361,17 @@ void ED_gpencil_strokes_copybuf_free(void)
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->triangles) MEM_freeN(gps->triangles);
-
+
BLI_freelinkN(&gp_strokes_copypastebuf, gps);
}
-
+
gp_strokes_copypastebuf.first = gp_strokes_copypastebuf.last = NULL;
}
@@ -381,18 +382,18 @@ GHash *gp_copybuf_validate_colormap(bGPdata *gpd)
{
GHash *new_colors = BLI_ghash_str_new("GPencil Paste Dst Colors");
GHashIterator gh_iter;
-
+
/* If there's no active palette yet (i.e. new datablock), add one */
bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
if (palette == NULL) {
palette = BKE_gpencil_palette_addnew(gpd, "Pasted Palette", true);
}
-
+
/* For each color, figure out what to map to... */
GHASH_ITER(gh_iter, gp_strokes_copypastebuf_colors) {
bGPDpalettecolor *palcolor;
char *name = BLI_ghashIterator_getKey(&gh_iter);
-
+
/* Look for existing color to map to */
/* XXX: What to do if same name but different color? Behaviour here should depend on a property? */
palcolor = BKE_gpencil_palettecolor_getbyname(palette, name);
@@ -400,17 +401,17 @@ GHash *gp_copybuf_validate_colormap(bGPdata *gpd)
/* Doesn't Exist - Create new matching color for this palette */
/* XXX: This still doesn't fix the pasting across file boundaries problem... */
bGPDpalettecolor *src_color = BLI_ghashIterator_getValue(&gh_iter);
-
+
palcolor = MEM_dupallocN(src_color);
BLI_addtail(&palette->colors, palcolor);
-
+
BLI_uniquename(&palette->colors, palcolor, DATA_("GP Color"), '.', offsetof(bGPDpalettecolor, info), sizeof(palcolor->info));
}
-
+
/* Store this mapping (for use later when pasting) */
BLI_ghash_insert(new_colors, name, palcolor);
}
-
+
return new_colors;
}
@@ -420,15 +421,15 @@ GHash *gp_copybuf_validate_colormap(bGPdata *gpd)
static int gp_strokes_copy_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;
}
-
+
/* 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
@@ -437,31 +438,31 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op)
{
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->tmp_layerinfo, gpl->info, sizeof(gpsd->tmp_layerinfo)); /* saves original layer name */
gpsd->points = MEM_dupallocN(gps->points);
-
+
/* triangles cache - will be recalculated on next redraw */
gpsd->flag |= GP_STROKE_RECALC_CACHES;
gpsd->tot_triangles = 0;
gpsd->triangles = NULL;
-
+
/* add to temp buffer */
gpsd->next = gpsd->prev = NULL;
BLI_addtail(&gp_strokes_copypastebuf, gpsd);
@@ -474,26 +475,26 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op)
}
}
CTX_DATA_END;
-
+
/* Build up hash of colors used in these strokes, making copies of these to protect against dangling pointers */
if (gp_strokes_copypastebuf.first) {
gp_strokes_copypastebuf_colors = BLI_ghash_str_new("GPencil CopyBuf Colors");
-
+
for (bGPDstroke *gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) {
if (ED_gpencil_stroke_can_use(C, gps)) {
if (BLI_ghash_haskey(gp_strokes_copypastebuf_colors, gps->colorname) == false) {
bGPDpalettecolor *color = MEM_dupallocN(gps->palcolor);
-
+
BLI_ghash_insert(gp_strokes_copypastebuf_colors, gps->colorname, color);
gps->palcolor = color;
}
}
}
}
-
+
/* 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;
}
@@ -504,11 +505,11 @@ void GPENCIL_OT_copy(wmOperatorType *ot)
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;
-
+
/* flags */
//ot->flag = OPTYPE_REGISTER;
}
@@ -537,10 +538,10 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
bGPdata *gpd = ED_gpencil_data_get_active(C);
bGPDlayer *gpl = CTX_data_active_gpencil_layer(C); /* only use active for copy merge */
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");
@@ -562,14 +563,14 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
/* 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
@@ -578,28 +579,28 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
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(gpd);
-
+
/* 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)) {
@@ -611,7 +612,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
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
@@ -622,33 +623,33 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
/* Create new stroke */
bGPDstroke *new_stroke = MEM_dupallocN(gps);
new_stroke->tmp_layerinfo[0] = '\0';
-
+
new_stroke->points = MEM_dupallocN(gps->points);
-
+
new_stroke->flag |= GP_STROKE_RECALC_CACHES;
new_stroke->triangles = NULL;
-
+
new_stroke->next = new_stroke->prev = NULL;
BLI_addtail(&gpf->strokes, new_stroke);
-
+
/* Fix color references */
BLI_assert(new_stroke->colorname[0] != '\0');
new_stroke->palcolor = BLI_ghash_lookup(new_colors, new_stroke->colorname);
-
+
BLI_assert(new_stroke->palcolor != NULL);
BLI_strncpy(new_stroke->colorname, new_stroke->palcolor->info, sizeof(new_stroke->colorname));
-
+
/*new_stroke->flag |= GP_STROKE_RECALC_COLOR; */
}
}
}
-
+
/* free temp data */
BLI_ghash_free(new_colors, NULL, NULL);
-
+
/* updates */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -659,19 +660,19 @@ void GPENCIL_OT_paste(wmOperatorType *ot)
{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;
-
+
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", copy_type, 0, "Type", "");
}
@@ -682,13 +683,13 @@ static int gp_move_to_layer_invoke(bContext *C, wmOperator *op, const wmEvent *U
{
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);
-
+
return OPERATOR_INTERFACE;
}
@@ -699,7 +700,7 @@ static int gp_move_to_layer_exec(bContext *C, wmOperator *op)
bGPDlayer *target_layer = NULL;
ListBase strokes = {NULL, NULL};
int layer_num = RNA_enum_get(op->ptr, "layer");
-
+
/* Get layer or create new one */
if (layer_num == -1) {
/* Create layer */
@@ -708,13 +709,13 @@ static int gp_move_to_layer_exec(bContext *C, wmOperator *op)
else {
/* Try to get layer */
target_layer = BLI_findlink(&gpd->layers, layer_num);
-
+
if (target_layer == NULL) {
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
@@ -723,19 +724,19 @@ static int gp_move_to_layer_exec(bContext *C, wmOperator *op)
{
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);
@@ -744,19 +745,19 @@ static int gp_move_to_layer_exec(bContext *C, wmOperator *op)
}
}
CTX_DATA_END;
-
+
/* Paste them all in one go */
if (strokes.first) {
Scene *scene = CTX_data_scene(C);
bGPDframe *gpf = BKE_gpencil_layer_getframe(target_layer, CFRA, true);
-
+
BLI_movelisttolist(&gpf->strokes, &strokes);
BLI_assert((strokes.first == strokes.last) && (strokes.first == NULL));
}
-
+
/* updates */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -766,15 +767,15 @@ void GPENCIL_OT_move_to_layer(wmOperatorType *ot)
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);
@@ -797,7 +798,7 @@ static int UNUSED_FUNCTION(gp_blank_frame_add_poll)(bContext *C)
else {
CTX_wm_operator_poll_msg_set(C, "Active region not set");
}
-
+
return 0;
}
@@ -814,8 +815,8 @@ static int gp_blank_frame_add_exec(bContext *C, wmOperator *op)
/* 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
+
+ /* 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)
@@ -832,15 +833,15 @@ static int gp_blank_frame_add_exec(bContext *C, wmOperator *op)
gpf->framenum += 1;
}
}
-
+
/* 2) Now add a new frame, with nothing in it */
gpl->actframe = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_NEW);
}
CTX_DATA_END;
-
+
/* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -851,11 +852,11 @@ void GPENCIL_OT_blank_frame_add(wmOperatorType *ot)
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");
@@ -867,7 +868,7 @@ static int gp_actframe_delete_poll(bContext *C)
{
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);
}
@@ -879,7 +880,7 @@ 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);
bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0);
-
+
/* if there's no existing Grease-Pencil data there, add some */
if (gpd == NULL) {
BKE_report(op->reports, RPT_ERROR, "No grease pencil data");
@@ -889,13 +890,13 @@ static int gp_actframe_delete_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "No active frame to delete");
return OPERATOR_CANCELLED;
}
-
+
/* delete it... */
BKE_gpencil_layer_delframe(gpl, gpf);
-
+
/* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -905,9 +906,9 @@ void GPENCIL_OT_active_frame_delete(wmOperatorType *ot)
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;
-
+
/* callbacks */
ot->exec = gp_actframe_delete_exec;
ot->poll = gp_actframe_delete_poll;
@@ -918,7 +919,7 @@ void GPENCIL_OT_active_frame_delete(wmOperatorType *ot)
static int gp_actframe_delete_all_poll(bContext *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
*/
@@ -929,26 +930,26 @@ static int gp_actframe_delete_all_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
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, 0);
-
+
if (gpf == NULL)
continue;
-
+
/* delete it... */
BKE_gpencil_layer_delframe(gpl, gpf);
-
+
/* we successfully modified something */
success = true;
}
CTX_DATA_END;
-
+
/* updates */
if (success) {
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
else {
@@ -963,9 +964,9 @@ void GPENCIL_OT_active_frames_delete_all(wmOperatorType *ot)
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;
-
+
/* callbacks */
ot->exec = gp_actframe_delete_all_exec;
ot->poll = gp_actframe_delete_all_poll;
@@ -988,36 +989,36 @@ typedef enum eGP_DeleteMode {
static int gp_delete_selected_strokes(bContext *C)
{
bool changed = false;
-
+
CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
{
bGPDframe *gpf = gpl->actframe;
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->triangles) MEM_freeN(gps->triangles);
BLI_freelinkN(&gpf->strokes, gps);
-
+
changed = true;
}
}
}
CTX_DATA_END;
-
+
if (changed) {
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -1033,34 +1034,34 @@ static int gp_delete_selected_strokes(bContext *C)
static int gp_dissolve_selected_points(bContext *C)
{
bool changed = false;
-
+
CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
{
bGPDframe *gpf = gpl->actframe;
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(gpl, gps) == false)
continue;
-
+
if (gps->flag & GP_STROKE_SELECT) {
bGPDspoint *pt;
int i;
-
+
int tot = gps->totpoints; /* number of points in new buffer */
-
+
/* First Pass: 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) {
@@ -1068,7 +1069,7 @@ static int gp_dissolve_selected_points(bContext *C)
tot--;
}
}
-
+
/* if no points are left, we simply delete the entire stroke */
if (tot <= 0) {
/* remove the entire stroke */
@@ -1082,35 +1083,35 @@ static int gp_dissolve_selected_points(bContext *C)
/* just copy all unselected into a smaller buffer */
bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * tot, "new gp stroke points copy");
bGPDspoint *npt = new_points;
-
+
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
if ((pt->flag & GP_SPOINT_SELECT) == 0) {
*npt = *pt;
npt++;
}
}
-
+
/* free the old buffer */
MEM_freeN(gps->points);
-
+
/* save the new buffer */
gps->points = new_points;
gps->totpoints = tot;
-
+
/* triangles cache needs to be recalculated */
gps->flag |= GP_STROKE_RECALC_CACHES;
gps->tot_triangles = 0;
-
+
/* deselect the stroke, since none of its selected points will still be selected */
gps->flag &= ~GP_STROKE_SELECT;
}
-
+
changed = true;
}
}
}
CTX_DATA_END;
-
+
if (changed) {
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -1150,10 +1151,10 @@ void gp_stroke_delete_tagged_points(bGPDframe *gpf, bGPDstroke *gps, bGPDstroke
tGPDeleteIsland *islands = MEM_callocN(sizeof(tGPDeleteIsland) * (gps->totpoints + 1) / 2, "gp_point_islands");
bool in_island = false;
int num_islands = 0;
-
+
bGPDspoint *pt;
int i;
-
+
/* First Pass: Identify start/end of islands */
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
if (pt->flag & tag_flags) {
@@ -1163,7 +1164,7 @@ void gp_stroke_delete_tagged_points(bGPDframe *gpf, bGPDstroke *gps, bGPDstroke
else {
/* unselected - start of a new island? */
int idx;
-
+
if (in_island) {
/* extend existing island */
idx = num_islands - 1;
@@ -1173,37 +1174,37 @@ void gp_stroke_delete_tagged_points(bGPDframe *gpf, bGPDstroke *gps, bGPDstroke
/* 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;
-
+
/* Create each new stroke... */
for (idx = 0; idx < num_islands; idx++) {
tGPDeleteIsland *island = &islands[idx];
bGPDstroke *new_stroke = MEM_dupallocN(gps);
-
+
/* initialize triangle memory - to be calculated on next redraw */
new_stroke->triangles = NULL;
new_stroke->flag |= GP_STROKE_RECALC_CACHES;
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;
new_stroke->points = MEM_callocN(sizeof(bGPDspoint) * new_stroke->totpoints, "gp delete stroke fragment");
-
+
/* Copy over the relevant points */
memcpy(new_stroke->points, gps->points + island->start_idx, sizeof(bGPDspoint) * new_stroke->totpoints);
-
-
- /* Each island corresponds to a new stroke. We must adjust the
+
+
+ /* 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
@@ -1215,15 +1216,15 @@ void gp_stroke_delete_tagged_points(bGPDframe *gpf, bGPDstroke *gps, bGPDstroke
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;
}
}
-
+
/* Add new stroke to the frame */
if (next_stroke) {
BLI_insertlinkbefore(&gpf->strokes, next_stroke, new_stroke);
@@ -1233,10 +1234,10 @@ void gp_stroke_delete_tagged_points(bGPDframe *gpf, bGPDstroke *gps, bGPDstroke
}
}
}
-
+
/* free islands */
MEM_freeN(islands);
-
+
/* Delete the old stroke */
MEM_freeN(gps->points);
if (gps->triangles) {
@@ -1250,40 +1251,40 @@ void gp_stroke_delete_tagged_points(bGPDframe *gpf, bGPDstroke *gps, bGPDstroke
static int gp_delete_selected_points(bContext *C)
{
bool changed = false;
-
+
CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
{
bGPDframe *gpf = gpl->actframe;
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(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);
-
+
changed = true;
}
}
}
CTX_DATA_END;
-
+
if (changed) {
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -1299,21 +1300,21 @@ static int gp_delete_exec(bContext *C, wmOperator *op)
{
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;
-
+
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;
}
-
+
return result;
}
@@ -1325,20 +1326,20 @@ void GPENCIL_OT_delete(wmOperatorType *ot)
{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");
}
@@ -1373,7 +1374,7 @@ static int gp_snap_poll(bContext *C)
{
bGPdata *gpd = CTX_data_gpencil_data(C);
ScrArea *sa = CTX_wm_area(C);
-
+
return (gpd != NULL) && ((sa != NULL) && (sa->spacetype == SPACE_VIEW3D));
}
@@ -1384,29 +1385,29 @@ 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);
const float gridf = rv3d->gridview;
-
+
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 if parent object */
if (gpl->parent != NULL) {
ED_gpencil_parent_location(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(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 */
@@ -1420,11 +1421,11 @@ static int gp_snap_to_grid(bContext *C, wmOperator *UNUSED(op))
/* 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(gpl, pt);
@@ -1434,7 +1435,7 @@ static int gp_snap_to_grid(bContext *C, wmOperator *UNUSED(op))
}
}
}
-
+
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
@@ -1445,11 +1446,11 @@ void GPENCIL_OT_snap_to_grid(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1459,28 +1460,28 @@ void GPENCIL_OT_snap_to_grid(wmOperatorType *ot)
static int gp_snap_to_cursor(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
-
+
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
-
+
const bool use_offset = RNA_boolean_get(op->ptr, "use_offset");
const float *cursor_global = ED_view3d_cursor3d_get(scene, v3d)->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 if parent object */
if (gpl->parent != NULL) {
ED_gpencil_parent_location(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;
@@ -1490,14 +1491,14 @@ static int gp_snap_to_cursor(bContext *C, wmOperator *op)
/* 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);
@@ -1515,10 +1516,10 @@ static int gp_snap_to_cursor(bContext *C, wmOperator *op)
}
}
}
-
+
}
}
-
+
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
@@ -1529,14 +1530,14 @@ void GPENCIL_OT_snap_to_cursor(wmOperatorType *ot)
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");
@@ -1547,33 +1548,33 @@ void GPENCIL_OT_snap_to_cursor(wmOperatorType *ot)
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);
-
+
float *cursor = ED_view3d_cursor3d_get(scene, v3d)->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 if parent object */
if (gpl->parent != NULL) {
ED_gpencil_parent_location(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;
@@ -1583,7 +1584,7 @@ static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op))
/* 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) {
if (gpl->parent == NULL) {
@@ -1594,18 +1595,18 @@ static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op))
/* 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_MEAN && count) {
mul_v3_fl(centroid, 1.0f / (float)count);
copy_v3_v3(cursor, centroid);
@@ -1614,7 +1615,7 @@ static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op))
mid_v3_v3v3(cursor, min, max);
}
-
+
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
@@ -1625,11 +1626,11 @@ void GPENCIL_OT_snap_cursor_to_selected(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1685,27 +1686,27 @@ static int gp_stroke_cyclical_set_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(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) {
bGPDpalettecolor *palcolor = gps->palcolor;
-
+
/* 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 (!palcolor || (palcolor->flag & PC_COLOR_HIDE) || (palcolor->flag & PC_COLOR_LOCKED))
continue;
-
+
switch (type) {
case GP_STROKE_CYCLIC_CLOSE:
/* Close all (enable) */
@@ -1726,10 +1727,10 @@ static int gp_stroke_cyclical_set_exec(bContext *C, wmOperator *op)
}
}
CTX_DATA_END;
-
+
/* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -1745,19 +1746,19 @@ void GPENCIL_OT_stroke_cyclical_set(wmOperatorType *ot)
{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", "");
}
@@ -1768,11 +1769,11 @@ void GPENCIL_OT_stroke_cyclical_set(wmOperatorType *ot)
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;
@@ -1782,7 +1783,7 @@ static void gpencil_flip_stroke(bGPDstroke *gps)
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;
@@ -1792,7 +1793,7 @@ static void gpencil_flip_stroke(bGPDstroke *gps)
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;
@@ -1802,7 +1803,7 @@ static void gpencil_flip_stroke(bGPDstroke *gps)
point->pressure = pt.pressure;
point->strength = pt.strength;
point->time = pt.time;
-
+
end--;
}
}
@@ -1812,10 +1813,10 @@ static void gpencil_stroke_copy_point(bGPDstroke *gps, bGPDspoint *point, float
float pressure, float strength, float deltatime)
{
bGPDspoint *newpoint;
-
+
gps->points = MEM_reallocN(gps->points, sizeof(bGPDspoint) * (gps->totpoints + 1));
gps->totpoints++;
-
+
newpoint = &gps->points[gps->totpoints - 1];
newpoint->x = point->x * delta[0];
newpoint->y = point->y * delta[1];
@@ -1834,28 +1835,28 @@ static void gpencil_stroke_join_strokes(bGPDstroke *gps_a, bGPDstroke *gps_b, co
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);
@@ -1863,19 +1864,19 @@ static void gpencil_stroke_join_strokes(bGPDstroke *gps_a, bGPDstroke *gps_b, co
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, 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, 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 */
@@ -1892,25 +1893,25 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op)
bGPDstroke *gps, *gpsn;
bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
bGPDpalettecolor *palcolor = BKE_gpencil_palettecolor_getactive(palette);
-
+
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)
@@ -1918,7 +1919,7 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op)
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) {
@@ -1930,10 +1931,10 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op)
if (ED_gpencil_stroke_color_use(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;
@@ -1942,7 +1943,7 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op)
}
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);
@@ -1950,7 +1951,7 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op)
new_stroke->triangles = NULL;
new_stroke->tot_triangles = 0;
new_stroke->flag |= GP_STROKE_RECALC_CACHES;
-
+
/* if new, set current color */
if (type == GP_STROKE_JOINCOPY) {
new_stroke->palcolor = palcolor;
@@ -1958,10 +1959,10 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op)
new_stroke->flag |= GP_STROKE_RECALC_COLOR;
}
}
-
+
/* 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) {
@@ -1981,21 +1982,21 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op)
}
}
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 */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -2006,19 +2007,19 @@ void GPENCIL_OT_stroke_join(wmOperatorType *ot)
{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");
@@ -2040,7 +2041,7 @@ static int gp_stroke_flip_exec(bContext *C, wmOperator *UNUSED(op))
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 */
@@ -2051,17 +2052,17 @@ static int gp_stroke_flip_exec(bContext *C, wmOperator *UNUSED(op))
if (ED_gpencil_stroke_color_use(gpl, gps) == false) {
continue;
}
-
+
/* flip stroke */
gpencil_flip_stroke(gps);
}
}
}
CTX_DATA_END;
-
+
/* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -2071,11 +2072,11 @@ void GPENCIL_OT_stroke_flip(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -2103,19 +2104,19 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
GP_SpaceConversion gsc = {NULL};
eGP_ReprojectModes mode = RNA_boolean_get(op->ptr, "type");
-
+
/* init space conversion stuff */
gp_point_conversion_init(C, &gsc);
-
+
/* init autodist for geometry projection */
if (mode == GP_REPROJECT_SURFACE) {
- struct Depsgraph *graph = CTX_data_depsgraph(C);
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
view3d_region_operator_needs_opengl(CTX_wm_window(C), gsc.ar);
- ED_view3d_autodist_init(graph, gsc.ar, CTX_wm_view3d(C), 0);
+ 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(C, gpl, gps)
{
@@ -2123,17 +2124,17 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
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? */
if (gpl->parent) {
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];
-
+
/* 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
@@ -2147,7 +2148,7 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
gp_point_to_parent_space(pt, diff_mat, &pt2);
gp_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]);
}
-
+
/* Project screenspace back to 3D space (from current perspective)
* so that all points have been treated the same way
*/
@@ -2159,10 +2160,10 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
/* 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);
@@ -2172,7 +2173,7 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
gp_point_xy_to_3d(&gsc, scene, xy, &pt->x);
}
}
-
+
/* Unapply parent corrections */
if (gpl->parent) {
mul_m4_v3(inverse_diff_mat, &pt->x);
@@ -2181,7 +2182,7 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
}
}
GP_EDITABLE_STROKES_END;
-
+
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
@@ -2189,29 +2190,29 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
void GPENCIL_OT_reproject(wmOperatorType *ot)
{
static const EnumPropertyItem reproject_type[] = {
- {GP_REPROJECT_PLANAR, "PLANAR", 0, "Planar",
+ {GP_REPROJECT_PLANAR, "PLANAR", 0, "Planar",
"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"},
{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_reproject_poll;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", reproject_type, GP_REPROJECT_PLANAR, "Projection Type", "");
}
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 04bcea02c9b..67b88efa285 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -41,6 +41,7 @@ struct bGPDstroke;
struct bGPDspoint;
struct GHash;
+struct RNG;
struct ARegion;
struct View2D;
@@ -117,7 +118,7 @@ bool gp_smooth_stroke(bGPDstroke *gps, int i, float inf, bool affect_pressure);
bool gp_smooth_stroke_strength(bGPDstroke *gps, int i, float inf);
bool gp_smooth_stroke_thickness(bGPDstroke *gps, int i, float inf);
void gp_subdivide_stroke(bGPDstroke *gps, const int new_totpoints);
-void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush);
+void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush, struct RNG *rng);
/* Layers Enums -------------------------------------- */
diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c
index 83e2a85db49..1b18c6f6731 100644
--- a/source/blender/editors/gpencil/gpencil_interpolate.c
+++ b/source/blender/editors/gpencil/gpencil_interpolate.c
@@ -89,18 +89,18 @@ static int gpencil_view3d_poll(bContext *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;
}
-
+
/* need data to interpolate */
if (ELEM(NULL, gpd, gpl)) {
return 0;
}
-
+
return 1;
}
@@ -108,13 +108,13 @@ static int gpencil_view3d_poll(bContext *C)
static void gp_interpolate_update_points(bGPDstroke *gps_from, bGPDstroke *gps_to, bGPDstroke *new_stroke, float factor)
{
bGPDspoint *prev, *pt, *next;
-
+
/* update points */
for (int i = 0; i < new_stroke->totpoints; i++) {
prev = &gps_from->points[i];
pt = &new_stroke->points[i];
next = &gps_to->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);
@@ -130,32 +130,32 @@ static void gp_interpolate_update_strokes(bContext *C, tGPDinterpolate *tgpi)
{
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);
}
}
}
-
+
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
}
@@ -164,7 +164,7 @@ static bool gp_interpolate_check_todo(bContext *C, bGPdata *gpd)
{
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 */
@@ -175,12 +175,12 @@ static bool gp_interpolate_check_todo(bContext *C, bGPdata *gpd)
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;
@@ -193,14 +193,14 @@ static bool gp_interpolate_check_todo(bContext *C, bGPdata *gpd)
if (ED_gpencil_stroke_color_use(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;
}
}
@@ -213,18 +213,18 @@ 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;
-
+
/* 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;
@@ -233,32 +233,32 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
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;
bool valid = true;
-
-
+
+
/* only selected */
if ((tgpi->flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) {
valid = false;
@@ -267,19 +267,19 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
if (ED_gpencil_stroke_can_use(C, gps_from) == false) {
valid = false;
}
-
+
/* check if the color is editable */
if (ED_gpencil_stroke_color_use(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 = MEM_dupallocN(gps_from);
new_stroke->points = MEM_dupallocN(gps_from->points);
@@ -306,7 +306,7 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
new_stroke->triangles = MEM_recallocN(new_stroke->triangles, sizeof(*new_stroke->triangles));
new_stroke->flag |= GP_STROKE_RECALC_CACHES;
}
-
+
/* add to strokes */
BLI_addtail(&tgpil->interFrame->strokes, new_stroke);
}
@@ -339,45 +339,46 @@ static void gpencil_mouse_update_shift(tGPDinterpolate *tgpi, wmOperator *op, co
{
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(tGPDinterpolate *p)
+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: ESC/RMB to cancel, Enter/LMB to confirm, WHEEL/MOVE to adjust factor"), 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);
+ 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));
+ BLI_snprintf(status_str, sizeof(status_str), "%s%d %%", msg_str, (int)((p->init_factor + p->shift) * 100.0f));
}
-
- ED_area_headerprint(p->sa, status_str);
+
+ 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(tgpi);
+ gpencil_interpolate_status_indicators(C, tgpi);
/* apply... */
tgpi->shift = RNA_float_get(op->ptr, "shift");
/* update points position */
@@ -391,7 +392,7 @@ static void gpencil_interpolate_exit(bContext *C, wmOperator *op)
{
tGPDinterpolate *tgpi = op->customdata;
tGPDinterpolate_layer *tgpil;
-
+
/* don't assume that operator data exists at all */
if (tgpi) {
/* remove drawing handler */
@@ -401,21 +402,22 @@ static void gpencil_interpolate_exit(bContext *C, wmOperator *op)
if (tgpi->draw_handle_3d) {
ED_region_draw_cb_exit(tgpi->ar->type, tgpi->draw_handle_3d);
}
-
+
/* clear status message area */
- ED_area_headerprint(tgpi->sa, NULL);
-
+ 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);
}
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
-
+
/* clear pointer */
op->customdata = NULL;
}
@@ -425,24 +427,24 @@ static bool gp_interpolate_set_init_values(bContext *C, wmOperator *op, tGPDinte
{
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 frame number */
tgpi->cframe = tgpi->scene->r.cfra;
-
+
/* 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);
-
+
return 1;
}
@@ -450,10 +452,10 @@ static bool gp_interpolate_set_init_values(bContext *C, wmOperator *op, tGPDinte
static tGPDinterpolate *gp_session_init_interpolation(bContext *C, wmOperator *op)
{
tGPDinterpolate *tgpi = MEM_callocN(sizeof(tGPDinterpolate), "GPencil Interpolate Data");
-
+
/* define initial values */
gp_interpolate_set_init_values(C, op, tgpi);
-
+
/* return context data for running operator */
return tgpi;
}
@@ -462,7 +464,7 @@ static tGPDinterpolate *gp_session_init_interpolation(bContext *C, wmOperator *o
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) {
@@ -470,7 +472,7 @@ static int gpencil_interpolate_init(bContext *C, wmOperator *op)
gpencil_interpolate_exit(C, op);
return 0;
}
-
+
/* everything is now setup ok */
return 1;
}
@@ -492,19 +494,19 @@ static int gpencil_interpolate_invoke(bContext *C, wmOperator *op, const wmEvent
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, 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)
@@ -514,24 +516,24 @@ static int gpencil_interpolate_invoke(bContext *C, wmOperator *op, const wmEvent
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
+ * 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(tgpi);
+ gpencil_interpolate_status_indicators(C, tgpi);
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;
}
@@ -544,27 +546,28 @@ static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent
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_headerprint(tgpi->sa, NULL);
+ 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);
@@ -573,34 +576,35 @@ static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent
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_headerprint(tgpi->sa, NULL);
+ 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;
@@ -610,7 +614,7 @@ static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent
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;
@@ -621,7 +625,7 @@ static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent
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);
}
@@ -632,21 +636,21 @@ static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent
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 {
@@ -655,7 +659,7 @@ static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent
}
}
}
-
+
/* still running... */
return OPERATOR_RUNNING_MODAL;
}
@@ -673,16 +677,16 @@ void GPENCIL_OT_interpolate(wmOperatorType *ot)
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);
}
@@ -695,14 +699,14 @@ static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_setting
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) {
@@ -715,7 +719,7 @@ static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_setting
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;
@@ -733,13 +737,13 @@ static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_setting
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:
@@ -751,7 +755,7 @@ static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_setting
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;
@@ -769,13 +773,13 @@ static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_setting
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:
@@ -787,13 +791,13 @@ static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_setting
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:
@@ -805,13 +809,13 @@ static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_setting
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:
@@ -823,13 +827,13 @@ static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_setting
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:
@@ -841,13 +845,13 @@ static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_setting
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:
@@ -859,13 +863,13 @@ static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_setting
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:
@@ -877,18 +881,18 @@ static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_setting
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;
}
@@ -897,12 +901,12 @@ 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;
-
+
Scene *scene = CTX_data_scene(C);
ToolSettings *ts = CTX_data_tool_settings(C);
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");
@@ -913,13 +917,13 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
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;
@@ -928,19 +932,19 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
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) {
@@ -954,11 +958,11 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
/* 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;
-
+
/* only selected */
if ((flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) {
continue;
@@ -971,20 +975,20 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
if (ED_gpencil_stroke_color_use(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 = MEM_dupallocN(gps_from);
new_stroke->points = MEM_dupallocN(gps_from->points);
@@ -999,19 +1003,19 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
new_stroke->tot_triangles = 0;
new_stroke->flag |= GP_STROKE_RECALC_CACHES;
}
-
+
/* update points position */
gp_interpolate_update_points(gps_from, gps_to, new_stroke, factor);
-
+
/* add to strokes */
BLI_addtail(&interFrame->strokes, new_stroke);
}
}
}
-
+
/* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -1021,11 +1025,11 @@ void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1045,7 +1049,7 @@ static int gpencil_interpolate_reverse_poll(bContext *C)
CTX_wm_operator_poll_msg_set(C, "Expected current frame to be a breakdown");
return 0;
}
-
+
return 1;
}
@@ -1059,11 +1063,11 @@ static int gpencil_interpolate_reverse_exec(bContext *C, wmOperator *UNUSED(op))
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) {
@@ -1077,7 +1081,7 @@ static int gpencil_interpolate_reverse_exec(bContext *C, wmOperator *UNUSED(op))
break;
}
}
-
+
/* Search right for "end_key" (i.e. the last breakdown to remove) */
gpf = gpl->actframe;
while (gpf) {
@@ -1091,36 +1095,36 @@ static int gpencil_interpolate_reverse_exec(bContext *C, wmOperator *UNUSED(op))
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) &&
+ 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 */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -1130,11 +1134,11 @@ void GPENCIL_OT_interpolate_reverse(wmOperatorType *ot)
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_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index 3a2169798e5..28d8c8c295b 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -57,28 +57,28 @@ static void ed_keymap_gpencil_general(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_find(keyconf, "Grease Pencil", 0, 0);
wmKeyMapItem *kmi;
-
+
/* Draw --------------------------------------- */
/* draw */
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", LEFTMOUSE, KM_PRESS, 0, DKEY);
RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW);
RNA_boolean_set(kmi->ptr, "wait_for_input", false);
-
+
/* draw - straight lines */
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", LEFTMOUSE, KM_PRESS, KM_CTRL, DKEY);
RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW_STRAIGHT);
RNA_boolean_set(kmi->ptr, "wait_for_input", false);
-
+
/* draw - poly lines */
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", RIGHTMOUSE, KM_PRESS, KM_CTRL, DKEY);
RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW_POLY);
RNA_boolean_set(kmi->ptr, "wait_for_input", false);
-
+
/* erase */
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", RIGHTMOUSE, KM_PRESS, 0, DKEY);
RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_ERASER);
RNA_boolean_set(kmi->ptr, "wait_for_input", false);
-
+
/* Tablet Mappings for Drawing ------------------ */
/* For now, only support direct drawing using the eraser, as most users using a tablet
* may still want to use that as their primary pointing device!
@@ -88,27 +88,31 @@ static void ed_keymap_gpencil_general(wmKeyConfig *keyconf)
RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW);
RNA_boolean_set(kmi->ptr, "wait_for_input", false);
#endif
-
+
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", TABLET_ERASER, KM_PRESS, 0, 0);
RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_ERASER);
RNA_boolean_set(kmi->ptr, "wait_for_input", false);
-
+
/* Viewport Tools ------------------------------- */
-
+
/* Enter EditMode */
WM_keymap_add_item(keymap, "GPENCIL_OT_editmode_toggle", TABKEY, KM_PRESS, 0, DKEY);
-
+
/* Pie Menu - For standard tools */
WM_keymap_add_menu_pie(keymap, "GPENCIL_MT_pie_tool_palette", QKEY, KM_PRESS, 0, DKEY);
WM_keymap_add_menu_pie(keymap, "GPENCIL_MT_pie_settings_palette", WKEY, KM_PRESS, 0, DKEY);
-
+
/* Add Blank Frame */
/* XXX: BKEY or NKEY? BKEY is easier to reach from DKEY, so we'll use that for now */
WM_keymap_add_item(keymap, "GPENCIL_OT_blank_frame_add", BKEY, KM_PRESS, 0, DKEY);
-
+
/* Delete Active Frame - For easier video tutorials/review sessions */
/* NOTE: This works even when not in EditMode */
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "GPENCIL_OT_active_frames_delete_all", XKEY, KM_PRESS, 0, DKEY);
+#else
+ WM_keymap_add_item(keymap, "GPENCIL_OT_active_frames_delete_all", DELKEY, KM_PRESS, 0, DKEY);
+#endif
}
/* ==================== */
@@ -125,81 +129,81 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_find(keyconf, "Grease Pencil Stroke Edit Mode", 0, 0);
wmKeyMapItem *kmi;
-
+
/* set poll callback - so that this keymap only gets enabled when stroke editmode is enabled */
keymap->poll = gp_stroke_editmode_poll;
-
+
/* ----------------------------------------------- */
-
+
/* Exit EditMode */
WM_keymap_add_item(keymap, "GPENCIL_OT_editmode_toggle", TABKEY, KM_PRESS, 0, 0);
-
+
/* Pie Menu - For settings/tools easy access */
WM_keymap_add_menu_pie(keymap, "GPENCIL_MT_pie_sculpt", EKEY, KM_PRESS, 0, DKEY);
-
+
/* Brush Settings */
/* NOTE: We cannot expose these in the standard keymap, as they will interfere with regular hotkeys
* in other modes. However, when we are dealing with Stroke Edit Mode, we know for certain
* that the only data being edited is that of the Grease Pencil strokes
*/
-
+
/* CTRL + FKEY = Eraser Radius */
kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, KM_CTRL, 0);
RNA_string_set(kmi->ptr, "data_path_primary", "user_preferences.edit.grease_pencil_eraser_radius");
-
+
/* Interpolation */
WM_keymap_add_item(keymap, "GPENCIL_OT_interpolate", EKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
WM_keymap_add_item(keymap, "GPENCIL_OT_interpolate_sequence", EKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
/* Sculpting ------------------------------------- */
-
+
/* Brush-Based Editing:
- * EKEY + LMB = Single stroke, draw immediately
+ * EKEY + LMB = Single stroke, draw immediately
* + Other Modifiers (Ctrl/Shift) = Invert, Smooth, etc.
*
* For the modal version, use D+E -> Sculpt
*/
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_paint", LEFTMOUSE, KM_PRESS, 0, EKEY);
RNA_boolean_set(kmi->ptr, "wait_for_input", false);
-
+
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_paint", LEFTMOUSE, KM_PRESS, KM_CTRL, EKEY);
RNA_boolean_set(kmi->ptr, "wait_for_input", false);
/*RNA_boolean_set(kmi->ptr, "use_invert", true);*/
-
+
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_paint", LEFTMOUSE, KM_PRESS, KM_SHIFT, EKEY);
RNA_boolean_set(kmi->ptr, "wait_for_input", false);
/*RNA_boolean_set(kmi->ptr, "use_smooth", true);*/
-
-
+
+
/* Shift-FKEY = Sculpt Strength */
kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0);
RNA_string_set(kmi->ptr, "data_path_primary", "tool_settings.gpencil_sculpt.brush.strength");
-
+
/* FKEY = Sculpt Brush Size */
kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path_primary", "tool_settings.gpencil_sculpt.brush.size");
-
-
+
+
/* Selection ------------------------------------- */
/* select all */
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_all", AKEY, KM_PRESS, 0, 0);
RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE);
-
+
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0);
RNA_enum_set(kmi->ptr, "action", SEL_INVERT);
-
+
/* circle select */
WM_keymap_add_item(keymap, "GPENCIL_OT_select_circle", CKEY, KM_PRESS, 0, 0);
-
+
/* border select */
WM_keymap_add_item(keymap, "GPENCIL_OT_select_border", BKEY, KM_PRESS, 0, 0);
-
+
/* lasso select */
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "deselect", false);
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_SHIFT | KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "deselect", true);
-
+
/* In the Node Editor, lasso select needs ALT modifier too (as somehow CTRL+LMB drag gets taken for "cut" quite early)
* There probably isn't too much harm adding this for other editors too as part of standard GP editing keymap. This hotkey
* combo doesn't seem to see much use under standard scenarios?
@@ -208,57 +212,65 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "deselect", false);
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_SHIFT | KM_CTRL | KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "deselect", true);
-
+
/* normal select */
WM_keymap_add_item(keymap, "GPENCIL_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
-
+
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "extend", true);
RNA_boolean_set(kmi->ptr, "toggle", true);
-
+
/* whole stroke select */
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "entire_strokes", true);
-
+
/* select linked */
/* NOTE: While LKEY is redundant, not having it breaks the mode illusion too much */
WM_keymap_add_item(keymap, "GPENCIL_OT_select_linked", LKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "GPENCIL_OT_select_linked", LKEY, KM_PRESS, KM_CTRL, 0);
-
+
/* select grouped */
WM_keymap_add_item(keymap, "GPENCIL_OT_select_grouped", GKEY, KM_PRESS, KM_SHIFT, 0);
-
+
/* select more/less */
WM_keymap_add_item(keymap, "GPENCIL_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "GPENCIL_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
-
+
/* Editing ----------------------------------------- */
-
+
/* duplicate and move selected points */
WM_keymap_add_item(keymap, "GPENCIL_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
-
+
/* delete */
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_gpencil_delete", XKEY, KM_PRESS, 0, 0);
+#endif
WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_gpencil_delete", DELKEY, KM_PRESS, 0, 0);
-
+
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "GPENCIL_OT_dissolve", XKEY, KM_PRESS, KM_CTRL, 0);
+#endif
WM_keymap_add_item(keymap, "GPENCIL_OT_dissolve", DELKEY, KM_PRESS, KM_CTRL, 0);
-
+
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "GPENCIL_OT_active_frames_delete_all", XKEY, KM_PRESS, KM_SHIFT, 0);
-
+#else
+ WM_keymap_add_item(keymap, "GPENCIL_OT_active_frames_delete_all", DELKEY, KM_PRESS, KM_SHIFT, 0);
+#endif
+
/* menu edit specials */
WM_keymap_add_menu(keymap, "GPENCIL_MT_gpencil_edit_specials", WKEY, KM_PRESS, 0, 0);
/* join strokes */
WM_keymap_add_item(keymap, "GPENCIL_OT_stroke_join", JKEY, KM_PRESS, KM_CTRL, 0);
-
+
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_stroke_join", JKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
RNA_enum_set(kmi->ptr, "type", GP_STROKE_JOINCOPY);
-
+
/* copy + paste */
WM_keymap_add_item(keymap, "GPENCIL_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "GPENCIL_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0);
-
+
#ifdef __APPLE__
WM_keymap_add_item(keymap, "GPENCIL_OT_copy", CKEY, KM_PRESS, KM_OSKEY, 0);
WM_keymap_add_item(keymap, "GPENCIL_OT_paste", VKEY, KM_PRESS, KM_OSKEY, 0);
@@ -266,72 +278,50 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
/* snap */
WM_keymap_add_menu(keymap, "GPENCIL_MT_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
-
-
+
+
/* convert to geometry */
WM_keymap_add_item(keymap, "GPENCIL_OT_convert", CKEY, KM_PRESS, KM_ALT, 0);
-
-
+
+
/* Show/Hide */
/* NOTE: These are available only in EditMode now, since they clash with general-purpose hotkeys */
WM_keymap_add_item(keymap, "GPENCIL_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0);
-
+
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_hide", HKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "unselected", false);
-
+
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "unselected", true);
WM_keymap_add_item(keymap, "GPENCIL_OT_selection_opacity_toggle", HKEY, KM_PRESS, KM_CTRL, 0);
-
+
/* Isolate Layer */
WM_keymap_add_item(keymap, "GPENCIL_OT_layer_isolate", PADASTERKEY, KM_PRESS, 0, 0);
-
+
/* Move to Layer */
WM_keymap_add_item(keymap, "GPENCIL_OT_move_to_layer", MKEY, KM_PRESS, 0, 0);
- /* Select drawing brush using index */
- kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_select", ONEKEY, KM_PRESS, 0, 0);
- RNA_int_set(kmi->ptr, "index", 0);
- kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_select", TWOKEY, KM_PRESS, 0, 0);
- RNA_int_set(kmi->ptr, "index", 1);
- kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_select", THREEKEY, KM_PRESS, 0, 0);
- RNA_int_set(kmi->ptr, "index", 2);
- kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_select", FOURKEY, KM_PRESS, 0, 0);
- RNA_int_set(kmi->ptr, "index", 3);
- kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_select", FIVEKEY, KM_PRESS, 0, 0);
- RNA_int_set(kmi->ptr, "index", 4);
- kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_select", SIXKEY, KM_PRESS, 0, 0);
- RNA_int_set(kmi->ptr, "index", 5);
- kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_select", SEVENKEY, KM_PRESS, 0, 0);
- RNA_int_set(kmi->ptr, "index", 6);
- kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_select", EIGHTKEY, KM_PRESS, 0, 0);
- RNA_int_set(kmi->ptr, "index", 7);
- kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_select", NINEKEY, KM_PRESS, 0, 0);
- RNA_int_set(kmi->ptr, "index", 8);
- kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_select", ZEROKEY, KM_PRESS, 0, 0);
- RNA_int_set(kmi->ptr, "index", 9);
-
/* Transform Tools */
kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", GKEY, KM_PRESS, 0, 0);
-
+
kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", EVT_TWEAK_S, KM_ANY, 0, 0);
-
+
kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_rotate", RKEY, KM_PRESS, 0, 0);
-
+
kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_resize", SKEY, KM_PRESS, 0, 0);
-
+
kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_mirror", MKEY, KM_PRESS, KM_CTRL, 0);
-
+
kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_bend", WKEY, KM_PRESS, KM_SHIFT, 0);
-
+
WM_keymap_add_item(keymap, "TRANSFORM_OT_tosphere", SKEY, KM_PRESS, KM_ALT | KM_SHIFT, 0);
-
+
WM_keymap_add_item(keymap, "TRANSFORM_OT_shear", SKEY, KM_PRESS, KM_ALT | KM_CTRL | KM_SHIFT, 0);
-
+
kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", SKEY, KM_PRESS, KM_ALT, 0);
RNA_enum_set(kmi->ptr, "mode", TFM_GPENCIL_SHRINKFATTEN);
-
+
/* Proportional Editing */
ED_keymap_proportional_cycle(keyconf, keymap);
ED_keymap_proportional_editmode(keyconf, keymap, true);
@@ -350,11 +340,11 @@ void ED_keymap_gpencil(wmKeyConfig *keyconf)
void ED_operatortypes_gpencil(void)
{
/* Drawing ----------------------- */
-
+
WM_operatortype_append(GPENCIL_OT_draw);
-
+
/* Editing (Strokes) ------------ */
-
+
WM_operatortype_append(GPENCIL_OT_editmode_toggle);
WM_operatortype_append(GPENCIL_OT_selection_opacity_toggle);
@@ -363,41 +353,41 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_select_circle);
WM_operatortype_append(GPENCIL_OT_select_border);
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_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_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_brush_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_hide);
WM_operatortype_append(GPENCIL_OT_reveal);
WM_operatortype_append(GPENCIL_OT_lock_all);
@@ -406,10 +396,10 @@ void ED_operatortypes_gpencil(void)
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_convert);
WM_operatortype_append(GPENCIL_OT_stroke_arrange);
@@ -445,7 +435,7 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_brush_select);
/* Editing (Time) --------------- */
-
+
/* Interpolation */
WM_operatortype_append(GPENCIL_OT_interpolate);
WM_operatortype_append(GPENCIL_OT_interpolate_sequence);
@@ -456,7 +446,7 @@ 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",
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 3f3349a752c..0ae45a9fde8 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -46,14 +46,15 @@
#include "PIL_time.h"
-#include "BKE_paint.h"
-#include "BKE_gpencil.h"
+#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_gpencil.h"
+#include "BKE_main.h"
+#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_screen.h"
#include "BKE_tracking.h"
-#include "BKE_colortools.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -72,6 +73,7 @@
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
+#include "GPU_state.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -115,37 +117,38 @@ typedef enum eGPencil_PaintFlags {
* "p" = op->customdata
*/
typedef struct tGPsdata {
+ Main *bmain;
Scene *scene; /* current scene from context */
- struct Depsgraph *graph;
-
+ struct Depsgraph *depsgraph;
+
wmWindow *win; /* window where painting originated */
ScrArea *sa; /* area where painting originated */
ARegion *ar; /* region where painting originated */
View2D *v2d; /* needed for GP_STROKE_2DSPACE */
rctf *subrect; /* for using the camera rect within the 3d view */
rctf subrect_data;
-
+
GP_SpaceConversion gsc; /* settings to pass to gp_points_to_xy() */
-
+
PointerRNA ownerPtr; /* pointer to owner of gp-datablock */
bGPdata *gpd; /* gp-datablock layer comes from */
bGPDlayer *gpl; /* layer we're working on */
bGPDframe *gpf; /* frame we're working on */
-
+
char *align_flag; /* projection-mode flags (toolsettings - eGPencil_Placement_Flags) */
-
+
eGPencil_PaintStatus status; /* current status of painting */
eGPencil_PaintModes paintmode; /* mode for painting */
eGPencil_PaintFlags flags; /* flags that can get set during runtime (eGPencil_PaintFlags) */
-
+
short radius; /* radius of influence for eraser */
-
+
int mval[2]; /* current mouse-position */
int mvalo[2]; /* previous recorded mouse-position */
-
+
float pressure; /* current stylus pressure */
float opressure; /* previous stylus pressure */
-
+
/* 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.
@@ -153,13 +156,13 @@ typedef struct tGPsdata {
double inittime; /* Used when converting to path */
double curtime; /* Used when converting to path */
double ocurtime; /* Used when converting to path */
-
+
float imat[4][4]; /* inverted transformation matrix applying when converting coords from screen-space
* to region space */
float mat[4][4];
-
+
float custom_color[4]; /* custom color - hack for enforcing a particular color for track/mask editing */
-
+
void *erasercursor; /* radial cursor data for drawing eraser */
bGPDpalettecolor *palettecolor; /* current palette color */
@@ -167,6 +170,8 @@ typedef struct tGPsdata {
short straight[2]; /* 1: line horizontal, 2: line vertical, other: not defined, second element position */
int lock_axis; /* lock drawing to one axis */
+ RNG *rng;
+
short keymodifier; /* key used for invoking the operator */
} tGPsdata;
@@ -216,7 +221,7 @@ static int gpencil_draw_poll(bContext *C)
else {
CTX_wm_operator_poll_msg_set(C, "Active region not set");
}
-
+
return 0;
}
@@ -237,12 +242,12 @@ static void gp_get_3d_reference(tGPsdata *p, float vec[3])
{
View3D *v3d = p->sa->spacedata.first;
const float *fp = ED_view3d_cursor3d_get(p->scene, v3d)->location;
-
+
/* the reference point used depends on the owner... */
#if 0 /* XXX: disabled for now, since we can't draw relative to the owner yet */
if (p->ownerPtr.type == &RNA_Object) {
Object *ob = (Object *)p->ownerPtr.data;
-
+
/* active Object
* - use relative distance of 3D-cursor from object center
*/
@@ -263,24 +268,24 @@ static bool gp_stroke_filtermval(tGPsdata *p, const int mval[2], int pmval[2])
{
int dx = abs(mval[0] - pmval[0]);
int dy = abs(mval[1] - pmval[1]);
-
+
/* if buffer is empty, just let this go through (i.e. so that dots will work) */
if (p->gpd->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;
@@ -349,7 +354,7 @@ static void gp_reproject_toplane(tGPsdata *p, bGPDstroke *gps)
static void gp_stroke_convertcoords(tGPsdata *p, const int 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->sbuffer_sflag & GP_STROKE_3DSPACE) {
if (gpencil_project_check(p) && (ED_view3d_autodist_simple(p->ar, mval, out, 0, depth))) {
@@ -362,7 +367,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3]
float rvec[3], dvec[3];
float mval_f[2] = {UNPACK2(mval)};
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.
@@ -371,10 +376,10 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3]
* - 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) {
sub_v2_v2v2(mval_f, mval_prj, mval_f);
ED_view3d_win_to_delta(p->ar, mval_f, dvec, zfac);
@@ -385,13 +390,13 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3]
}
}
}
-
+
/* 2d - on 'canvas' (assume that p->v2d is set) */
else if ((gpd->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 */
@@ -406,7 +411,8 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3]
}
/* apply jitter to stroke */
-static void gp_brush_jitter(bGPdata *gpd, bGPDbrush *brush, tGPspoint *pt, const int mval[2], int r_mval[2])
+static void gp_brush_jitter(
+ bGPdata *gpd, bGPDbrush *brush, tGPspoint *pt, const int mval[2], int r_mval[2], RNG *rng)
{
float pressure = pt->pressure;
float tmp_pressure = pt->pressure;
@@ -415,7 +421,7 @@ static void gp_brush_jitter(bGPdata *gpd, bGPDbrush *brush, tGPspoint *pt, const
tmp_pressure = curvef * brush->draw_sensitivity;
}
const float exfactor = (brush->draw_jitter + 2.0f) * (brush->draw_jitter + 2.0f); /* exponential value */
- const float fac = BLI_frand() * exfactor * tmp_pressure;
+ 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 */
@@ -432,7 +438,7 @@ static void gp_brush_jitter(bGPdata *gpd, bGPDbrush *brush, tGPspoint *pt, const
svec[0] = -mvec[1];
svec[1] = mvec[0];
/* scale the displacement by the random, and apply */
- if (BLI_frand() > 0.5f) {
+ if (BLI_rng_get_float(rng) > 0.5f) {
mul_v2_fl(svec, -fac);
}
else {
@@ -477,7 +483,7 @@ static void gp_brush_angle(bGPdata *gpd, bGPDbrush *brush, tGPspoint *pt, const
fac = 1.0f - fabs(dot_v2v2(v0, mvec)); /* 0.0 to 1.0 */
/* interpolate with previous point for smoother transitions */
mpressure = interpf(pt->pressure - (sen * fac), (pt - 1)->pressure, 0.3f);
- pt->pressure = mpressure;
+ pt->pressure = mpressure;
CLAMP(pt->pressure, GPENCIL_ALPHA_OPACITY_THRESH, 1.0f);
}
@@ -499,13 +505,13 @@ static short gp_stroke_addpoint(
if (gpd->sbuffer_size == 0) {
/* first point in buffer (start point) */
pt = (tGPspoint *)(gpd->sbuffer);
-
+
/* store settings */
copy_v2_v2_int(&pt->x, mval);
pt->pressure = 1.0f; /* T44932 - Pressure vals are unreliable, so ignore for now */
pt->strength = 1.0f;
pt->time = (float)(curtime - p->inittime);
-
+
/* increment buffer size */
gpd->sbuffer_size++;
}
@@ -514,17 +520,17 @@ static short gp_stroke_addpoint(
* - assume that pointers for this are always valid...
*/
pt = ((tGPspoint *)(gpd->sbuffer) + 1);
-
+
/* store settings */
copy_v2_v2_int(&pt->x, mval);
pt->pressure = 1.0f; /* T44932 - Pressure vals are unreliable, so ignore for now */
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->sbuffer_size = 2;
}
-
+
/* can keep carrying on this way :) */
return GP_STROKEADD_NORMAL;
}
@@ -532,10 +538,10 @@ static short gp_stroke_addpoint(
/* check if still room in buffer */
if (gpd->sbuffer_size >= GP_STROKE_BUFFER_MAX)
return GP_STROKEADD_OVERFLOW;
-
+
/* get pointer to destination point */
pt = ((tGPspoint *)(gpd->sbuffer) + gpd->sbuffer_size);
-
+
/* store settings */
/* pressure */
if (brush->flag & GP_BRUSH_USE_PRESSURE) {
@@ -548,7 +554,7 @@ static short gp_stroke_addpoint(
/* Apply jitter to position */
if (brush->draw_jitter > 0.0f) {
int r_mval[2];
- gp_brush_jitter(gpd, brush, pt, mval, r_mval);
+ gp_brush_jitter(gpd, brush, pt, mval, r_mval, p->rng);
copy_v2_v2_int(&pt->x, r_mval);
}
else {
@@ -558,11 +564,11 @@ static short gp_stroke_addpoint(
if ((brush->draw_random_press > 0.0f) && (brush->flag & GP_BRUSH_USE_RANDOM_PRESSURE)) {
float curvef = curvemapping_evaluateF(brush->cur_sensitivity, 0, pressure);
float tmp_pressure = curvef * brush->draw_sensitivity;
- if (BLI_frand() > 0.5f) {
- pt->pressure -= tmp_pressure * brush->draw_random_press * BLI_frand();
+ if (BLI_rng_get_float(p->rng) > 0.5f) {
+ pt->pressure -= tmp_pressure * brush->draw_random_press * BLI_rng_get_float(p->rng);
}
else {
- pt->pressure += tmp_pressure * brush->draw_random_press * BLI_frand();
+ pt->pressure += tmp_pressure * brush->draw_random_press * BLI_rng_get_float(p->rng);
}
CLAMP(pt->pressure, GPENCIL_STRENGTH_MIN, 1.0f);
}
@@ -586,21 +592,21 @@ static short gp_stroke_addpoint(
/* apply randomness to color strength */
if ((brush->draw_random_press > 0.0f) && (brush->flag & GP_BRUSH_USE_RANDOM_STRENGTH)) {
- if (BLI_frand() > 0.5f) {
- pt->strength -= pt->strength * brush->draw_random_press * BLI_frand();
+ if (BLI_rng_get_float(p->rng) > 0.5f) {
+ pt->strength -= pt->strength * brush->draw_random_press * BLI_rng_get_float(p->rng);
}
else {
- pt->strength += pt->strength * brush->draw_random_press * BLI_frand();
+ pt->strength += pt->strength * brush->draw_random_press * BLI_rng_get_float(p->rng);
}
CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
}
/* point time */
pt->time = (float)(curtime - p->inittime);
-
+
/* increment counters */
gpd->sbuffer_size++;
-
+
/* check if another operation can still occur */
if (gpd->sbuffer_size == GP_STROKE_BUFFER_MAX)
return GP_STROKEADD_FULL;
@@ -608,17 +614,17 @@ static short gp_stroke_addpoint(
return GP_STROKEADD_NORMAL;
}
else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
-
+
bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
/* get pointer to destination point */
pt = (tGPspoint *)(gpd->sbuffer);
-
+
/* store settings */
copy_v2_v2_int(&pt->x, mval);
pt->pressure = 1.0f; /* T44932 - Pressure vals are unreliable, so ignore for now */
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.)
@@ -626,15 +632,15 @@ static short gp_stroke_addpoint(
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->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,
@@ -642,12 +648,12 @@ static short gp_stroke_addpoint(
*/
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->graph, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
+ 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);
/* if axis locked, reproject to plane locked (only in 3d space) */
@@ -665,11 +671,11 @@ static short gp_stroke_addpoint(
/* force fill recalc */
gps->flag |= GP_STROKE_RECALC_CACHES;
}
-
+
/* increment counters */
if (gpd->sbuffer_size == 0)
gpd->sbuffer_size++;
-
+
return GP_STROKEADD_NORMAL;
}
@@ -688,15 +694,15 @@ static void gp_stroke_simplify(tGPsdata *p)
short num_points = gpd->sbuffer_size;
short flag = gpd->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
@@ -704,7 +710,7 @@ static void gp_stroke_simplify(tGPsdata *p)
gpd->sbuffer = NULL;
gp_session_validatebuffer(p);
gpd->sbuffer_sflag = flag;
-
+
/* macro used in loop to get position of new point
* - used due to the mixture of datatypes in use here
*/
@@ -715,30 +721,30 @@ static void gp_stroke_simplify(tGPsdata *p)
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;
int 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] = (int)co[0];
mco[1] = (int)co[1];
-
+
/* ignore return values on this... assume to be ok for now */
gp_stroke_addpoint(p, mco, pressure, p->inittime + (double)time);
@@ -747,7 +753,7 @@ static void gp_stroke_simplify(tGPsdata *p)
}
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);
}
@@ -762,11 +768,11 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
tGPspoint *ptc;
bGPDbrush *brush = p->brush;
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->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
*/
@@ -774,14 +780,14 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
totelem = (gpd->sbuffer_size >= 2) ? 2 : gpd->sbuffer_size;
else
totelem = gpd->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->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
@@ -791,23 +797,23 @@ static void gp_stroke_newfrombuffer(tGPsdata *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->thickness;
gps->flag = gpd->sbuffer_sflag;
gps->inittime = p->inittime;
-
+
/* enable recalculation flag by default (only used if hq fill) */
gps->flag |= GP_STROKE_RECALC_CACHES;
/* allocate enough memory for a continuous array for storage points */
int sublevel = brush->sublevel;
int new_totpoints = gps->totpoints;
-
+
for (i = 0; i < sublevel; i++) {
new_totpoints += new_totpoints - 1;
}
@@ -818,14 +824,14 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
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->sbuffer;
-
+
/* convert screen-coordinates to appropriate coordinates (and store them) */
gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
/* if axis locked, reproject to plane locked (only in 3d space) */
@@ -841,14 +847,14 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
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->sbuffer) + (gpd->sbuffer_size - 1);
-
+
/* convert screen-coordinates to appropriate coordinates (and store them) */
gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
/* if axis locked, reproject to plane locked (only in 3d space) */
@@ -870,7 +876,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
/* first point */
ptc = gpd->sbuffer;
-
+
/* convert screen-coordinates to appropriate coordinates (and store them) */
gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
/* if axis locked, reproject to plane locked (only in 3d space) */
@@ -976,7 +982,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
}
/* apply randomness to stroke */
if (brush->draw_random_sub > 0.0f) {
- gp_randomize_stroke(gps, brush);
+ gp_randomize_stroke(gps, brush, p->rng);
}
/* smooth stroke after subdiv - only if there's something to do
@@ -1012,7 +1018,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
gps->palcolor = palcolor;
BLI_strncpy(gps->colorname, palcolor->info, sizeof(gps->colorname));
- /* add stroke to frame, usually on tail of the listbase, but if on back is enabled the stroke is added on listbase head
+ /* 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
*/
@@ -1060,7 +1066,7 @@ static bool gp_stroke_eraser_is_occluded(tGPsdata *p, const bGPDspoint *pt, cons
mul_v3_m4v3(fpt, diff_mat, &pt->x);
const float depth_pt = view3d_point_depth(rv3d, fpt);
-
+
if (depth_pt > depth_mval) {
return true;
}
@@ -1075,13 +1081,13 @@ static float gp_stroke_eraser_calc_influence(tGPsdata *p, const int mval[2], con
/* Linear Falloff... */
float distance = (float)len_v2v2_int(mval, co);
float fac;
-
+
CLAMP(distance, 0.0f, (float)radius);
fac = 1.0f - (distance / (float)radius);
-
+
/* Control this further using pen pressure */
fac *= p->pressure;
-
+
/* Return influence factor computed here */
return fac;
}
@@ -1142,15 +1148,15 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
* below which we would have invisible strokes
*/
const float cull_thresh = (gps->thickness) ? 1.0f / ((float)gps->thickness) : 1.0f;
-
+
/* Amount to decrease the pressure of each point with each stroke */
// TODO: Fetch from toolsettings, or compute based on thickness instead?
const float strength = 0.1f;
-
+
/* Perform culling? */
bool do_cull = false;
-
-
+
+
/* Clear Tags
*
* Note: It's better this way, as we are sure that
@@ -1161,7 +1167,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
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)
@@ -1174,7 +1180,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
/* only process if it hasn't been masked out... */
if ((p->flags & GP_PAINTFLAG_SELECTMASK) && !(gps->points->flag & GP_SPOINT_SELECT))
continue;
-
+
if (gpl->parent == NULL) {
gp_point_to_xy(&p->gsc, gps, pt1, &pc1[0], &pc1[1]);
gp_point_to_xy(&p->gsc, gps, pt2, &pc2[0], &pc2[1]);
@@ -1207,7 +1213,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
*/
pt1->pressure -= gp_stroke_eraser_calc_influence(p, mval, radius, pc1) * strength;
pt2->pressure -= gp_stroke_eraser_calc_influence(p, mval, radius, pc2) * strength / 2.0f;
-
+
/* 2) Tag any point with overly low influence for removal in the next pass */
if (pt1->pressure < cull_thresh) {
pt1->flag |= GP_SPOINT_TAG;
@@ -1221,7 +1227,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
}
}
}
-
+
/* Second Pass: Remove any points that are tagged */
if (do_cull) {
gp_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_TAG);
@@ -1235,28 +1241,28 @@ static void gp_stroke_doeraser(tGPsdata *p)
bGPDlayer *gpl;
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->graph, p->ar, v3d, 0);
+ 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;
@@ -1264,7 +1270,7 @@ static void gp_stroke_doeraser(tGPsdata *p)
else if (gpf == NULL) {
continue;
}
-
+
/* loop over strokes, checking segments for intersections */
for (gps = gpf->strokes.first; gps; gps = gpn) {
gpn = gps->next;
@@ -1289,7 +1295,7 @@ static void gp_stroke_doeraser(tGPsdata *p)
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->sbuffer) {
/* printf("\t\tGP - reset sbuffer\n"); */
@@ -1299,13 +1305,13 @@ static void gp_session_validatebuffer(tGPsdata *p)
/* printf("\t\tGP - allocate sbuffer\n"); */
gpd->sbuffer = MEM_callocN(sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX, "gp_session_strokebuffer");
}
-
+
/* reset indices */
gpd->sbuffer_size = 0;
-
+
/* reset flags */
gpd->sbuffer_sflag = 0;
-
+
/* reset inittime */
p->inittime = 0.0;
}
@@ -1316,7 +1322,7 @@ static bGPDpalettecolor *gp_create_new_color(bGPDpalette *palette)
bGPDpalettecolor *palcolor;
palcolor = BKE_gpencil_palettecolor_addnew(palette, DATA_("Color"), true);
-
+
return palcolor;
}
@@ -1385,11 +1391,12 @@ static void gp_init_palette(tGPsdata *p)
/* (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;
@@ -1397,22 +1404,23 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
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->graph = CTX_data_depsgraph(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)
*/
@@ -1420,7 +1428,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
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)
@@ -1432,7 +1440,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
case SPACE_NODE:
{
/* SpaceNode *snode = curarea->spacedata.first; */
-
+
/* set current area */
p->sa = curarea;
p->ar = ar;
@@ -1443,13 +1451,13 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
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;
@@ -1462,7 +1470,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
case SPACE_IMAGE:
{
/* SpaceImage *sima = curarea->spacedata.first; */
-
+
/* set the current area */
p->sa = curarea;
p->ar = ar;
@@ -1474,7 +1482,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
{
SpaceClip *sc = curarea->spacedata.first;
MovieClip *clip = ED_space_clip_get_clip(sc);
-
+
if (clip == NULL) {
p->status = GP_STATUS_ERROR;
return false;
@@ -1485,15 +1493,15 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
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);
@@ -1508,7 +1516,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
return false;
}
}
-
+
invert_m4_m4(p->mat, p->imat);
copy_m4_m4(p->gsc.mat, p->mat);
break;
@@ -1522,7 +1530,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
return 0;
}
}
-
+
/* get gp-data */
gpd_ptr = ED_gpencil_data_get_pointers(C, &p->ownerPtr);
if (gpd_ptr == NULL) {
@@ -1534,17 +1542,17 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
else {
/* if no existing GPencil block exists, add one */
if (*gpd_ptr == NULL)
- *gpd_ptr = BKE_gpencil_data_addnew("GPencil");
+ *gpd_ptr = BKE_gpencil_data_addnew(bmain, "GPencil");
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);
/* set brush and create a new one if null */
@@ -1567,18 +1575,23 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
static tGPsdata *gp_session_initpaint(bContext *C)
{
tGPsdata *p = NULL;
-
+
/* create new context data */
p = MEM_callocN(sizeof(tGPsdata), "GPencil Drawing Data");
-
+
gp_session_initdata(C, p);
-
+
/* radius for eraser circle is defined in userprefs now */
/* NOTE: we do this here, so that if we exit immediately,
* erase size won't get lost
*/
p->radius = U.gp_eraser;
+ /* Random generator, only init once. */
+ uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
+ rng_seed ^= GET_UINT_FROM_POINTER(p);
+ p->rng = BLI_rng_new(rng_seed);
+
/* return context data for running paint operator */
return p;
}
@@ -1587,35 +1600,44 @@ static tGPsdata *gp_session_initpaint(bContext *C)
static void gp_session_cleanup(tGPsdata *p)
{
bGPdata *gpd = (p) ? p->gpd : NULL;
-
+
/* error checking */
if (gpd == NULL)
return;
-
+
/* free stroke buffer */
if (gpd->sbuffer) {
/* printf("\t\tGP - free sbuffer\n"); */
MEM_freeN(gpd->sbuffer);
gpd->sbuffer = NULL;
}
-
+
/* clear flags */
gpd->sbuffer_size = 0;
gpd->sbuffer_sflag = 0;
p->inittime = 0.0;
}
+static void gp_session_free(tGPsdata *p)
+{
+ if (p->rng != NULL) {
+ BLI_rng_free(p->rng);
+ }
+ 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) {
p->gpl = BKE_gpencil_layer_addnew(p->gpd, "GP_Layer", true);
-
+
if (p->custom_color[3])
copy_v3_v3(p->gpl->color, p->custom_color);
}
@@ -1625,7 +1647,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
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:
@@ -1634,12 +1656,12 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
* (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)
*
@@ -1651,16 +1673,16 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
gpl->actframe = BKE_gpencil_layer_getframe(gpl, CFRA, 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)
*/
@@ -1669,7 +1691,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
p->flags |= GP_PAINTFLAG_SELECTMASK;
}
}
-
+
if (has_layer_to_erase == false) {
p->status = GP_STATUS_ERROR;
//if (G.debug & G_DEBUG)
@@ -1680,14 +1702,14 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
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, add_frame_mode);
-
+
if (p->gpf == NULL) {
p->status = GP_STATUS_ERROR;
if (G.debug & G_DEBUG)
@@ -1698,12 +1720,12 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
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->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) {
@@ -1714,25 +1736,25 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
else {
/* disable eraser flags - so that we can switch modes during a session */
p->gpd->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) {
ED_view3d_calc_camera_border(p->scene, depsgraph, p->ar, v3d, rv3d, &p->subrect_data, true); /* no shift */
@@ -1740,21 +1762,21 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
}
}
}
-
+
/* 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) {
@@ -1776,7 +1798,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
case SPACE_IMAGE:
{
SpaceImage *sima = (SpaceImage *)p->sa->spacedata.first;
-
+
/* only set these flags if the image editor doesn't have an image active,
* otherwise user will be confused by strokes not appearing after they're drawn
*
@@ -1810,12 +1832,12 @@ static void gp_paint_strokeend(tGPsdata *p)
*/
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->graph, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
+ 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->sbuffer_sflag & GP_STROKE_ERASER) == 0) {
/* simplify stroke before transferring? */
@@ -1824,7 +1846,7 @@ static void gp_paint_strokeend(tGPsdata *p)
/* transfer stroke to frame */
gp_stroke_newfrombuffer(p);
}
-
+
/* clean up buffer now */
gp_session_validatebuffer(p);
}
@@ -1839,7 +1861,7 @@ static void gp_paint_cleanup(tGPsdata *p)
/* finish off a stroke */
gp_paint_strokeend(p);
}
-
+
/* "unlock" frame */
if (p->gpf)
p->gpf->flag &= ~GP_FRAME_PAINT;
@@ -1857,9 +1879,9 @@ static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr)
const uint shdr_pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
@@ -1869,7 +1891,7 @@ static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr)
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
immUniformColor4f(1.0f, 0.39f, 0.39f, 0.78f);
@@ -1884,8 +1906,8 @@ static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr)
immUnbindProgram();
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
+ GPU_blend(false);
+ GPU_line_smooth(false);
}
}
@@ -1912,7 +1934,7 @@ static bool gpencil_is_tablet_eraser_active(const wmEvent *event)
const wmTabletData *wmtab = event->tablet_data;
return (wmtab->Active == EVT_TABLET_ERASER);
}
-
+
return false;
}
@@ -1921,13 +1943,13 @@ static bool gpencil_is_tablet_eraser_active(const wmEvent *event)
static void gpencil_draw_exit(bContext *C, wmOperator *op)
{
tGPsdata *p = op->customdata;
-
+
/* clear undo stack */
gpencil_undo_finish();
-
+
/* 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 */
@@ -1941,15 +1963,13 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op)
* have been toggled at some point.
*/
U.gp_eraser = p->radius;
-
+
/* cleanup */
gp_paint_cleanup(p);
gp_session_cleanup(p);
-
- /* finally, free the temp data */
- MEM_freeN(p);
+ gp_session_free(p);
}
-
+
op->customdata = NULL;
}
@@ -1966,7 +1986,7 @@ 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)) {
@@ -1974,7 +1994,7 @@ static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event)
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) {
@@ -1988,7 +2008,7 @@ static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event)
else {
p->keymodifier = -1;
}
-
+
/* everything is now setup ok */
return 1;
}
@@ -2006,46 +2026,46 @@ static void gpencil_draw_cursor_set(tGPsdata *p)
}
/* update UI indicators of status, including cursor and header prints */
-static void gpencil_draw_status_indicators(tGPsdata *p)
+static void gpencil_draw_status_indicators(bContext *C, tGPsdata *p)
{
/* header prints */
switch (p->status) {
case GP_STATUS_PAINTING:
/* only print this for paint-sessions, otherwise it gets annoying */
if (GPENCIL_SKETCH_SESSIONS_ON(p->scene))
- ED_area_headerprint(p->sa, IFACE_("Grease Pencil: Drawing/erasing stroke... Release to end stroke"));
+ ED_workspace_status_text(C, IFACE_("Grease Pencil: Drawing/erasing stroke... Release to end stroke"));
break;
-
+
case GP_STATUS_IDLING:
/* print status info */
switch (p->paintmode) {
case GP_PAINTMODE_ERASER:
- ED_area_headerprint(p->sa, IFACE_("Grease Pencil Erase Session: Hold and drag LMB or RMB to erase | "
+ 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_area_headerprint(p->sa, IFACE_("Grease Pencil Line Session: Hold and drag LMB to draw | "
+ 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_DRAW:
- ED_area_headerprint(p->sa, IFACE_("Grease Pencil Freehand Session: Hold and drag LMB to draw | "
+ ED_workspace_status_text(C, IFACE_("Grease Pencil Freehand Session: Hold and drag LMB to draw | "
"E/ESC/Enter to end (or click outside this area)"));
break;
case GP_PAINTMODE_DRAW_POLY:
- ED_area_headerprint(p->sa, IFACE_("Grease Pencil Poly Session: LMB click to place next stroke vertex | "
+ ED_workspace_status_text(C, IFACE_("Grease Pencil Poly Session: LMB click to place next stroke vertex | "
"ESC/Enter to end (or click outside this area)"));
break;
-
+
default: /* unhandled future cases */
- ED_area_headerprint(p->sa, IFACE_("Grease Pencil Session: ESC/Enter to end (or click outside this area)"));
+ 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_area_headerprint(p->sa, NULL);
+ ED_workspace_status_text(C, NULL);
break;
}
}
@@ -2076,7 +2096,7 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p, Depsgraph *depsgraph
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! */
@@ -2093,12 +2113,12 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p, Depsgraph *depsgraph
/* 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];
@@ -2114,13 +2134,13 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event, Depsg
PointerRNA itemptr;
float mousef[2];
int tablet = 0;
-
+
/* convert from window-space to area-space mouse coordinates
* NOTE: float to ints conversions, +1 factor is probably used to ensure a bit more accurate rounding...
*/
p->mval[0] = event->mval[0] + 1;
p->mval[1] = event->mval[1] + 1;
-
+
/* verify key status for straight lines */
if ((event->ctrl > 0) || (event->alt > 0)) {
if (p->straight[0] == 0) {
@@ -2146,14 +2166,14 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event, Depsg
}
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
@@ -2170,11 +2190,11 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event, Depsg
/* 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;
@@ -2188,7 +2208,7 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event, Depsg
if (tablet && (p->pressure >= 0.99f))
return;
}
-
+
/* check if alt key is pressed and limit to straight lines */
if (p->straight[0] != 0) {
if (p->straight[0] == 1) {
@@ -2203,15 +2223,15 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event, Depsg
/* 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);
@@ -2226,9 +2246,9 @@ 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);
@@ -2237,25 +2257,25 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op)
}
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
@@ -2266,30 +2286,30 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op)
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;
}
@@ -2300,10 +2320,10 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op)
static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
tGPsdata *p = NULL;
-
+
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)
@@ -2314,17 +2334,17 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
}
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);
}
- /* set cursor
+ /* set cursor
* NOTE: This may change later (i.e. intentionally via brush toggle,
* or unintentionally if the user scrolls outside the area)...
*/
@@ -2345,7 +2365,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
/* 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);
@@ -2362,7 +2382,7 @@ static bool gpencil_area_exists(bContext *C, ScrArea *sa_test)
static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op)
{
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)
*/
@@ -2370,21 +2390,21 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op)
printf("\t\t\tGP - wrong area execution abort!\n");
p->status = GP_STATUS_ERROR;
}
-
+
/* printf("\t\tGP - start stroke\n"); */
-
+
/* we may need to set up paint env again if we're resuming */
/* XXX: watch it with the paintmode! in future,
* it'd be nice to allow changing paint-mode when in sketching-sessions */
-
+
if (gp_session_initdata(C, 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;
}
-
+
return op->customdata;
}
@@ -2395,12 +2415,12 @@ static void gpencil_stroke_end(wmOperator *op)
gp_paint_cleanup(p);
gpencil_undo_push(p->gpd);
-
+
gp_session_cleanup(p);
-
+
p->status = GP_STATUS_IDLING;
op->flag |= OP_IS_MODAL_CURSOR_REGION;
-
+
p->gpd = NULL;
p->gpl = NULL;
p->gpf = NULL;
@@ -2434,7 +2454,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
tGPsdata *p = op->customdata;
ToolSettings *ts = CTX_data_tool_settings(C);
int estate = OPERATOR_PASS_THROUGH; /* default exit state - pass through to support MMB view nav, etc. */
-
+
/* if (event->type == NDOF_MOTION)
* return OPERATOR_PASS_THROUGH;
* -------------------------------
@@ -2447,7 +2467,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
* better in tools that immediately apply
* in 3D space.
*/
-
+
if (p->status == GP_STATUS_IDLING) {
ARegion *ar = CTX_wm_region(C);
p->ar = ar;
@@ -2484,9 +2504,9 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
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]
*/
@@ -2504,25 +2524,25 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
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) && (event->val != KM_NOTHING)) {
+ 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 what happens next depends on whether we 'painting sessions' is enabled
*/
sketch |= GPENCIL_SKETCH_SESSIONS_ON(p->scene);
/* polyline drawing is also 'sketching' -- 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"); */
@@ -2533,13 +2553,13 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
*/
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) {
+ if (p->paintmode != GP_PAINTMODE_ERASER) {
/* turn off cursor...
* NOTE: this should be enough for now
* Just hiding this makes it seem like
@@ -2548,10 +2568,10 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
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);
}
@@ -2571,7 +2591,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
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
@@ -2579,13 +2599,13 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
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
@@ -2597,14 +2617,14 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* 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);
@@ -2613,11 +2633,11 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* 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
@@ -2630,18 +2650,18 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* 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
+ /* 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)
*/
@@ -2657,12 +2677,12 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
estate = OPERATOR_FINISHED;
}
}
- else {
+ 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? */
@@ -2695,19 +2715,19 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
case PADPLUSKEY:
p->radius += 5;
break;
-
+
case WHEELUPMOUSE: /* smaller */
case PADMINUS:
p->radius -= 5;
-
+
if (p->radius <= 0)
p->radius = 1;
break;
}
-
+
/* force refresh */
ED_region_tag_redraw(p->ar); /* just active area for now, since doing whole screen is too slow */
-
+
/* event handled, so just tag as running modal */
estate = OPERATOR_RUNNING_MODAL;
}
@@ -2719,16 +2739,16 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
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(p);
+ 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:
@@ -2736,11 +2756,11 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
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
@@ -2749,7 +2769,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
#endif
break;
}
-
+
/* return status code */
return estate;
}
@@ -2767,28 +2787,28 @@ static const EnumPropertyItem prop_gpencil_drawmodes[] = {
void GPENCIL_OT_draw(wmOperatorType *ot)
{
PropertyRNA *prop;
-
+
/* identifiers */
ot->name = "Grease Pencil Draw";
ot->idname = "GPENCIL_OT_draw";
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/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
index dc3483163bf..ac0b046e499 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -70,14 +70,14 @@
static int gpencil_select_poll(bContext *C)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
-
+
/* we just need some visible strokes, and to be in editmode */
if ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE)) {
/* TODO: include a check for visible strokes? */
if (gpd->layers.first)
return true;
}
-
+
return false;
}
@@ -88,16 +88,16 @@ 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");
-
+
if (gpd == NULL) {
BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
return OPERATOR_CANCELLED;
}
-
+
/* 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) {
@@ -107,7 +107,7 @@ static int gpencil_select_all_exec(bContext *C, wmOperator *op)
}
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,
@@ -122,21 +122,21 @@ static int gpencil_select_all_exec(bContext *C, wmOperator *op)
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;
}
}
@@ -151,7 +151,7 @@ static int gpencil_select_all_exec(bContext *C, wmOperator *op)
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) {
@@ -165,11 +165,11 @@ static int gpencil_select_all_exec(bContext *C, wmOperator *op)
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;
@@ -178,7 +178,7 @@ static int gpencil_select_all_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
}
-
+
/* updates */
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
@@ -190,14 +190,14 @@ void GPENCIL_OT_select_all(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
WM_operator_properties_select_all(ot);
}
@@ -207,26 +207,26 @@ 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;
}
-
+
/* 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 */
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
@@ -238,11 +238,11 @@ void GPENCIL_OT_select_linked(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -253,10 +253,10 @@ void GPENCIL_OT_select_linked(wmOperatorType *ot)
typedef enum eGP_SelectGrouped {
/* Select strokes in the same layer */
GP_SEL_SAME_LAYER = 0,
-
+
/* Select strokes with the same color */
GP_SEL_SAME_COLOR = 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 ? */
} eGP_SelectGrouped;
@@ -267,16 +267,16 @@ typedef enum eGP_SelectGrouped {
static void gp_select_same_layer(bContext *C)
{
Scene *scene = CTX_data_scene(C);
-
+
CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
{
bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0);
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)) {
@@ -286,18 +286,18 @@ static void gp_select_same_layer(bContext *C)
}
}
}
-
+
/* 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;
}
}
@@ -310,11 +310,11 @@ static void gp_select_same_layer(bContext *C)
static void gp_select_same_color(bContext *C)
{
/* First, build set containing all the colors of selected strokes
- * - We use the palette names, so that we can select all strokes with one
+ * - We use the palette names, so that we can select all strokes with one
* (potentially missing) color, and remap them to something else
*/
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) {
@@ -325,7 +325,7 @@ static void gp_select_same_color(bContext *C)
}
}
CTX_DATA_END;
-
+
/* Second, select any visible stroke that uses these colors */
CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
{
@@ -333,11 +333,11 @@ static void gp_select_same_color(bContext *C)
/* 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;
}
}
@@ -350,7 +350,7 @@ static void gp_select_same_color(bContext *C)
static int gpencil_select_grouped_exec(bContext *C, wmOperator *op)
{
eGP_SelectGrouped mode = RNA_enum_get(op->ptr, "type");
-
+
switch (mode) {
case GP_SEL_SAME_LAYER:
gp_select_same_layer(C);
@@ -358,12 +358,12 @@ static int gpencil_select_grouped_exec(bContext *C, wmOperator *op)
case GP_SEL_SAME_COLOR:
gp_select_same_color(C);
break;
-
+
default:
BLI_assert(!"unhandled select grouped gpencil mode");
break;
}
-
+
/* updates */
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
@@ -376,20 +376,20 @@ void GPENCIL_OT_select_grouped(wmOperatorType *ot)
{GP_SEL_SAME_COLOR, "COLOR", 0, "Color", "Shared colors"},
{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", "");
}
@@ -401,33 +401,33 @@ static int gpencil_select_first_exec(bContext *C, wmOperator *op)
{
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 */
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
@@ -439,18 +439,18 @@ void GPENCIL_OT_select_first(wmOperatorType *ot)
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");
}
@@ -461,33 +461,33 @@ static int gpencil_select_last_exec(bContext *C, wmOperator *op)
{
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 */
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
@@ -499,18 +499,18 @@ void GPENCIL_OT_select_last(wmOperatorType *ot)
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");
}
@@ -525,8 +525,8 @@ static int gpencil_select_more_exec(bContext *C, wmOperator *UNUSED(op))
bGPDspoint *pt;
int i;
bool prev_sel;
-
- /* First Pass: Go in forward order, expanding selection if previous was selected (pre changes)...
+
+ /* 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;
@@ -543,8 +543,8 @@ static int gpencil_select_more_exec(bContext *C, wmOperator *UNUSED(op))
prev_sel = false;
}
}
-
- /* Second Pass: Go in reverse order, doing the same as before (except in opposite order)
+
+ /* 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;
@@ -563,7 +563,7 @@ static int gpencil_select_more_exec(bContext *C, wmOperator *UNUSED(op))
}
}
CTX_DATA_END;
-
+
/* updates */
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
@@ -575,11 +575,11 @@ void GPENCIL_OT_select_more(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -595,8 +595,8 @@ static int gpencil_select_less_exec(bContext *C, wmOperator *UNUSED(op))
bGPDspoint *pt;
int i;
bool prev_sel;
-
- /* First Pass: Go in forward order, shrinking selection if previous was not selected (pre changes)...
+
+ /* 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;
@@ -613,8 +613,8 @@ static int gpencil_select_less_exec(bContext *C, wmOperator *UNUSED(op))
prev_sel = false;
}
}
-
- /* Second Pass: Go in reverse order, doing the same as before (except in opposite order)
+
+ /* 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;
@@ -634,7 +634,7 @@ static int gpencil_select_less_exec(bContext *C, wmOperator *UNUSED(op))
}
}
CTX_DATA_END;
-
+
/* updates */
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
@@ -646,11 +646,11 @@ void GPENCIL_OT_select_less(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -671,7 +671,7 @@ static bool gp_stroke_do_circle_sel(
int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
int i;
bool changed = false;
-
+
if (gps->totpoints == 1) {
if (!parented) {
gp_point_to_xy(gsc, gps, gps->points, &x0, &y0);
@@ -681,7 +681,7 @@ static bool gp_stroke_do_circle_sel(
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 */
@@ -695,13 +695,13 @@ static bool gp_stroke_do_circle_sel(
gps->points->flag &= ~GP_SPOINT_SELECT;
gps->flag &= ~GP_STROKE_SELECT;
}
-
+
return true;
}
}
}
else {
- /* Loop over the points in the stroke, checking for intersections
+ /* 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++) {
@@ -720,43 +720,43 @@ static bool gp_stroke_do_circle_sel(
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)))
{
int mval[2] = {mx, my};
int mvalo[2] = {mx, 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
+ /* 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)
+ * as we only do n-1 loops through)
*/
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;
}
}
}
}
-
+
/* Ensure that stroke selection is in sync with its points */
BKE_gpencil_stroke_sync_selection(gps);
}
-
+
return changed;
}
@@ -764,36 +764,36 @@ static bool gp_stroke_do_circle_sel(
static int gpencil_circle_select_exec(bContext *C, wmOperator *op)
{
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");
-
+
bool select = !RNA_boolean_get(op->ptr, "deselect");
-
+
GP_SpaceConversion gsc = {NULL};
rcti rect = {0}; /* for bounding rect around circle (for quicky intersection testing) */
-
+
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);
-
-
+
+
/* 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(C, gpl, gps)
{
@@ -807,7 +807,7 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op)
if (changed) {
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
}
-
+
return OPERATOR_FINISHED;
}
@@ -817,17 +817,17 @@ void GPENCIL_OT_select_circle(wmOperatorType *ot)
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;
-
+
/* properties */
WM_operator_properties_gesture_circle_select(ot);
}
@@ -838,45 +838,45 @@ void GPENCIL_OT_select_circle(wmOperatorType *ot)
static int gpencil_border_select_exec(bContext *C, wmOperator *op)
{
ScrArea *sa = CTX_wm_area(C);
-
+
const bool select = !RNA_boolean_get(op->ptr, "deselect");
const bool extend = RNA_boolean_get(op->ptr, "extend");
-
+
GP_SpaceConversion gsc = {NULL};
rcti rect = {0};
-
+
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 (select && !extend) {
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;
}
-
+
/* get settings from operator */
WM_operator_properties_border_to_rcti(op, &rect);
-
+
/* select/deselect points */
GP_EDITABLE_STROKES_BEGIN(C, gpl, gps)
{
@@ -919,7 +919,7 @@ static int gpencil_border_select_exec(bContext *C, wmOperator *op)
if (changed) {
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
}
-
+
return OPERATOR_FINISHED;
}
@@ -929,18 +929,18 @@ void GPENCIL_OT_select_border(wmOperatorType *ot)
ot->name = "Border Select";
ot->description = "Select Grease Pencil strokes within a rectangular region";
ot->idname = "GPENCIL_OT_select_border";
-
+
/* callbacks */
ot->invoke = WM_gesture_border_invoke;
ot->exec = gpencil_border_select_exec;
ot->modal = WM_gesture_border_modal;
ot->cancel = WM_gesture_border_cancel;
-
+
ot->poll = gpencil_select_poll;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* rna */
WM_operator_properties_gesture_border_select(ot);
}
@@ -952,41 +952,41 @@ static int gpencil_lasso_select_exec(bContext *C, wmOperator *op)
{
GP_SpaceConversion gsc = {NULL};
rcti rect = {0};
-
+
const bool extend = RNA_boolean_get(op->ptr, "extend");
const bool select = !RNA_boolean_get(op->ptr, "deselect");
-
+
int mcords_tot;
const int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
-
+
bool changed = false;
-
+
/* sanity check */
if (mcords == NULL)
return OPERATOR_PASS_THROUGH;
-
+
/* compute boundbox of lasso (for faster testing later) */
BLI_lasso_boundbox(&rect, mcords, mcords_tot);
-
+
/* init space conversion stuff */
gp_point_conversion_init(C, &gsc);
-
+
/* deselect all strokes first? */
if (select && !extend) {
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(C, gpl, gps)
{
@@ -1027,12 +1027,12 @@ static int gpencil_lasso_select_exec(bContext *C, wmOperator *op)
/* cleanup */
MEM_freeN((void *)mcords);
-
+
/* updates */
if (changed) {
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
}
-
+
return OPERATOR_FINISHED;
}
@@ -1041,16 +1041,16 @@ 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;
-
+
/* properties */
WM_operator_properties_gesture_lasso_select(ot);
}
@@ -1061,36 +1061,36 @@ void GPENCIL_OT_select_lasso(wmOperatorType *ot)
static int gpencil_select_exec(bContext *C, wmOperator *op)
{
ScrArea *sa = CTX_wm_area(C);
-
+
/* "radius" is simply a threshold (screen space) to make it easier to test with a tolerance */
const float radius = 0.75f * 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};
-
+
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;
}
-
+
/* 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(C, gpl, gps)
@@ -1133,38 +1133,38 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
if (ELEM(NULL, hit_stroke, hit_point)) {
return OPERATOR_CANCELLED;
}
-
+
/* adjust selection behaviour - for toggle option */
if (toggle) {
deselect = (hit_point->flag & GP_SPOINT_SELECT) != 0;
}
-
+
/* If not extending selection, deselect everything else */
if (extend == false) {
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;
}
-
+
/* 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)
@@ -1172,7 +1172,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
else
pt->flag &= ~GP_SPOINT_SELECT;
}
-
+
/* stroke too... */
if (deselect == false)
hit_stroke->flag |= GP_STROKE_SELECT;
@@ -1189,17 +1189,17 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
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) {
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
}
-
+
return OPERATOR_FINISHED;
}
@@ -1212,26 +1212,26 @@ static int gpencil_select_invoke(bContext *C, wmOperator *op, const wmEvent *eve
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_REGISTER | OPTYPE_UNDO;
-
+
/* 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 202d7630ae0..d35df8bc380 100644
--- a/source/blender/editors/gpencil/gpencil_undo.c
+++ b/source/blender/editors/gpencil/gpencil_undo.c
@@ -55,7 +55,7 @@
typedef struct bGPundonode {
struct bGPundonode *next, *prev;
-
+
char name[BKE_UNDO_STR_MAX];
struct bGPdata *gpd;
} bGPundonode;
@@ -71,9 +71,9 @@ int ED_gpencil_session_active(void)
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) {
@@ -92,18 +92,18 @@ int ED_undo_gpencil_step(bContext *C, int step, const char *name)
}
}
}
-
+
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);
@@ -112,9 +112,9 @@ int ED_undo_gpencil_step(bContext *C, int step, const char *name)
}
}
}
-
+
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -129,7 +129,7 @@ static void gpencil_undo_free_node(bGPundonode *undo_node)
* 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);
}
@@ -137,65 +137,65 @@ static void gpencil_undo_free_node(bGPundonode *undo_node)
void gpencil_undo_push(bGPdata *gpd)
{
bGPundonode *undo_node;
-
+
//printf("\t\tGP - undo push\n");
-
+
if (cur_node) {
/* remove all un-done nodes from stack */
undo_node = cur_node->next;
-
+
while (undo_node) {
bGPundonode *next_node = undo_node->next;
-
+
gpencil_undo_free_node(undo_node);
BLI_freelinkN(&undo_nodes, undo_node);
-
+
undo_node = next_node;
}
}
-
+
/* limit number of undo steps to the maximum undo steps
- * - to prevent running out of memory during **really**
+ * - 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;
-
+
if (steps >= U.undosteps) {
gpencil_undo_free_node(undo_node);
BLI_freelinkN(&undo_nodes, undo_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(G.main, gpd, true);
-
+ undo_node->gpd = BKE_gpencil_data_duplicate(NULL, gpd, true);
+
cur_node = undo_node;
-
+
BLI_addtail(&undo_nodes, undo_node);
}
void gpencil_undo_finish(void)
{
bGPundonode *undo_node = undo_nodes.first;
-
+
while (undo_node) {
gpencil_undo_free_node(undo_node);
undo_node = undo_node->next;
}
-
+
BLI_freelistN(&undo_nodes);
-
+
cur_node = NULL;
}
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index babe68ba439..4ee3bdd587e 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -47,10 +47,11 @@
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
+#include "BKE_action.h"
#include "BKE_context.h"
#include "BKE_gpencil.h"
+#include "BKE_main.h"
#include "BKE_tracking.h"
-#include "BKE_action.h"
#include "WM_api.h"
@@ -82,16 +83,16 @@ bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrAr
*/
if (sa) {
SpaceLink *sl = sa->spacedata.first;
-
+
switch (sa->spacetype) {
case SPACE_VIEW3D: /* 3D-View */
{
BLI_assert(scene && ELEM(scene->toolsettings->gpencil_src,
GP_TOOL_SOURCE_SCENE, GP_TOOL_SOURCE_OBJECT));
-
+
if (scene->toolsettings->gpencil_src == GP_TOOL_SOURCE_OBJECT) {
/* legacy behaviour for usage with old addons requiring object-linked to objects */
-
+
/* just in case no active/selected object... */
if (ob && (ob->flag & SELECT)) {
/* for now, as long as there's an object, default to using that in 3D-View */
@@ -109,21 +110,21 @@ bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrAr
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 (ptr) RNA_id_pointer_create(&snode->nodetree->id, 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 (ptr) RNA_pointer_create(screen_id, &RNA_SpaceSequenceEditor, sseq, ptr);
@@ -132,7 +133,7 @@ bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrAr
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 (ptr) RNA_pointer_create(screen_id, &RNA_SpaceImageEditor, sima, ptr);
@@ -142,23 +143,23 @@ bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrAr
{
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 (ptr)
RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, ptr);
-
+
return &track->gpd;
}
else {
if (ptr)
RNA_id_pointer_create(&clip->id, ptr);
-
+
return &clip->gpd;
}
}
@@ -168,7 +169,7 @@ bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrAr
return NULL;
}
}
-
+
/* just fall back on the scene's GP data */
if (ptr) RNA_id_pointer_create((ID *)scene, ptr);
return (scene) ? &scene->gpd : NULL;
@@ -181,7 +182,7 @@ bGPdata **ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *ptr)
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, scene, sa, ob, ptr);
}
@@ -211,7 +212,7 @@ bGPdata *ED_gpencil_data_get_active_v3d(Scene *scene, ViewLayer *view_layer)
/* We have to make sure active object is actually visible and selected, else we must use default scene gpd,
* to be consistent with ED_gpencil_data_get_active's behavior.
*/
-
+
if (base && TESTBASE(base)) {
gpd = base->object->gpd;
}
@@ -239,7 +240,7 @@ bool ED_gpencil_has_keyframe_v3d(Scene *scene, Object *ob, int cfra)
}
}
}
-
+
if (ob && ob->gpd) {
bGPDlayer *gpl = BKE_gpencil_layer_getactive(ob->gpd);
if (gpl) {
@@ -253,7 +254,7 @@ bool ED_gpencil_has_keyframe_v3d(Scene *scene, Object *ob, int cfra)
}
}
}
-
+
return false;
}
@@ -272,7 +273,7 @@ int gp_active_layer_poll(bContext *C)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
-
+
return (gpl != NULL);
}
@@ -317,25 +318,25 @@ const EnumPropertyItem *ED_gpencil_layers_enum_itemf(
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
+ else
item_tmp.icon = ICON_NONE;
-
+
RNA_enum_item_add(&item, &totitem, &item_tmp);
}
-
+
RNA_enum_item_end(&item, &totitem);
*r_free = true;
@@ -351,11 +352,11 @@ const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(
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? */
{
@@ -365,25 +366,25 @@ const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(
item_tmp.value = -1;
item_tmp.icon = ICON_ZOOMIN;
RNA_enum_item_add(&item, &totitem, &item_tmp);
-
+
/* separator */
RNA_enum_item_add_separator(&item, &totitem);
}
-
+
/* Existing layers */
for (gpl = gpd->layers.first, i = 0; 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
+ else
item_tmp.icon = ICON_NONE;
-
+
RNA_enum_item_add(&item, &totitem, &item_tmp);
}
-
+
RNA_enum_item_end(&item, &totitem);
*r_free = true;
@@ -412,11 +413,11 @@ bool gp_stroke_inside_circle(const int mval[2], const int UNUSED(mvalo[2]),
const float mval_fl[2] = {mval[0], mval[1]};
const float screen_co_a[2] = {x0, y0};
const float screen_co_b[2] = {x1, y1};
-
+
if (edge_inside_circle(mval_fl, rad, screen_co_a, screen_co_b)) {
return true;
}
-
+
/* not inside */
return false;
}
@@ -469,7 +470,7 @@ bool ED_gpencil_stroke_color_use(const bGPDlayer *gpl, const bGPDstroke *gps)
if (((gpl->flag & GP_LAYER_UNLOCK_COLOR) == 0) && (palcolor->flag & PC_COLOR_LOCKED))
return false;
}
-
+
return true;
}
@@ -524,30 +525,30 @@ 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->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 *graph = CTX_data_depsgraph(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(graph, ar, v3d, 0);
-
+ 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); /* no shift */
@@ -563,7 +564,7 @@ void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc)
* \param diff_mat Matrix with the difference between original parent matrix
* \param[out] r_pt Pointer to new point after apply matrix
*/
-void gp_point_to_parent_space(bGPDspoint *pt, float diff_mat[4][4], bGPDspoint *r_pt)
+void gp_point_to_parent_space(bGPDspoint *pt, float diff_mat[4][4], bGPDspoint *r_pt)
{
float fpt[3];
@@ -626,12 +627,12 @@ void gp_point_to_xy(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt,
View2D *v2d = gsc->v2d;
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];
@@ -679,12 +680,12 @@ void gp_point_to_xy_fl(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt,
View2D *v2d = gsc->v2d;
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];
@@ -698,10 +699,10 @@ void gp_point_to_xy_fl(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt,
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;
@@ -748,22 +749,22 @@ bool gp_point_xy_to_3d(GP_SpaceConversion *gsc, Scene *scene, const float screen
float *rvec = ED_view3d_cursor3d_get(scene, v3d)->location;
float ref[3] = {rvec[0], rvec[1], rvec[2]};
float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL);
-
+
float mval_f[2], mval_prj[2];
float dvec[3];
-
+
copy_v2_v2(mval_f, screen_co);
-
+
if (ED_view3d_project_float_global(gsc->ar, ref, 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 false;
}
}
@@ -780,19 +781,19 @@ bool gp_smooth_stroke(bGPDstroke *gps, int i, float inf, bool affect_pressure)
bGPDspoint *pt = &gps->points[i];
float pressure = 0.0f;
float sco[3] = {0.0f};
-
+
/* Do nothing if not enough points to smooth out */
if (gps->totpoints <= 2) {
return false;
}
-
+
/* Only affect endpoints by a fraction of the normal strength,
* to prevent the stroke from shrinking too much
*/
if ((i == 0) || (i == gps->totpoints - 1)) {
inf *= 0.1f;
}
-
+
/* Compute smoothed coordinate by taking the ones nearby */
/* XXX: This is potentially slow, and suffers from accumulation error as earlier points are handled before later ones */
{
@@ -800,14 +801,14 @@ bool gp_smooth_stroke(bGPDstroke *gps, int i, float inf, bool affect_pressure)
const int steps = 2;
const float average_fac = 1.0f / (float)(steps * 2 + 1);
int step;
-
+
/* add the point itself */
madd_v3_v3fl(sco, &pt->x, average_fac);
-
+
if (affect_pressure) {
pressure += pt->pressure * average_fac;
}
-
+
/* n-steps before/after current point */
// XXX: review how the endpoints are treated by this algorithm
// XXX: falloff measures should also introduce some weighting variations, so that further-out points get less weight
@@ -815,17 +816,17 @@ bool gp_smooth_stroke(bGPDstroke *gps, int i, float inf, bool affect_pressure)
bGPDspoint *pt1, *pt2;
int before = i - step;
int after = i + step;
-
+
CLAMP_MIN(before, 0);
CLAMP_MAX(after, gps->totpoints - 1);
-
+
pt1 = &gps->points[before];
pt2 = &gps->points[after];
-
+
/* add both these points to the average-sum (s += p[i]/n) */
madd_v3_v3fl(sco, &pt1->x, average_fac);
madd_v3_v3fl(sco, &pt2->x, average_fac);
-
+
#if 0
/* XXX: Disabled because get weird result */
/* do pressure too? */
@@ -836,17 +837,17 @@ bool gp_smooth_stroke(bGPDstroke *gps, int i, float inf, bool affect_pressure)
#endif
}
}
-
+
/* Based on influence factor, blend between original and optimal smoothed coordinate */
interp_v3_v3v3(&pt->x, &pt->x, sco, inf);
-
+
#if 0
/* XXX: Disabled because get weird result */
if (affect_pressure) {
pt->pressure = pressure;
}
#endif
-
+
return true;
}
@@ -939,22 +940,22 @@ void gp_subdivide_stroke(bGPDstroke *gps, const int new_totpoints)
gps->points[new_totpoints - y] = gps->points[i];
y += 2;
}
-
+
/* Create interpolated points */
for (int i = 0; i < new_totpoints - 1; i += 2) {
bGPDspoint *prev = &gps->points[i];
bGPDspoint *pt = &gps->points[i + 1];
bGPDspoint *next = &gps->points[i + 2];
-
+
/* Interpolate all values */
interp_v3_v3v3(&pt->x, &prev->x, &next->x, 0.5f);
-
+
pt->pressure = interpf(prev->pressure, next->pressure, 0.5f);
pt->strength = interpf(prev->strength, next->strength, 0.5f);
CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
pt->time = interpf(prev->time, next->time, 0.5f);
}
-
+
/* Update to new total number of points */
gps->totpoints = new_totpoints;
}
@@ -964,7 +965,7 @@ void gp_subdivide_stroke(bGPDstroke *gps, const int new_totpoints)
* \param gps Stroke data
* \param brush Brush data
*/
-void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush)
+void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush, RNG *rng)
{
bGPDspoint *pt1, *pt2, *pt3;
float v1[3];
@@ -987,20 +988,20 @@ void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush)
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_frand() * (brush->draw_random_sub / 10.0f);
+ const float fac = BLI_rng_get_float(rng) * (brush->draw_random_sub / 10.0f);
float svec[3];
copy_v3_v3(svec, ortho);
- if (BLI_frand() > 0.5f) {
+ if (BLI_rng_get_float(rng) > 0.5f) {
mul_v3_fl(svec, -fac);
}
else {
diff --git a/source/blender/editors/include/BIF_gl.h b/source/blender/editors/include/BIF_gl.h
index f91e7d42bca..e2e110ffc31 100644
--- a/source/blender/editors/include/BIF_gl.h
+++ b/source/blender/editors/include/BIF_gl.h
@@ -48,4 +48,3 @@
#define GLA_PIXEL_OFS 0.375f
#endif /* #ifdef __BIF_GL_H__ */
-
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index 2165402b6d3..59a54f03e56 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
@@ -36,6 +36,7 @@ struct ListBase;
struct AnimData;
struct bContext;
+struct Main;
struct wmKeyConfig;
struct ReportList;
struct ScrArea;
@@ -64,30 +65,32 @@ struct PropertyRNA;
/* --------------- Context --------------------- */
-/* This struct defines a structure used for animation-specific
+/* This struct defines a structure used for animation-specific
* 'context' information
*/
typedef struct bAnimContext {
void *data; /* data to be filtered for use in animation editor */
short datatype; /* type of data eAnimCont_Types */
-
+
short mode; /* editor->mode */
short spacetype; /* sa->spacetype */
short regiontype; /* active region -> type (channels or main) */
-
+
struct ScrArea *sa; /* editor host */
struct SpaceLink *sl; /* editor data */
struct ARegion *ar; /* region within editor */
-
+
struct bDopeSheet *ads; /* dopesheet data for editor (or which is being used) */
-
+
+ struct Depsgraph *depsgraph; /* active dependency graph */
+ struct Main *bmain; /* Current Main */
struct Scene *scene; /* active scene */
struct ViewLayer *view_layer; /* active scene layer */
struct Object *obact; /* active object */
ListBase *markers; /* active set of markers */
-
+
struct ReportList *reports; /* pointer to current reports list */
-
+
float yscale_fac; /* scale factor for height of channels (i.e. based on the size of keyframes) */
} bAnimContext;
@@ -108,24 +111,24 @@ typedef enum eAnimCont_Types {
/* --------------- Channels -------------------- */
-/* This struct defines a structure used for quick and uniform access for
+/* This struct defines a structure used for quick and uniform access for
* channels of animation data
*/
typedef struct bAnimListElem {
struct bAnimListElem *next, *prev;
-
+
void *data; /* source data this elem represents */
int type; /* (eAnim_ChannelType) one of the ANIMTYPE_* values */
int flag; /* copy of elem's flags for quick access */
int index; /* for un-named data, the index of the data in its collection */
-
+
char update; /* (eAnim_Update_Flags) tag the element for updating */
char tag; /* tag the included data. Temporary always */
short datatype; /* (eAnim_KeyType) type of motion data to expect */
void *key_data; /* motion data - mostly F-Curves, but can be other types too */
-
-
+
+
/* 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
@@ -137,12 +140,12 @@ typedef struct bAnimListElem {
*/
struct ID *id; /* ID block that channel is attached to */
struct AnimData *adt; /* source of the animation data attached to ID block (for convenience) */
-
+
void *owner; /* for per-element F-Curves (e.g. NLA Control Curves), the element that this represents (e.g. NlaStrip) */
} bAnimListElem;
-/* Some types for easier type-testing
+/* Some types for easier type-testing
* NOTE: need to keep the order of these synchronized with the channels define code
* which is used for drawing and handling channel lists for
*/
@@ -150,20 +153,20 @@ 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,
@@ -182,18 +185,18 @@ typedef enum eAnim_ChannelType {
ANIMTYPE_DSSPK,
ANIMTYPE_DSGPENCIL,
ANIMTYPE_DSMCLIP,
-
+
ANIMTYPE_SHAPEKEY,
-
+
ANIMTYPE_GPDATABLOCK,
ANIMTYPE_GPLAYER,
-
+
ANIMTYPE_MASKDATABLOCK,
ANIMTYPE_MASKLAYER,
-
+
ANIMTYPE_NLATRACK,
ANIMTYPE_NLAACTION,
-
+
/* always as last item, the total number of channel types... */
ANIMTYPE_NUM_TYPES
} eAnim_ChannelType;
@@ -238,31 +241,31 @@ typedef enum eAnimFilter_Flags {
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 */
// NOTE: 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),
@@ -324,7 +327,7 @@ typedef enum eAnimFilter_Flags {
/* Grease Pencil only */
/* Grease Pencil datablock settings */
-#define EXPANDED_GPD(gpd) (gpd->flag & GP_DATA_EXPAND)
+#define EXPANDED_GPD(gpd) (gpd->flag & GP_DATA_EXPAND)
/* Grease Pencil Layer settings */
#define EDITABLE_GPL(gpl) ((gpl->flag & GP_LAYER_LOCKED) == 0)
#define SEL_GPL(gpl) (gpl->flag & GP_LAYER_SELECT)
@@ -386,12 +389,12 @@ typedef enum eAnimFilter_Flags {
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.
+ * Returns whether the operation was successful.
*/
bool ANIM_animdata_get_context(const struct bContext *C, bAnimContext *ac);
-/* Obtain current anim-data context (from Animation Editor) given
- * that Blender Context info has already been set.
+/* Obtain current anim-data context (from Animation Editor) given
+ * that Blender Context info has already been set.
* Returns whether the operation was successful.
*/
bool ANIM_animdata_context_getdata(bAnimContext *ac);
@@ -443,7 +446,7 @@ typedef struct bAnimChannelType {
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]);
@@ -453,14 +456,14 @@ typedef struct bAnimChannelType {
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);
@@ -489,28 +492,28 @@ void ANIM_channel_draw_widgets(const struct bContext *C, bAnimContext *ac, bAnim
/* ------------------------ Editing API -------------------------- */
-/* Check if some setting for a channel is enabled
+/* Check if some setting for a channel is enabled
* Returns: 1 = On, 0 = Off, -1 = Invalid
*
* - setting: eAnimChannel_Settings
*/
short ANIM_channel_setting_get(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting);
-/* Change value of some setting for a channel
+/* 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);
-/* Flush visibility (for Graph Editor) changes up/down hierarchy for changes in the given setting
+/* 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
* -> filtered using ANIMFILTER_CHANNELS only, since if we took VISIBLE too,
* then the channels under closed expanders get ignored...
* - ale_setting: the anim channel (not in the anim_data list directly, though occurring there)
- * with the new state of the setting that we want flushed up/down the hierarchy
+ * with the new state of the setting that we want flushed up/down the hierarchy
* - setting: type of setting to set
- * - on: whether the visibility setting has been enabled or disabled
+ * - 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);
@@ -578,8 +581,8 @@ void ANIM_fmodifiers_copybuf_free(void);
*/
bool ANIM_fmodifiers_copy_to_buf(ListBase *modifiers, bool active);
-/* 'Paste' the F-Modifier(s) from the buffer to the specified list
- * - replace: free all the existing modifiers to leave only the pasted ones
+/* 'Paste' the F-Modifier(s) from the buffer to the specified list
+ * - replace: free all the existing modifiers to leave only the pasted ones
*/
bool ANIM_fmodifiers_paste_from_buf(ListBase *modifiers, bool replace, struct FCurve *curve);
@@ -653,7 +656,7 @@ float ANIM_unit_mapping_get_factor(struct Scene *scene, struct ID *id, struct FC
*/
#define BEZKEYTYPE(bezt) ((bezt)->hide)
-/* set/clear/toggle macro
+/* set/clear/toggle macro
* - channel - channel with a 'flag' member that we're setting
* - smode - 0=clear, 1=set, 2=invert
* - sflag - bitflag to set
@@ -664,8 +667,8 @@ float ANIM_unit_mapping_get_factor(struct Scene *scene, struct ID *id, struct FC
else if (smode == ACHANNEL_SETFLAG_ADD) (channel)->flag |= (sflag); \
else (channel)->flag &= ~(sflag); \
}
-
-/* set/clear/toggle macro, where the flag is negative
+
+/* set/clear/toggle macro, where the flag is negative
* - channel - channel with a 'flag' member that we're setting
* - smode - 0=clear, 1=set, 2=invert
* - sflag - bitflag to set
@@ -681,15 +684,16 @@ float ANIM_unit_mapping_get_factor(struct Scene *scene, struct ID *id, struct FC
/* --------- anim_deps.c, animation updates -------- */
void ANIM_id_update(struct Scene *scene, struct ID *id);
-void ANIM_list_elem_update(struct Scene *scene, bAnimListElem *ale);
+void ANIM_list_elem_update(struct Main *bmain, struct Scene *scene, bAnimListElem *ale);
/* data -> channels syncing */
void ANIM_sync_animchannels_to_data(const struct bContext *C);
void ANIM_center_frame(struct bContext *C, int smooth_viewtx);
+
/* ************************************************* */
/* OPERATORS */
-
+
/* generic animation channels */
void ED_operatortypes_animchannels(void);
void ED_keymap_animchannels(struct wmKeyConfig *keyconf);
@@ -697,7 +701,7 @@ void ED_keymap_animchannels(struct wmKeyConfig *keyconf);
/* generic time editing */
void ED_operatortypes_anim(void);
void ED_keymap_anim(struct wmKeyConfig *keyconf);
-
+
/* space_graph */
void ED_operatormacros_graph(void);
/* space_action */
@@ -709,11 +713,14 @@ 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,
+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);
+
/* ************************************************ */
#endif /* __ED_ANIM_API_H__ */
-
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index 2934745484a..cb422c2fb95 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -42,6 +42,7 @@ struct bPoseChannel;
struct Depsgraph;
struct IDProperty;
struct ListBase;
+struct Main;
struct MeshDeformModifierData;
struct Mesh;
struct Object;
@@ -73,7 +74,7 @@ typedef struct EditBone {
* animation are automatically relative to the bones' rest positions*/
int flag;
int layer;
-
+
float dist, weight;
float xwidth, length, zwidth; /* put them in order! transform uses this as scale */
float rad_head, rad_tail;
@@ -86,7 +87,7 @@ typedef struct EditBone {
float scaleIn, scaleOut;
float oldlength; /* for envelope scaling */
-
+
short segments;
/* Used for display */
@@ -135,7 +136,7 @@ void ED_operatormacros_armature(void);
void ED_keymap_armature(struct wmKeyConfig *keyconf);
/* editarmature.c */
-void ED_armature_from_edit(struct bArmature *arm);
+void ED_armature_from_edit(struct Main *bmain, struct bArmature *arm);
void ED_armature_to_edit(struct bArmature *arm);
void ED_armature_edit_free(struct bArmature *arm);
@@ -181,11 +182,11 @@ 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 Object *ob, float cursor[3], int centermode, int around);
+void ED_armature_origin_set(struct Main *bmain, struct Object *ob, 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 Object *ob, float mat[4][4], const bool do_props);
-void ED_armature_transform(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
#define ARM_GROUPS_ENVELOPE 2
@@ -197,8 +198,8 @@ void ED_object_vgroup_calc_from_armature(
/* 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 bArmature *arm, const char *oldnamep, const char *newnamep);
-void ED_armature_bones_flip_names(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);
diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h
index da726cb8000..8fcfb4743d5 100644
--- a/source/blender/editors/include/ED_curve.h
+++ b/source/blender/editors/include/ED_curve.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -32,15 +32,16 @@
#define __ED_CURVE_H__
struct bContext;
+struct BezTriple;
+struct BPoint;
+struct Curve;
+struct EditNurb;
+struct Main;
struct Nurb;
struct Object;
struct Text;
struct wmOperator;
struct wmKeyConfig;
-struct Curve;
-struct EditNurb;
-struct BezTriple;
-struct BPoint;
struct UndoType;
/* curve_ops.c */
@@ -51,7 +52,7 @@ void ED_keymap_curve(struct wmKeyConfig *keyconf);
/* editcurve.c */
struct ListBase *object_editcurve_get(struct Object *ob);
-void ED_curve_editnurb_load(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);
diff --git a/source/blender/editors/include/ED_datafiles.h b/source/blender/editors/include/ED_datafiles.h
index 661ab58b98c..7d509d1243a 100644
--- a/source/blender/editors/include/ED_datafiles.h
+++ b/source/blender/editors/include/ED_datafiles.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -242,4 +242,3 @@ extern char datatoc_mc24_jpg[];
#endif /* __ED_DATAFILES_H__ */
-
diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h
index 92acfa6c1d2..64739d968b8 100644
--- a/source/blender/editors/include/ED_fileselect.h
+++ b/source/blender/editors/include/ED_fileselect.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -113,6 +113,17 @@ void ED_file_change_dir(struct bContext *C);
/* File menu stuff */
+/* FSMenuEntry's without paths indicate separators */
+typedef struct FSMenuEntry {
+ struct FSMenuEntry *next;
+
+ 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,
@@ -145,4 +156,3 @@ char *ED_fsmenu_entry_get_name(struct FSMenuEntry *fsentry);
void ED_fsmenu_entry_set_name(struct FSMenuEntry *fsentry, const char *name);
#endif /* __ED_FILESELECT_H__ */
-
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index 57ca1f04c0a..f1f2ce29e7f 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -87,7 +87,7 @@ typedef struct tGPDinterpolate {
void *draw_handle_screen; /* handle for drawing strokes while operator is running screen stuff */
} tGPDinterpolate;
-/* Temporary 'Stroke Point' data
+/* Temporary 'Stroke Point' data
*
* Used as part of the 'stroke cache' used during drawing of new strokes
*/
diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h
index cb824b3c9b7..ed9102a2d8b 100644
--- a/source/blender/editors/include/ED_image.h
+++ b/source/blender/editors/include/ED_image.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -17,7 +17,7 @@
*
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -43,7 +43,7 @@ struct ViewLayer;
/* image_edit.c, exported for transform */
struct Image *ED_space_image(struct SpaceImage *sima);
-void ED_space_image_set(struct SpaceImage *sima, struct Scene *scene, struct Object *obedit, struct Image *ima);
+void ED_space_image_set(struct Main *bmain, struct SpaceImage *sima, struct Scene *scene, struct Object *obedit, struct Image *ima);
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);
@@ -60,8 +60,8 @@ void ED_space_image_get_uv_aspect(struct SpaceImage *sima, float *aspx, float *a
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 wmWindowManager *wm, struct Scene *scene);
-void ED_space_image_uv_sculpt_update(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]);
@@ -85,4 +85,3 @@ void ED_image_draw_info(struct Scene *scene, struct ARegion *ar, bool color_mana
bool ED_space_image_show_cache(struct SpaceImage *sima);
#endif /* __ED_IMAGE_H__ */
-
diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h
index 62f1a617fcb..9b0b2c970b2 100644
--- a/source/blender/editors/include/ED_keyframes_draw.h
+++ b/source/blender/editors/include/ED_keyframes_draw.h
@@ -53,17 +53,17 @@ struct DLRBT_Tree;
typedef struct ActKeyColumn {
/* ListBase linkage */
struct ActKeyColumn *next, *prev;
-
+
/* sorting-tree linkage */
struct ActKeyColumn *left, *right; /* 'children' of this node, less than and greater than it (respectively) */
struct ActKeyColumn *parent; /* parent of this node in the tree */
char tree_col; /* DLRB_BLACK or DLRB_RED */
-
+
/* keyframe info */
char key_type; /* eBezTripe_KeyframeType */
short sel;
float cfra;
-
+
/* only while drawing - used to determine if long-keyframe needs to be drawn */
short modified;
short totcurve;
@@ -73,21 +73,21 @@ typedef struct ActKeyColumn {
typedef struct ActKeyBlock {
/* ListBase linkage */
struct ActKeyBlock *next, *prev;
-
+
/* sorting-tree linkage */
struct ActKeyBlock *left, *right; /* 'children' of this node, less than and greater than it (respectively) */
struct ActKeyBlock *parent; /* parent of this node in the tree */
char tree_col; /* DLRB_BLACK or DLRB_RED */
-
+
/* key-block info */
char sel;
short flag;
float val;
float start, end;
-
+
/* only while drawing - used to determine if block needs to be drawn */
short modified;
- short totcurve;
+ short totcurve;
} ActKeyBlock;
/* ActKeyBlock - Flag */
diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h
index c0eb88cd982..5787a63d324 100644
--- a/source/blender/editors/include/ED_keyframes_edit.h
+++ b/source/blender/editors/include/ED_keyframes_edit.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
@@ -141,12 +141,12 @@ typedef enum eKeyframeVertOk {
typedef enum eKeyframeIterFlags {
/* 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 "f2" parameter */
KED_F2_NLA_UNMAP = (1 << 2),
} eKeyframeIterFlags;
@@ -165,7 +165,7 @@ typedef struct KeyframeEditData {
struct FCurve *fcu; /* F-Curve that is being iterated over */
int curIndex; /* index of current keyframe being iterated over */
float channel_y; /* y-position of midpoint of the channel (for the dopesheet) */
-
+
/* flags */
eKeyframeVertOk curflags; /* current flags for the keyframe we're reached in the iteration process */
eKeyframeIterFlags iterflags; /* settings for iteration process */
@@ -243,8 +243,8 @@ KeyframeEditFunc ANIM_editkeyframes_easing(short mode);
/* -------- BezTriple Callbacks (Selection Map) ---------- */
-/* Get a callback to populate the selection settings map
- * requires: ked->custom = char[] of length fcurve->totvert
+/* Get a callback to populate the selection settings map
+ * requires: ked->custom = char[] of length fcurve->totvert
*/
KeyframeEditFunc ANIM_editkeyframes_buildselmap(short mode);
@@ -262,7 +262,7 @@ short bezt_calc_average(KeyframeEditData *ked, struct BezTriple *bezt);
short bezt_to_cfraelem(KeyframeEditData *ked, struct BezTriple *bezt);
/* used to remap times from one range to another
- * requires: ked->custom = KeyframeEditCD_Remap
+ * requires: ked->custom = KeyframeEditCD_Remap
*/
void bezt_remap_times(KeyframeEditData *ked, struct BezTriple *bezt);
diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h
index 4e3c92f0dc4..5882c44a9b3 100644
--- a/source/blender/editors/include/ED_keyframing.h
+++ b/source/blender/editors/include/ED_keyframing.h
@@ -50,6 +50,8 @@ struct bPoseChannel;
struct bContext;
struct ReportList;
+struct Depsgraph;
+
struct PointerRNA;
struct PropertyRNA;
struct EnumPropertyItem;
@@ -59,19 +61,19 @@ struct EnumPropertyItem;
/* ************ Keyframing Management **************** */
-/* Get the active settings for keyframing settings from context (specifically the given scene)
+/* Get the active settings for keyframing settings from context (specifically the given scene)
* - incl_mode: include settings from keyframing mode in the result (i.e. replace only)
*/
short ANIM_get_keyframing_flags(struct Scene *scene, short incl_mode);
/* -------- */
-/* Get (or add relevant data to be able to do so) the Active Action for the given
+/* Get (or add relevant data to be able to do so) the Active Action for the given
* Animation Data block, given an ID block where the Animation Data should reside.
*/
-struct bAction *verify_adt_action(struct ID *id, short add);
+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.
+/* 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 bAction *act, const char group[], struct PointerRNA *ptr,
@@ -94,7 +96,7 @@ void update_autoflags_fcurve(struct FCurve *fcu, struct bContext *C, struct Repo
*/
int insert_bezt_fcurve(struct FCurve *fcu, const struct BezTriple *bezt, eInsertKeyFlags flag);
-/* Main Keyframing API call:
+/* Main Keyframing API call:
* Use this when validation of necessary animation data isn't necessary as it
* already exists. It will insert a keyframe using the current value being keyframed.
* Returns the index at which a keyframe was added (or -1 if failed)
@@ -103,21 +105,23 @@ int insert_vert_fcurve(struct FCurve *fcu, float x, float y, eBezTriple_Keyframe
/* -------- */
-/* Secondary Keyframing API calls:
- * Use this to insert a keyframe using the current value being keyframed, in the
+/* Secondary Keyframing API calls:
+ * 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 ReportList *reports, struct PointerRNA ptr, struct PropertyRNA *prop, struct FCurve *fcu, float cfra, eBezTriple_KeyframeType keytype, 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, eInsertKeyFlags flag);
/* -------- */
-/* Main Keyframing API calls:
+/* Main Keyframing API calls:
* 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 ReportList *reports, struct ID *id, struct bAction *act, const char group[], const char rna_path[], int array_index, float cfra, eBezTriple_KeyframeType keytype, 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, eInsertKeyFlags flag);
-/* Main Keyframing API call:
+/* 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 ReportList *reports, struct ID *id, struct bAction *act, const char group[], const char rna_path[], int array_index, float cfra, eInsertKeyFlags flag);
@@ -133,13 +137,13 @@ typedef int (*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);
/* 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];
@@ -149,11 +153,11 @@ typedef struct KeyingSetInfo {
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
@@ -162,7 +166,7 @@ typedef struct KeyingSetInfo {
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;
@@ -241,7 +245,7 @@ typedef enum eCreateDriver_MappingTypes {
CREATEDRIVER_MAPPING_1_N = 0, /* 1 to Many - Use the specified index, and drive all elements with it */
CREATEDRIVER_MAPPING_1_1 = 1, /* 1 to 1 - Only for the specified index on each side */
CREATEDRIVER_MAPPING_N_N = 2, /* Many to Many - Match up the indices one by one (only for drivers on vectors/arrays) */
-
+
CREATEDRIVER_MAPPING_NONE = 3, /* None (Single Prop) - Do not create driver with any targets; these will get added later instead */
CREATEDRIVER_MAPPING_NONE_ALL = 4, /* None (All Properties) - Do not create driver with any targets; these will get added later instead */
} eCreateDriver_MappingTypes;
@@ -270,7 +274,7 @@ struct FCurve *verify_driver_fcurve(struct ID *id, const char rna_path[], const
* - mapping_type: eCreateDriver_MappingTypes
*/
int ANIM_add_driver_with_target(
- struct ReportList *reports,
+ 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);
@@ -307,7 +311,7 @@ bool ANIM_copy_driver(struct ReportList *reports, struct ID *id, const char rna_
/* 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
+ * 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);
@@ -362,7 +366,7 @@ bool fcurve_frame_has_keyframe(struct FCurve *fcu, float frame, short filter);
*/
bool id_frame_has_keyframe(struct ID *id, float frame, short filter);
-/* filter flags for id_cfra_has_keyframe
+/* filter flags for id_cfra_has_keyframe
*
* WARNING: do not alter order of these, as also stored in files
* (for v3d->keyflags)
diff --git a/source/blender/editors/include/ED_manipulator_library.h b/source/blender/editors/include/ED_manipulator_library.h
index 7166292147e..fca0f5c8806 100644
--- a/source/blender/editors/include/ED_manipulator_library.h
+++ b/source/blender/editors/include/ED_manipulator_library.h
@@ -73,11 +73,18 @@ enum {
ED_MANIPULATOR_ARROW_STYLE_CONE = 3,
};
+/* transform */
enum {
/* inverted offset during interaction - if set it also sets constrained below */
- ED_MANIPULATOR_ARROW_STYLE_INVERTED = (1 << 3),
+ ED_MANIPULATOR_ARROW_XFORM_FLAG_INVERTED = (1 << 3),
/* clamp arrow interaction to property width */
- ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED = (1 << 4),
+ ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED = (1 << 4),
+};
+
+/* draw_options */
+enum {
+ /* Show arrow stem. */
+ ED_MANIPULATOR_ARROW_DRAW_FLAG_STEM = (1 << 0),
};
void ED_manipulator_arrow3d_set_ui_range(struct wmManipulator *mpr, const float min, const float max);
@@ -192,6 +199,18 @@ enum {
ED_MANIPULATOR_GRAB_STYLE_CROSS_2D = 1,
};
+/* -------------------------------------------------------------------- */
+/* Button Manipulator */
+
+enum {
+ ED_MANIPULATOR_BUTTON_SHOW_OUTLINE = (1 << 0),
+ /**
+ * Draw a line from the origin to the offset (similar to an arrow)
+ * sometimes needed to show what the button edits.
+ */
+ ED_MANIPULATOR_BUTTON_SHOW_HELPLINE = (1 << 1),
+};
+
/* -------------------------------------------------------------------- */
/* Primitive Manipulator */
diff --git a/source/blender/editors/include/ED_markers.h b/source/blender/editors/include/ED_markers.h
index 5eaf459a4e1..a95e283f218 100644
--- a/source/blender/editors/include/ED_markers.h
+++ b/source/blender/editors/include/ED_markers.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -68,7 +68,7 @@ struct TimeMarker *ED_markers_get_first_selected(ListBase *markers);
/* Operators ------------------------------ */
/* called in screen_ops.c:ED_operatortypes_screen() */
-void ED_operatortypes_marker(void);
+void ED_operatortypes_marker(void);
/* called in screen_ops.c:ED_keymap_screen() */
void ED_keymap_marker(struct wmKeyConfig *keyconf);
diff --git a/source/blender/editors/include/ED_mball.h b/source/blender/editors/include/ED_mball.h
index 9982c87a764..46c34d36efc 100644
--- a/source/blender/editors/include/ED_mball.h
+++ b/source/blender/editors/include/ED_mball.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 787cf7f0524..32504db6498 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -83,7 +83,7 @@ void EDBM_mesh_clear(struct BMEditMesh *em);
void EDBM_selectmode_to_scene(struct bContext *C);
void EDBM_mesh_make(struct Object *ob, const int select_mode, const bool add_key_index);
void EDBM_mesh_free(struct BMEditMesh *em);
-void EDBM_mesh_load(struct Object *ob);
+void EDBM_mesh_load(struct Main *bmain, struct Object *ob);
struct DerivedMesh *EDBM_mesh_deform_dm_get(struct BMEditMesh *em);
/* flushes based on the current select mode. if in vertex select mode,
@@ -225,9 +225,9 @@ typedef struct MirrTopoStore_t {
} MirrTopoStore_t;
bool ED_mesh_mirrtopo_recalc_check(
- struct Mesh *me, struct DerivedMesh *dm, MirrTopoStore_t *mesh_topo_store);
+ struct Mesh *me, struct Mesh *me_eval, MirrTopoStore_t *mesh_topo_store);
void ED_mesh_mirrtopo_init(
- struct Mesh *me, struct DerivedMesh *dm, MirrTopoStore_t *mesh_topo_store,
+ 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);
@@ -317,17 +317,17 @@ 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 DerivedMesh *dm, const float co[3], char mode);
-int ED_mesh_mirror_topo_table(struct Object *ob, struct DerivedMesh *dm, 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 DerivedMesh *dm, 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 DerivedMesh *dm);
+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);
diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h
index 20363c69fa0..8d652609fbc 100644
--- a/source/blender/editors/include/ED_node.h
+++ b/source/blender/editors/include/ED_node.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -86,7 +86,7 @@ float ED_node_grid_size(void);
/* node_relationships.c */
void ED_node_link_intersect_test(struct ScrArea *sa, int test);
-void ED_node_link_insert(struct ScrArea *sa);
+void ED_node_link_insert(struct Main *bmain, struct ScrArea *sa);
/* node_edit.c */
void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typeinfo);
@@ -107,7 +107,6 @@ void ED_node_composite_job(const struct bContext *C, struct bNodeTree *nodetree,
void ED_operatormacros_node(void);
/* node_view.c */
-bool ED_space_node_color_sample(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_object.h b/source/blender/editors/include/ED_object.h
index 0775c2b953b..29f7edaebf0 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -40,6 +40,7 @@ struct Base;
struct EnumPropertyItem;
struct ID;
struct Main;
+struct Menu;
struct ModifierData;
struct Object;
struct ReportList;
@@ -58,12 +59,14 @@ struct PointerRNA;
struct PropertyRNA;
struct EnumPropertyItem;
struct Depsgraph;
+struct uiLayout;
#include "DNA_object_enums.h"
/* object_edit.c */
struct Object *ED_object_context(struct bContext *C); /* context.object */
struct Object *ED_object_active_context(struct bContext *C); /* context.object or context.active_object */
+void ED_hide_collections_menu_draw(const struct bContext *C, struct uiLayout *layout);
/* object_ops.c */
void ED_operatortypes_object(void);
@@ -122,27 +125,26 @@ void ED_object_parent(struct Object *ob, struct Object *parent, const int type,
enum {
EM_FREEDATA = (1 << 0),
EM_WAITCURSOR = (1 << 1),
- EM_DO_UNDO = (1 << 2),
EM_IGNORE_LAYER = (1 << 3),
EM_NO_CONTEXT = (1 << 4),
};
-void ED_object_editmode_exit_ex(
- struct bContext *C, struct Scene *scene, struct Object *obedit, int flag);
-void ED_object_editmode_exit(struct bContext *C, 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);
-void ED_object_editmode_enter_ex(struct Scene *scene, struct Object *ob, int flag);
-void ED_object_editmode_enter(struct bContext *C, int flag);
-bool ED_object_editmode_load(struct Object *obedit);
+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);
bool ED_object_editmode_calc_active_center(struct Object *obedit, const bool select_only, float r_center[3]);
void ED_object_vpaintmode_enter_ex(
- struct Depsgraph *depsgraph, struct wmWindowManager *wm,
+ 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 Depsgraph *depsgraph, struct wmWindowManager *wm,
+ struct Main *bmain, struct Depsgraph *depsgraph, struct wmWindowManager *wm,
struct Scene *scene, struct Object *ob);
void ED_object_wpaintmode_enter(struct bContext *C);
@@ -152,7 +154,7 @@ void ED_object_wpaintmode_exit_ex(struct Object *ob);
void ED_object_wpaintmode_exit(struct bContext *C);
void ED_object_sculptmode_enter_ex(
- struct Depsgraph *depsgraph,
+ struct Main *bmain, struct Depsgraph *depsgraph,
struct Scene *scene, struct Object *ob,
struct ReportList *reports);
void ED_object_sculptmode_enter(struct bContext *C, struct ReportList *reports);
@@ -198,13 +200,13 @@ struct ListBase *get_active_constraints(struct Object *ob);
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 Object *ob);
+void object_test_constraints(struct Main *bmain, struct Object *ob);
void ED_object_constraint_set_active(struct Object *ob, struct bConstraint *con);
-void ED_object_constraint_update(struct Object *ob);
+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 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 */
@@ -217,6 +219,7 @@ 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(
@@ -233,17 +236,20 @@ enum {
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);
+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 Scene *scene,
- struct ViewLayer *view_layer, struct Object *ob, struct ModifierData *md);
-int ED_object_modifier_apply(struct ReportList *reports, struct Depsgraph *depsgraph, struct Scene *scene,
- struct Object *ob, struct ModifierData *md, int mode);
+int ED_object_modifier_convert(
+ struct ReportList *reports, struct Main *bmain, 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(
@@ -263,7 +269,8 @@ const struct EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(
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);
/* 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_outliner.h b/source/blender/editors/include/ED_outliner.h
index 73ee2542247..c1b3c3e9e1c 100644
--- a/source/blender/editors/include/ED_outliner.h
+++ b/source/blender/editors/include/ED_outliner.h
@@ -27,4 +27,11 @@
#ifndef __ED_OUTLINER_H__
#define __ED_OUTLINER_H__
+struct bContext;
+struct ListBase;
+
+int ED_outliner_collections_editor_poll(struct bContext *C);
+
+void ED_outliner_selected_objects_get(const struct bContext *C, struct ListBase *objects);
+
#endif /* __ED_OUTLINER_H__ */
diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h
index 8b522c91188..b50250dfb96 100644
--- a/source/blender/editors/include/ED_particle.h
+++ b/source/blender/editors/include/ED_particle.h
@@ -71,4 +71,3 @@ void PE_deselect_all_visible(struct PTCacheEdit *edit);
void ED_particle_undosys_type(struct UndoType *ut);
#endif /* __ED_PARTICLE_H__ */
-
diff --git a/source/blender/editors/include/ED_physics.h b/source/blender/editors/include/ED_physics.h
index fed842c969e..70b54a64d6b 100644
--- a/source/blender/editors/include/ED_physics.h
+++ b/source/blender/editors/include/ED_physics.h
@@ -57,4 +57,3 @@ void ED_operatortypes_physics(void);
void ED_keymap_physics(struct wmKeyConfig *keyconf);
#endif /* __ED_PHYSICS_H__ */
-
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index 5bfa73f6271..0785b63ca37 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -60,6 +60,9 @@ struct Main;
struct wmMsgBus;
struct wmMsgSubscribeKey;
struct wmMsgSubscribeValue;
+struct wmOperatorType;
+struct IDProperty;
+struct MenuType;
/* regions */
void ED_region_do_listen(
@@ -69,21 +72,33 @@ 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 bContext *C, struct ARegion *ar);
-void ED_region_init(struct bContext *C, 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(
- const struct bContext *C, struct ARegion *ar,
- const char *context, int contextnr,
- const bool vertical);
-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_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_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);
@@ -93,6 +108,7 @@ void ED_region_image_metadata_draw(int x, int y, struct ImBuf *ibuf, const rc
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);
@@ -118,25 +134,25 @@ int ED_area_header_switchbutton(const struct bContext *C, struct uiBlock *bl
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_topbar_area_create(
- struct wmWindow *win,
- const struct bScreen *screen);
void ED_screen_global_areas_create(
struct wmWindow *win);
void ED_area_do_listen(struct bScreen *sc, ScrArea *sa, struct wmNotifier *note, Scene *scene,
struct WorkSpace *workspace);
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_azones_update(ScrArea *sa, const int mouse_xy[]);
-void ED_area_headerprint(ScrArea *sa, const char *str);
+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(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);
@@ -160,7 +176,7 @@ ScrArea *ED_screen_areas_iter_next(const bScreen *screen, const ScrArea *area);
vert_name = (vert_name == (win)->global_areas.vertbase.last) ? (screen)->vertbase.first : vert_name->next)
/* screens */
-void ED_screens_initialize(struct wmWindowManager *wm);
+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);
@@ -172,7 +188,7 @@ void ED_screen_update_after_scene_change(
const struct bScreen *screen,
struct Scene *scene_new,
struct ViewLayer *view_layer);
-void ED_screen_set_active_region(struct bContext *C, const int xy[2]);
+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);
@@ -211,10 +227,12 @@ void ED_workspace_view_layer_unset(
const struct Main *bmain, struct Scene *scene,
const ViewLayer *layer_unset, ViewLayer *layer_new) ATTR_NONNULL(1, 2);
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(
@@ -229,6 +247,8 @@ void ED_workspace_object_mode_sync_from_object(
void ED_workspace_object_mode_sync_from_scene(
struct wmWindowManager *wm, WorkSpace *workspace, struct Scene *scene);
+void ED_workspace_status_text(struct bContext *C, const char *str);
+
/* anim */
void ED_update_for_newframe(struct Main *bmain, struct Depsgraph *depsgraph);
@@ -249,6 +269,7 @@ int ED_operator_screen_mainwinactive(struct bContext *C);
int ED_operator_areaactive(struct bContext *C);
int ED_operator_regionactive(struct bContext *C);
+int ED_operator_scene(struct bContext *C);
int ED_operator_scene_editable(struct bContext *C);
int ED_operator_objectmode(struct bContext *C);
@@ -297,6 +318,29 @@ int ED_operator_posemode_local(struct bContext *C);
int ED_operator_mask(struct bContext *C);
int ED_operator_camera(struct bContext *C);
+/* screen_user_menu.c */
+
+struct bUserMenu *ED_screen_user_menu_find(struct bContext *C);
+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);
+
+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_remove(
+ struct ListBase *lb, struct bUserMenuItem *umi);
+void ED_screen_user_menu_register(void);
/* Cache display helpers */
@@ -304,6 +348,11 @@ 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);
+/* interface_region_hud.c */
+struct ARegionType *ED_area_type_hud(int space_type);
+void ED_area_type_hud_clear(struct wmWindowManager *wm, ScrArea *sa_keep);
+void ED_area_type_hud_ensure(struct bContext *C, struct ScrArea *sa);
+
/* default keymaps, bitflags */
#define ED_KEYMAP_UI 1
#define ED_KEYMAP_VIEW2D 2
@@ -314,4 +363,3 @@ void ED_region_cache_draw_cached_segments(const struct ARegion *ar, const int nu
#define ED_KEYMAP_HEADER 64
#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 0fed5eb03fd..8ef7fee0f32 100644
--- a/source/blender/editors/include/ED_screen_types.h
+++ b/source/blender/editors/include/ED_screen_types.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -63,7 +63,7 @@ enum {
#define REDRAW_FRAME_AVERAGE 8
-/* for playback framerate info
+/* for playback framerate info
* stored during runtime as scene->fps_info
*/
typedef struct ScreenFrameRateInfo {
diff --git a/source/blender/editors/include/ED_sculpt.h b/source/blender/editors/include/ED_sculpt.h
index 574523696f5..c624405cd0c 100644
--- a/source/blender/editors/include/ED_sculpt.h
+++ b/source/blender/editors/include/ED_sculpt.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/source/blender/editors/include/ED_sound.h b/source/blender/editors/include/ED_sound.h
index d3e7502bb99..b4b424b0318 100644
--- a/source/blender/editors/include/ED_sound.h
+++ b/source/blender/editors/include/ED_sound.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -34,4 +34,3 @@
void ED_operatortypes_sound(void);
#endif /* __ED_SOUND_H__ */
-
diff --git a/source/blender/editors/include/ED_space_api.h b/source/blender/editors/include/ED_space_api.h
index 0cb23514867..ddd8b59c264 100644
--- a/source/blender/editors/include/ED_space_api.h
+++ b/source/blender/editors/include/ED_space_api.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -57,9 +57,10 @@ void ED_spacetype_logic(void);
void ED_spacetype_console(void);
void ED_spacetype_userpref(void);
void ED_spacetype_clip(void);
+void ED_spacetype_statusbar(void);
void ED_spacetype_topbar(void);
-/* calls for instancing and freeing spacetype static data
+/* calls for instancing and freeing spacetype static data
* called in WM_init_exit */
/* in space_file.c */
void ED_file_init(void);
@@ -69,7 +70,7 @@ void ED_file_exit(void);
#define REGION_DRAW_POST_PIXEL 1
#define REGION_DRAW_PRE_VIEW 2
-void *ED_region_draw_cb_activate(struct ARegionType *,
+void *ED_region_draw_cb_activate(struct ARegionType *,
void (*draw)(const struct bContext *, struct ARegion *, void *),
void *custumdata, int type);
void ED_region_draw_cb_draw(const struct bContext *, struct ARegion *, int);
diff --git a/source/blender/editors/include/ED_text.h b/source/blender/editors/include/ED_text.h
index 763fbe3bac5..858902eeec1 100644
--- a/source/blender/editors/include/ED_text.h
+++ b/source/blender/editors/include/ED_text.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -17,7 +17,7 @@
*
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index e17d02abcd7..1e3c8995314 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -102,6 +102,7 @@ enum TfmMode {
#define CTX_MASK (1 << 7)
#define CTX_PAINT_CURVE (1 << 8)
#define CTX_GPENCIL_STROKES (1 << 9)
+#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)
@@ -152,6 +153,7 @@ int BIF_countTransformOrientation(const struct bContext *C);
#define P_NO_TEXSPACE (1 << 11)
#define P_CENTER (1 << 12)
#define P_GPENCIL_EDIT (1 << 13)
+#define P_CURSOR_EDIT (1 << 14)
void Transform_Properties(struct wmOperatorType *ot, int flags);
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 f1d47911cdd..8ac7dfcf9d8 100644
--- a/source/blender/editors/include/ED_transform_snap_object_context.h
+++ b/source/blender/editors/include/ED_transform_snap_object_context.h
@@ -72,6 +72,9 @@ struct SnapObjectParams {
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;
@@ -116,7 +119,6 @@ bool ED_transform_snap_object_project_view3d_ex(
const unsigned short snap_to,
const struct SnapObjectParams *params,
const float mval[2], float *dist_px,
- float *ray_depth,
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(
@@ -124,16 +126,8 @@ bool ED_transform_snap_object_project_view3d(
const unsigned short snap_to,
const struct SnapObjectParams *params,
const float mval[2], float *dist_px,
- float *ray_depth,
/* return args */
float r_loc[3], float r_no[3]);
-bool ED_transform_snap_object_project_view3d_mixed(
- SnapObjectContext *sctx,
- const unsigned short snap_to_flag,
- const struct SnapObjectParams *params,
- const float mval_fl[2], float *dist_px,
- bool use_depth,
- float r_co[3], float r_no[3]);
bool ED_transform_snap_object_project_all_view3d_ex(
SnapObjectContext *sctx,
diff --git a/source/blender/editors/include/ED_types.h b/source/blender/editors/include/ED_types.h
index fac4c02e8ed..a478278da4c 100644
--- a/source/blender/editors/include/ED_types.h
+++ b/source/blender/editors/include/ED_types.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
diff --git a/source/blender/editors/include/ED_undo.h b/source/blender/editors/include/ED_undo.h
index 6df568a6bc9..7995644f39e 100644
--- a/source/blender/editors/include/ED_undo.h
+++ b/source/blender/editors/include/ED_undo.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -52,14 +52,6 @@ int ED_undo_operator_repeat(struct bContext *C, struct wmOperator *op);
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);
-/* Context sanity helpers for operator repeat. */
-typedef struct OperatorRepeatContextHandle OperatorRepeatContextHandle;
-
-const OperatorRepeatContextHandle *ED_operator_repeat_prepare_context(
- struct bContext *C, struct wmOperator *op) ATTR_WARN_UNUSED_RESULT;
-void ED_operator_repeat_reset_context(
- struct bContext *C, const OperatorRepeatContextHandle *context_info);
-
bool ED_undo_is_valid(const struct bContext *C, const char *undoname);
struct UndoStack *ED_undo_stack_get(void);
@@ -76,4 +68,3 @@ void ED_undosys_type_free(void);
struct MemFile *ED_undosys_stack_memfile_get_active(struct UndoStack *ustack);
#endif /* __ED_UNDO_H__ */
-
diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h
index 69e80f60d0a..7e91b5b88c1 100644
--- a/source/blender/editors/include/ED_util.h
+++ b/source/blender/editors/include/ED_util.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -55,4 +55,3 @@ void apply_keyb_grid(int shift, int ctrl, float *val, float fac1, float fac2, fl
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 d6e8b6e9504..434e9cfe2ac 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -17,7 +17,7 @@
*
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -54,6 +54,11 @@ bool ED_uvedit_minmax(struct Scene *scene, struct Image *ima, struct Object *obe
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);
@@ -140,4 +145,3 @@ void ED_uvedit_draw_main(
void ED_uvedit_buttons_register(struct ARegionType *art);
#endif /* __ED_UVEDIT_H__ */
-
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index bb86c7ba6c5..68aeccdcc32 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -75,6 +75,7 @@ enum eGPUFXFlags;
/* for derivedmesh drawing callbacks, for view3d_select, .... */
typedef struct ViewContext {
+ struct Main *bmain;
struct Depsgraph *depsgraph;
struct Scene *scene;
struct ViewLayer *view_layer;
@@ -93,23 +94,44 @@ typedef struct ViewDepths {
short x, y; /* only for temp use for sub-rects, added to ar->winx/y */
float *depths;
double depth_range[2];
-
+
bool damaged;
} ViewDepths;
+
+/* Rotate 3D cursor on placement. */
+enum eV3DCursorOrient {
+ V3D_CURSOR_ORIENT_NONE = 0,
+ V3D_CURSOR_ORIENT_VIEW,
+ V3D_CURSOR_ORIENT_GEOM,
+};
+
struct View3DCursor *ED_view3d_cursor3d_get(struct Scene *scene, struct View3D *v3d);
-void ED_view3d_cursor3d_calc_mat3(const struct Scene *scene, const struct View3D *v3d, float mat[3][3]);
-void ED_view3d_cursor3d_calc_mat4(const struct Scene *scene, const struct View3D *v3d, float mat[4][4]);
-void ED_view3d_cursor3d_position(struct bContext *C, float fp[3], const int mval[2]);
-void ED_view3d_cursor3d_update(struct bContext *C, const int mval[2]);
+void ED_view3d_cursor3d_calc_mat3(const struct Scene *scene, const struct View3D *v3d, float mat[3][3]);
+void ED_view3d_cursor3d_calc_mat4(const struct Scene *scene, const struct View3D *v3d, 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],
+ bool use_depth, enum eV3DCursorOrient orientation);
struct Camera *ED_view3d_camera_data_get(struct View3D *v3d, struct RegionView3D *rv3d);
void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], const float dist);
-void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist);
+void ED_view3d_from_m4(const float mat[4][4], float ofs[3], float quat[4], float *dist);
-void ED_view3d_from_object(struct Object *ob, float ofs[3], float quat[4], float *dist, float *lens);
-void ED_view3d_to_object(struct Object *ob, const float ofs[3], const float quat[4], const 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);
void ED_view3d_lastview_store(struct RegionView3D *rv3d);
@@ -225,6 +247,7 @@ eV3DProjStatus ED_view3d_project_float_global(const struct ARegion *ar, const fl
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]);
@@ -302,12 +325,14 @@ 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);
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_validate_with_select_mode(struct ViewContext *vc, short select_mode);
void ED_view3d_backbuf_validate(struct ViewContext *vc);
struct ImBuf *ED_view3d_backbuf_read(
struct ViewContext *vc, int xmin, int ymin, int xmax, int ymax);
@@ -319,12 +344,13 @@ unsigned int ED_view3d_backbuf_sample(
struct ViewContext *vc, int x, int y);
bool ED_view3d_autodist(
- struct Depsgraph *graph, struct ARegion *ar, struct View3D *v3d,
+ 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 *graph, struct ARegion *ar, struct View3D *v3d, int mode);
+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);
@@ -342,12 +368,19 @@ typedef enum {
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,
+} eV3DSelectObjectFilter;
+
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);
+ eV3DSelectMode select_mode, eV3DSelectObjectFilter select_filter);
/* view3d_select.c */
float ED_view3d_select_dist_px(void);
@@ -379,7 +412,8 @@ int ED_view3d_view_layer_set(int lay, const int *values, int *active);
struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d);
void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat);
-void ED_draw_object_facemap(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, const float col[4], const int facemap);
+void ED_draw_object_facemap(
+ struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, const float col[4], const int facemap);
struct RenderEngineType *ED_view3d_engine_type(struct Scene *scene, int drawtype);
@@ -436,17 +470,25 @@ uint64_t ED_view3d_datamask(const struct Scene *scene, const struct View3D *v3d)
uint64_t ED_view3d_screen_datamask(const struct Scene *scene, const struct bScreen *screen);
bool ED_view3d_offset_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d);
-void ED_view3d_persp_switch_from_camera(struct View3D *v3d, struct RegionView3D *rv3d, const char persp);
-bool ED_view3d_persp_ensure(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(struct View3D *v3d, struct RegionView3D *rv3d, const bool calc_dist);
-void ED_view3d_camera_lock_init(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(struct View3D *v3d, struct RegionView3D *rv3d);
+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,
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 6a9067ef95d..75e835ff1d3 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -61,7 +61,7 @@ DEF_ICON(PLUG)
DEF_ICON(UI)
DEF_ICON(NODE)
DEF_ICON(NODE_SEL)
-
+
/* ui */
DEF_ICON(FULLSCREEN)
DEF_ICON(SPLITSCREEN)
@@ -89,7 +89,7 @@ DEF_ICON(DOTSDOWN)
DEF_ICON(LINK)
DEF_ICON(INLINK)
DEF_ICON(PLUGIN)
-
+
/* various ui */
DEF_ICON(HELP)
DEF_ICON(GHOST_ENABLED)
@@ -113,13 +113,11 @@ DEF_ICON(FILE_TICK)
DEF_ICON(QUIT)
DEF_ICON(URL)
DEF_ICON(RECOVER_LAST)
-#ifndef DEF_ICON_BLANK_SKIP
- DEF_ICON(BLANK038)
-#endif
+DEF_ICON(PRESET)
DEF_ICON(FULLSCREEN_ENTER)
DEF_ICON(FULLSCREEN_EXIT)
DEF_ICON(BLANK1) // Not actually blank - this is used all over the place
-
+
/* BUTTONS */
DEF_ICON(LAMP)
DEF_ICON(MATERIAL)
@@ -208,7 +206,7 @@ DEF_ICON(GREASEPENCIL_STROKE_PAINT)
DEF_ICON(BLANK077)
DEF_ICON(BLANK077b)
#endif
-
+
/* DATA */
DEF_ICON(SCENE_DATA)
DEF_ICON(RENDERLAYERS)
@@ -275,10 +273,14 @@ DEF_ICON(RNA_ADD)
DEF_ICON(BLANK093)
DEF_ICON(BLANK094)
DEF_ICON(BLANK095)
- DEF_ICON(BLANK096)
- DEF_ICON(BLANK097)
- DEF_ICON(BLANK098)
- DEF_ICON(BLANK099)
+#endif
+
+DEF_ICON(MOUSE_LMB)
+DEF_ICON(MOUSE_MMB)
+DEF_ICON(MOUSE_RMB)
+DEF_ICON(MOUSE_DRAG)
+
+#ifndef DEF_ICON_BLANK_SKIP
DEF_ICON(BLANK100)
DEF_ICON(BLANK101)
DEF_ICON(BLANK102)
@@ -294,11 +296,13 @@ DEF_ICON(RNA_ADD)
DEF_ICON(BLANK112)
DEF_ICON(BLANK113)
DEF_ICON(BLANK114)
- DEF_ICON(BLANK115)
- DEF_ICON(BLANK116)
+#endif
+DEF_ICON(RESTRICT_VIEW_OFF)
+DEF_ICON(RESTRICT_VIEW_ON)
+#ifndef DEF_ICON_BLANK_SKIP
DEF_ICON(BLANK116b)
#endif
-
+
/* OUTLINER */
DEF_ICON(OUTLINER_OB_EMPTY)
DEF_ICON(OUTLINER_OB_MESH)
@@ -321,8 +325,8 @@ DEF_ICON(OUTLINER_OB_LIGHTPROBE)
#endif
DEF_ICON(RESTRICT_COLOR_OFF)
DEF_ICON(RESTRICT_COLOR_ON)
-DEF_ICON(RESTRICT_VIEW_OFF)
-DEF_ICON(RESTRICT_VIEW_ON)
+DEF_ICON(HIDE_OFF)
+DEF_ICON(HIDE_ON)
DEF_ICON(RESTRICT_SELECT_OFF)
DEF_ICON(RESTRICT_SELECT_ON)
DEF_ICON(RESTRICT_RENDER_OFF)
@@ -360,7 +364,7 @@ DEF_ICON(OUTLINER_DATA_GREASEPENCIL)
DEF_ICON(BLANK142)
DEF_ICON(BLANK142b)
#endif
-
+
/* PRIMITIVES */
DEF_ICON(MESH_PLANE)
DEF_ICON(MESH_CUBE)
@@ -394,7 +398,7 @@ DEF_ICON(META_CAPSULE)
#ifndef DEF_ICON_BLANK_SKIP
DEF_ICON(BLANK625)
#endif
-
+
/* PRIMITIVES */
DEF_ICON(SURFACE_NCURVE)
DEF_ICON(SURFACE_NCIRCLE)
@@ -485,7 +489,7 @@ DEF_ICON(NODE_INSERT_OFF)
DEF_ICON(BLANK713)
DEF_ICON(BLANK714)
DEF_ICON(BLANK715)
-
+
/* EMPTY */
DEF_ICON(BLANK720)
DEF_ICON(BLANK721)
@@ -600,7 +604,7 @@ DEF_ICON(MOD_NORMALEDIT)
DEF_ICON(BLANK176)
DEF_ICON(BLANK177)
#endif
-
+
/* ANIMATION */
DEF_ICON(REC)
DEF_ICON(PLAY)
@@ -691,7 +695,7 @@ DEF_ICON(SCULPT_DYNTOPO) /* XXX Empty icon! */
DEF_ICON(PARTICLE_POINT)
DEF_ICON(PARTICLE_TIP)
DEF_ICON(PARTICLE_PATH)
-
+
/* EDITING */
DEF_ICON(MAN_TRANS)
DEF_ICON(MAN_ROT)
@@ -753,7 +757,7 @@ DEF_ICON(UV_SYNC_SELECT)
DEF_ICON(BLANK247)
DEF_ICON(BLANK247b)
#endif
-
+
/* 3D VIEW */
DEF_ICON(BBOX)
DEF_ICON(WIRE)
@@ -876,7 +880,7 @@ DEF_ICON(FORWARD)
DEF_ICON(FILE_HIDDEN)
DEF_ICON(FILE_BACKUP)
DEF_ICON(DISK_DRIVE)
-
+
/* SHADING / TEXT */
DEF_ICON(MATPLANE)
DEF_ICON(MATSPHERE)
@@ -908,7 +912,7 @@ DEF_ICON(SCRIPTPLUGINS) // XXX CREATE NEW
DEF_ICON(BLANK328)
DEF_ICON(BLANK328b)
#endif
-
+
/* SEQUENCE / IMAGE EDITOR */
DEF_ICON(SEQ_SEQUENCER)
DEF_ICON(SEQ_PREVIEW)
@@ -1002,7 +1006,7 @@ DEF_ICON(MATCAP_22)
DEF_ICON(MATCAP_23)
DEF_ICON(MATCAP_24)
-/* vector icons, VICO_ prefix added */
+/* vector icons, VICO_ prefix added */
DEF_VICO(SMALL_TRI_RIGHT_VEC)
DEF_VICO(KEYTYPE_KEYFRAME_VEC)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 3efd04ee701..7fef72b7484 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -42,6 +42,7 @@ struct ID;
struct IDProperty;
struct ListBase;
struct ARegion;
+struct ARegionType;
struct ScrArea;
struct bScreen;
struct wmEvent;
@@ -75,6 +76,7 @@ struct wmEvent;
struct wmManipulator;
struct wmMsgBus;
struct uiButtonGroup;
+struct wmKeyMap;
typedef struct uiBut uiBut;
typedef struct uiBlock uiBlock;
@@ -145,8 +147,9 @@ enum {
#define UI_BLOCK_LIST_ITEM (1 << 19)
#define UI_BLOCK_RADIAL (1 << 20)
#define UI_BLOCK_POPOVER (1 << 21)
+#define UI_BLOCK_POPOVER_ONCE (1 << 22)
/** Always show keymaps, even for non-menus. */
-#define UI_BLOCK_SHOW_SHORTCUT_ALWAYS (1 << 22)
+#define UI_BLOCK_SHOW_SHORTCUT_ALWAYS (1 << 23)
/* uiPopupBlockHandle->menuretval */
#define UI_RETURN_CANCEL (1 << 0) /* cancel all menus cascading */
@@ -303,7 +306,8 @@ typedef enum {
UI_BTYPE_NODE_SOCKET = (53 << 9),
UI_BTYPE_SEPR = (54 << 9),
UI_BTYPE_SEPR_LINE = (55 << 9),
- UI_BTYPE_GRIP = (56 << 9), /* resize handle (resize uilist) */
+ UI_BTYPE_SEPR_SPACER = (56 << 9), /* Dynamically fill available space. */
+ UI_BTYPE_GRIP = (57 << 9), /* resize handle (resize uilist) */
} eButType;
#define BUTTYPE (63 << 9)
@@ -399,6 +403,15 @@ 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_is_tool(const uiBut *but);
+#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
*
@@ -415,6 +428,7 @@ 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();
@@ -427,9 +441,14 @@ void UI_popup_menu_but_set(uiPopupMenu *pup, struct ARegion *butregion, uiBut *b
typedef struct uiPopover uiPopover;
-uiPopover *UI_popover_begin(struct bContext *C) ATTR_NONNULL();
-void UI_popover_end(struct bContext *C, struct uiPopover *head);
+int UI_popover_panel_invoke(
+ struct bContext *C, int space_id, int region_id, const char *idname,
+ bool keep_open, struct ReportList *reports);
+
+uiPopover *UI_popover_begin(struct bContext *C) ATTR_NONNULL(1);
+void UI_popover_end(struct bContext *C, struct uiPopover *head, struct wmKeyMap *keymap);
struct uiLayout *UI_popover_layout(uiPopover *head);
+void UI_popover_once_clear(uiPopover *pup);
/* interface_region_menu_pie.c */
/* Pie menus */
@@ -469,7 +488,7 @@ void UI_popup_block_close(struct bContext *C, struct wmWindow *win, uiBlock *blo
*
* Functions for creating, drawing and freeing blocks. A Block is a
* container of buttons and used for various purposes.
- *
+ *
* Begin/Define Buttons/End/Draw is the typical order in which these
* function should be called, though for popup blocks Draw is left out.
* Freeing blocks is done by the screen/ module automatically.
@@ -484,8 +503,6 @@ void UI_blocklist_update_window_matrix(const struct bContext *C, const struct Li
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);
-uiBlock *UI_block_find_in_region(const char *name, struct ARegion *ar);
-
void UI_block_emboss_set(uiBlock *block, char dt);
void UI_block_free(const struct bContext *C, uiBlock *block);
@@ -526,6 +543,7 @@ 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);
@@ -574,7 +592,7 @@ bool UI_but_online_manual_id_from_active(
* - R: RNA
* - O: operator */
-uiBut *uiDefBut(uiBlock *block,
+uiBut *uiDefBut(uiBlock *block,
int type, int retval, const char *str,
int x1, int y1,
short x2, short y2,
@@ -594,7 +612,7 @@ uiBut *uiDefButR_prop(uiBlock *block, int type, int retval, const char *str, int
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,
+uiBut *uiDefIconBut(uiBlock *block,
int type, int retval, int icon,
int x1, int y1,
short x2, short y2,
@@ -659,7 +677,7 @@ enum {
typedef struct uiStringInfo {
int type;
char *strinfo;
-} uiStringInfo;
+} uiStringInfo;
/* Note: Expects pointers to uiStringInfo structs as parameters.
* Will fill them with translated strings, when possible.
@@ -821,11 +839,14 @@ void UI_panels_begin(const struct bContext *C, struct ARegion *ar);
void UI_panels_end(const struct bContext *C, struct ARegion *ar, int *x, int *y);
void UI_panels_draw(const struct bContext *C, struct ARegion *ar);
-struct Panel *UI_panel_find_by_type(struct ARegion *ar, struct PanelType *pt);
-struct Panel *UI_panel_begin(struct ScrArea *sa, struct ARegion *ar, uiBlock *block,
- struct PanelType *pt, struct Panel *pa, bool *r_open);
+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);
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 *x, int *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);
@@ -838,6 +859,8 @@ struct PanelCategoryDyn *UI_panel_category_find_mouse_over(struct ARegion *ar,
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);
+
/* Handlers
*
* Handlers that can be registered in regions, areas and windows for
@@ -855,7 +878,7 @@ void UI_popup_handlers_remove_all(struct bContext *C, struct ListBase *handlers)
* be used to reinitialize some internal state if user preferences change. */
void UI_init(void);
-void UI_init_userdef(void);
+void UI_init_userdef(struct Main *bmain);
void UI_reinit_font(void);
void UI_exit(void);
@@ -899,6 +922,7 @@ void UI_exit(void);
#define UI_ITEM_O_DEPRESS (1 << 9)
#define UI_ITEM_R_COMPACT (1 << 10)
+#define UI_HEADER_OFFSET ((void)0, 0.2f * UI_UNIT_X)
/* uiLayoutOperatorButs flags */
enum {
@@ -938,10 +962,10 @@ uiBlock *uiLayoutGetBlock(uiLayout *layout);
void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv);
void uiLayoutSetContextPointer(uiLayout *layout, const char *name, struct PointerRNA *ptr);
void uiLayoutContextCopy(uiLayout *layout, struct bContextStore *context);
-const char *uiLayoutIntrospect(uiLayout *layout); // XXX - testing
struct MenuType *UI_but_menutype_get(uiBut *but);
struct PanelType *UI_but_paneltype_get(uiBut *but);
void UI_menutype_draw(struct bContext *C, struct MenuType *mt, struct uiLayout *layout);
+void UI_paneltype_draw(struct bContext *C, struct PanelType *pt, struct uiLayout *layout);
/* Only for convenience. */
void uiLayoutSetContextFromBut(uiLayout *layout, uiBut *but);
@@ -955,6 +979,8 @@ void uiLayoutSetKeepAspect(uiLayout *layout, bool keepaspect);
void uiLayoutSetScaleX(uiLayout *layout, float scale);
void uiLayoutSetScaleY(uiLayout *layout, float scale);
void uiLayoutSetEmboss(uiLayout *layout, char emboss);
+void uiLayoutSetPropSep(uiLayout *layout, bool is_sep);
+void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep);
int uiLayoutGetOperatorContext(uiLayout *layout);
bool uiLayoutGetActive(uiLayout *layout);
@@ -966,11 +992,15 @@ int uiLayoutGetWidth(uiLayout *layout);
float uiLayoutGetScaleX(uiLayout *layout);
float uiLayoutGetScaleY(uiLayout *layout);
int uiLayoutGetEmboss(uiLayout *layout);
+bool uiLayoutGetPropSep(uiLayout *layout);
+bool uiLayoutGetPropDecorate(uiLayout *layout);
/* layout specifiers */
uiLayout *uiLayoutRow(uiLayout *layout, int align);
uiLayout *uiLayoutColumn(uiLayout *layout, int align);
uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align);
+uiLayout *uiLayoutGridFlow(
+ uiLayout *layout, int row_major, int num_columns, int even_columns, int even_rows, int 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);
@@ -996,7 +1026,7 @@ void uiTemplateIDTabs(
PointerRNA *ptr, const char *propname,
const char *newop, const char *openop, const char *unlinkop,
int filter);
-void uiTemplateAnyID(uiLayout *layout, struct PointerRNA *ptr, const char *propname,
+void uiTemplateAnyID(uiLayout *layout, struct PointerRNA *ptr, const char *propname,
const char *proptypename, const char *text);
void uiTemplateSearch(
uiLayout *layout, struct bContext *C,
@@ -1009,7 +1039,7 @@ void uiTemplateSearchPreview(
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,
+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);
@@ -1019,6 +1049,7 @@ uiLayout *uiTemplateConstraint(uiLayout *layout, struct PointerRNA *ptr);
void uiTemplatePreview(uiLayout *layout, struct bContext *C, struct ID *id, int show_buttons, struct ID *parent,
struct MTex *slot, const char *preview_id);
void uiTemplateColorRamp(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int expand);
+void uiTemplateIcon(uiLayout *layout, int icon_value, float icon_scale);
void uiTemplateIconView(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int show_labels, float icon_scale);
void uiTemplateHistogram(uiLayout *layout, struct PointerRNA *ptr, const char *propname);
void uiTemplateWaveform(uiLayout *layout, struct PointerRNA *ptr, const char *propname);
@@ -1047,6 +1078,7 @@ 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 uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color);
@@ -1114,9 +1146,10 @@ void uiItemsFullEnumO_items(
void uiItemL(uiLayout *layout, const char *name, int icon); /* label */
void uiItemLDrag(uiLayout *layout, struct PointerRNA *ptr, const char *name, int icon); /* label icon for dragging */
-void uiItemM(uiLayout *layout, struct bContext *C, const char *menuname, const char *name, int icon); /* menu */
+void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon); /* menu */
void uiItemV(uiLayout *layout, const char *name, int icon, int argval); /* value */
void uiItemS(uiLayout *layout); /* separator */
+void uiItemSpacer(uiLayout *layout); /* Special separator. */
void uiItemPopoverPanel_ptr(
uiLayout *layout, struct bContext *C,
@@ -1237,8 +1270,9 @@ void UI_widgetbase_draw_cache_flush(void);
void UI_widgetbase_draw_cache_end(void);
/* Special drawing for toolbar, mainly workarounds for inflexible icon sizing. */
-#define USE_TOOLBAR_HACK
+#define USE_UI_TOOLBAR_HACK
-bool UI_but_is_tool(const uiBut *but);
+/* Support click-drag motion which presses the button and closes a popover (like a menu). */
+#define USE_UI_POPOVER_ONCE
#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 a3be887bf5b..651081c46bb 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -21,7 +21,7 @@
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
- *
+ *
* ***** END GPL LICENSE BLOCK *****
*/
@@ -49,7 +49,7 @@ typedef struct IconFile {
#define ICON_DEFAULT_HEIGHT 16
#define ICON_DEFAULT_WIDTH 16
-#define ICON_DEFAULT_HEIGHT_TOOLBAR 38
+#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))
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 2fc9b2946fb..cab0fa8645d 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -21,7 +21,7 @@
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
- *
+ *
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
@@ -56,7 +56,7 @@ typedef enum ThemeColorID {
TH_THEMEUI,
// common colors among spaces
-
+
TH_BACK,
TH_TEXT,
TH_TEXT_HI,
@@ -65,22 +65,23 @@ typedef enum ThemeColorID {
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_PANEL_SHOW_HEADER,
TH_PANEL_SHOW_BACK,
-
+
TH_BUTBACK,
TH_BUTBACK_TEXT,
TH_BUTBACK_TEXT_HI,
-
+
TH_SHADE1,
TH_SHADE2,
TH_HILITE,
@@ -141,14 +142,14 @@ typedef enum ThemeColorID {
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,
@@ -157,15 +158,15 @@ typedef enum ThemeColorID {
TH_KEYTYPE_BREAKDOWN_SELECT,
TH_KEYTYPE_JITTER,
TH_KEYTYPE_JITTER_SELECT,
-
+
TH_KEYBORDER,
TH_KEYBORDER_SELECT,
-
+
TH_LAMP,
TH_SPEAKER,
TH_CAMERA,
TH_EMPTY,
-
+
TH_NODE,
TH_NODE_INPUT,
TH_NODE_OUTPUT,
@@ -183,14 +184,14 @@ typedef enum ThemeColorID {
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,
@@ -205,20 +206,20 @@ typedef enum ThemeColorID {
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_PREVIEW_BACK,
-
+
TH_EDGE_CREASE,
TH_DRAWEXTRA_EDGELEN,
@@ -259,20 +260,20 @@ typedef enum ThemeColorID {
TH_SELECT_HIGHLIGHT, /* highlight color for selected outliner item */
TH_SKIN_ROOT,
-
+
TH_ANIM_ACTIVE, /* active action */
TH_ANIM_INACTIVE, /* no active action */
-
+
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,
@@ -302,7 +303,7 @@ typedef enum ThemeColorID {
TH_INFO_DEBUG,
TH_INFO_DEBUG_TEXT,
TH_VIEW_OVERLAY,
-
+
TH_V3D_CLIPPING_BORDER,
TH_METADATA_BG,
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index 1f106e3f08d..d407878d063 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,12 +18,12 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation, Joshua Leung
*
*
* Generic 2d view with should allow drawing grids,
- * panning, zooming, scrolling, ..
+ * panning, zooming, scrolling, ..
* ***** END GPL LICENSE BLOCK *****
*/
@@ -44,8 +44,8 @@
/* generic value to use when coordinate lies out of view when converting */
#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
+/* Common View2D view types
+ * NOTE: only define a type here if it completely sets all (+/- a few) of the relevant flags
* and settings for a View2D region, and that set of settings is used in more
* than one specific place
*/
@@ -75,7 +75,7 @@ enum eView2D_Units {
V2D_UNIT_SECONDS = 0,
V2D_UNIT_FRAMES,
V2D_UNIT_FRAMESCALE,
-
+
/* for drawing values */
V2D_UNIT_VALUES,
V2D_UNIT_DEGREES,
@@ -95,7 +95,7 @@ enum eView2D_Gridlines {
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),
};
diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt
index 6dc345b30e0..869c91f69eb 100644
--- a/source/blender/editors/interface/CMakeLists.txt
+++ b/source/blender/editors/interface/CMakeLists.txt
@@ -44,6 +44,7 @@ set(SRC
interface.c
interface_align.c
interface_anim.c
+ interface_context_menu.c
interface_draw.c
interface_eyedropper.c
interface_eyedropper_color.c
@@ -57,14 +58,16 @@ set(SRC
interface_layout.c
interface_ops.c
interface_panel.c
- interface_regions.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
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index b8e80f40b58..3eb8f3d6bb5 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -53,13 +53,15 @@
#include "BKE_animsys.h"
#include "BKE_context.h"
-#include "BKE_unit.h"
+#include "BKE_idprop.h"
+#include "BKE_main.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
-#include "BKE_idprop.h"
+#include "BKE_unit.h"
#include "GPU_glew.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "BLF_api.h"
#include "BLT_translation.h"
@@ -85,6 +87,9 @@
#include "interface_intern.h"
+/* prototypes. */
+static void ui_but_to_pixelrect(struct rcti *rect, const struct ARegion *ar, struct uiBlock *block, struct uiBut *but);
+
/* 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
@@ -93,25 +98,13 @@
/**
* a full doc with API notes can be found in 'blender/doc/guides/interface_API.txt'
- *
+ *
* `uiBlahBlah()` external function.
* `ui_blah_blah()` internal function.
*/
static void ui_but_free(const bContext *C, 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));
-}
-
-bool ui_block_is_pie_menu(const uiBlock *block)
-{
- return ((block->flag & UI_BLOCK_RADIAL) != 0);
-}
-
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);
@@ -224,6 +217,64 @@ void ui_region_to_window(const ARegion *ar, int *x, int *y)
*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);
+}
+
static void ui_update_window_matrix(const wmWindow *window, const ARegion *region, uiBlock *block)
{
/* window matrix and aspect */
@@ -262,7 +313,7 @@ void ui_region_winrct_get_no_margin(const struct ARegion *ar, struct rcti *r_rec
/* ******************* block calc ************************* */
-void ui_block_translate(uiBlock *block, int x, int y)
+void UI_block_translate(uiBlock *block, int x, int y)
{
uiBut *but;
@@ -282,7 +333,7 @@ static void ui_block_bounds_calc_text(uiBlock *block, float offset)
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)) {
+ 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)
@@ -318,7 +369,7 @@ void ui_block_bounds_calc(uiBlock *block)
{
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;
@@ -326,13 +377,13 @@ void ui_block_bounds_calc(uiBlock *block)
}
}
else {
-
+
BLI_rctf_init_minmax(&block->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;
@@ -341,7 +392,7 @@ void ui_block_bounds_calc(uiBlock *block)
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 */
+ /* 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;
@@ -357,7 +408,7 @@ 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 */
@@ -365,18 +416,18 @@ static void ui_block_bounds_calc_centered(wmWindow *window, uiBlock *block)
ymax = WM_window_pixels_y(window);
ui_block_bounds_calc(block);
-
+
width = BLI_rctf_size_x(&block->rect);
height = BLI_rctf_size_y(&block->rect);
-
+
startx = (xmax * 0.5f) - (width * 0.5f);
starty = (ymax * 0.5f) - (height * 0.5f);
-
- ui_block_translate(block, startx - block->rect.xmin, starty - block->rect.ymin);
-
+
+ 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)
@@ -386,7 +437,7 @@ static void ui_block_bounds_calc_centered_pie(uiBlock *block)
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);
@@ -406,7 +457,7 @@ static void ui_block_bounds_calc_popup(
/* compute mouse position with user defined offset */
ui_block_bounds_calc(block);
-
+
xmax = WM_window_pixels_x(window);
ymax = WM_window_pixels_y(window);
@@ -446,7 +497,7 @@ static void ui_block_bounds_calc_popup(
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);
+ UI_block_translate(block, rect.xmin - block->rect.xmin, rect.ymin - block->rect.ymin);
/* now recompute bounds and safety */
ui_block_bounds_calc(block);
@@ -464,7 +515,7 @@ void UI_block_bounds_set_normal(uiBlock *block, int addval)
{
if (block == NULL)
return;
-
+
block->bounds = addval;
block->bounds_type = UI_BLOCK_BOUNDS;
}
@@ -723,7 +774,7 @@ bool UI_but_active_only(const bContext *C, ARegion *ar, uiBlock *block, uiBut *b
uiBlock *oldblock;
uiBut *oldbut;
bool activate = false, found = false, isactive = false;
-
+
oldblock = block->oldblock;
if (!oldblock) {
activate = true;
@@ -746,7 +797,7 @@ bool UI_but_active_only(const bContext *C, ARegion *ar, uiBlock *block, uiBut *b
ui_but_free(C, but);
return false;
}
-
+
return true;
}
@@ -950,27 +1001,27 @@ static bool ui_but_event_property_operator_string(
"WM_OT_context_cycle_array",
"WM_OT_context_menu_enum",
NULL
- };
+ };
const size_t num_ops = sizeof(ctx_toggle_opnames) / sizeof(const char *);
-
+
bool found = false;
-
+
/* this version is only for finding hotkeys for properties (which get set via context using operators) */
if (but->rnaprop) {
- /* to avoid massive slowdowns on property panels, for now, we only check the
+ /* to avoid massive slowdowns on property panels, for now, we only check the
* hotkeys for Editor / Scene settings...
*
* TODO: userpref settings?
*/
// TODO: value (for enum stuff)?
char *data_path = NULL;
-
+
if (but->rnapoin.id.data) {
ID *id = but->rnapoin.id.data;
-
+
if (GS(id->name) == ID_SCR) {
- /* screen/editor property
- * NOTE: in most cases, there is actually no info for backwards tracing
+ /* 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(but->rnapoin.type, &RNA_Space)) {
@@ -991,7 +1042,7 @@ static bool ui_but_event_property_operator_string(
}
else if (GS(id->name) == ID_SCE) {
if (RNA_struct_is_a(but->rnapoin.type, &RNA_ToolSettings)) {
- /* toolsettings property
+ /* toolsettings property
* NOTE: toolsettings is usually accessed directly (i.e. not through scene)
*/
data_path = RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop);
@@ -999,7 +1050,7 @@ static bool ui_but_event_property_operator_string(
else {
/* scene property */
char *path = RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop);
-
+
if (path) {
data_path = BLI_sprintfN("scene.%s", path);
MEM_freeN(path);
@@ -1015,23 +1066,23 @@ static bool ui_but_event_property_operator_string(
else {
//puts("other id");
}
-
+
//printf("prop shortcut: '%s' (%s)\n", RNA_property_identifier(but->rnaprop), data_path);
}
-
+
/* we have a datapath! */
if (data_path) {
size_t i;
-
+
/* create a property to host the "datapath" property we're sending to the operators */
IDProperty *prop_path;
IDProperty *prop_path_value;
-
+
IDPropertyTemplate val = {0};
prop_path = IDP_New(IDP_GROUP, &val, __func__);
prop_path_value = IDP_NewString(data_path, "data_path", strlen(data_path) + 1);
IDP_AddToGroup(prop_path, prop_path_value);
-
+
/* check each until one works... */
for (i = 0; (i < num_ops) && (ctx_toggle_opnames[i]); i++) {
if (WM_key_event_operator_string(
@@ -1042,14 +1093,14 @@ static bool ui_but_event_property_operator_string(
break;
}
}
-
+
/* cleanup */
IDP_FreeProperty(prop_path);
MEM_freeN(prop_path);
MEM_freeN(data_path);
}
}
-
+
return found;
}
@@ -1181,6 +1232,7 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x
{
wmWindow *window = CTX_wm_window(C);
Scene *scene = CTX_data_scene(C);
+ ARegion *region = CTX_wm_region(C);
uiBut *but;
BLI_assert(block->active);
@@ -1209,6 +1261,9 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x
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);
+ }
}
@@ -1225,7 +1280,7 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x
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:
@@ -1257,6 +1312,8 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x
UI_block_align_end(block);
}
+ ui_update_flexible_spacing(region, block);
+
block->endblock = 1;
}
@@ -1273,12 +1330,12 @@ void ui_fontscale(short *points, float aspect)
{
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;
-
+
if (aspect > 1.0f)
*points = ceilf(pointsf);
else
@@ -1303,7 +1360,7 @@ void UI_block_draw(const bContext *C, uiBlock *block)
ARegion *ar;
uiBut *but;
rcti rect;
-
+
/* get menu region or area region */
ar = CTX_wm_menu(C);
if (!ar)
@@ -1313,24 +1370,24 @@ void UI_block_draw(const bContext *C, uiBlock *block)
UI_block_end(C, block);
/* we set this only once */
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-
+ 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 */
gpuPushProjectionMatrix();
gpuPushMatrix();
gpuLoadIdentity();
wmOrtho2_region_pixelspace(ar);
-
+
/* back */
if (block->flag & UI_BLOCK_RADIAL)
ui_draw_pie_center(block);
@@ -1349,7 +1406,7 @@ void UI_block_draw(const bContext *C, uiBlock *block)
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)
@@ -1360,7 +1417,7 @@ void UI_block_draw(const bContext *C, uiBlock *block)
UI_widgetbase_draw_cache_end();
UI_icon_draw_cache_end();
BLF_batch_draw_end();
-
+
/* restore matrix */
gpuPopProjectionMatrix();
gpuPopMatrix();
@@ -1680,10 +1737,10 @@ bool ui_but_is_float(const uiBut *but)
{
if (but->pointype == UI_BUT_POIN_FLOAT && but->poin)
return true;
-
+
if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_FLOAT)
return true;
-
+
return false;
}
@@ -1714,7 +1771,7 @@ bool ui_but_is_unit(const uiBut *but)
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;
@@ -1898,7 +1955,7 @@ void ui_but_value_set(uiBut *but, double value)
if (fval >= -0.00001f && fval <= 0.00001f) fval = 0.0f; /* prevent negative zero */
value = fval;
}
-
+
/* then set value with possible edit override */
if (but->editval)
value = *but->editval = value;
@@ -2032,11 +2089,11 @@ void ui_but_convert_to_unit_alt_name(uiBut *but, char *str, size_t maxlen)
UnitSettings *unit = but->block->unit;
int unit_type = UI_but_unit_type_get(but);
char *orig_str;
-
+
orig_str = BLI_strdup(str);
-
+
bUnit_ToUnitAltName(str, maxlen, orig_str, unit->system, RNA_SUBTYPE_UNIT_VALUE(unit_type));
-
+
MEM_freeN(orig_str);
}
}
@@ -2692,7 +2749,7 @@ void UI_block_free(const bContext *C, uiBlock *block)
BLI_freelistN(&block->saferct);
BLI_freelistN(&block->color_pickers.list);
-
+
MEM_freeN(block);
}
@@ -2721,7 +2778,7 @@ void UI_blocklist_draw(const bContext *C, const ListBase *lb)
void UI_blocklist_free(const bContext *C, ListBase *lb)
{
uiBlock *block;
-
+
while ((block = BLI_pophead(lb))) {
UI_block_free(C, block);
}
@@ -2733,7 +2790,7 @@ void UI_blocklist_free_inactive(const bContext *C, ListBase *lb)
for (block = lb->first; block; block = nextblock) {
nextblock = block->next;
-
+
if (!block->handle) {
if (!block->active) {
BLI_remlink(lb, block);
@@ -2814,11 +2871,6 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, sh
return block;
}
-uiBlock *UI_block_find_in_region(const char *name, ARegion *ar)
-{
- return BLI_findstring(&ar->uiblocks, name, offsetof(uiBlock, name));
-}
-
void UI_block_emboss_set(uiBlock *block, char dt)
{
block->dt = dt;
@@ -2834,9 +2886,9 @@ void ui_but_update_ex(uiBut *but, const bool validate)
/* if something changed in the button */
double value = UI_BUT_VALUE_UNSET;
// float okwidth; // UNUSED
-
+
ui_but_update_select_flag(but, &value);
-
+
/* only update soft range while not editing */
if (!(but->editval || but->editstr || but->editvec)) {
if ((but->rnaprop != NULL) ||
@@ -2865,7 +2917,7 @@ void ui_but_update_ex(uiBut *but, const bool validate)
but->hardmin <= but->hardmax);
}
break;
-
+
case UI_BTYPE_ICON_TOGGLE:
case UI_BTYPE_ICON_TOGGLE_N:
if (!but->rnaprop || (RNA_property_flag(but->rnaprop) & PROP_ICONS_CONSECUTIVE)) {
@@ -2873,21 +2925,21 @@ void ui_but_update_ex(uiBut *but, const bool validate)
else but->iconadd = 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) > 24.0f) {
+ 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)) {
@@ -2970,7 +3022,7 @@ void ui_but_update_ex(uiBut *but, const bool validate)
else {
BLI_strncpy(but->drawstr, but->str, UI_MAX_DRAW_STR);
}
-
+
break;
case UI_BTYPE_TEXT:
@@ -2983,7 +3035,7 @@ void ui_but_update_ex(uiBut *but, const bool validate)
BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s%s", but->str, str);
}
break;
-
+
case UI_BTYPE_KEY_EVENT:
{
const char *str;
@@ -3030,13 +3082,13 @@ void ui_but_update_ex(uiBut *but, const bool validate)
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 */
}
@@ -3129,7 +3181,7 @@ static uiBut *ui_def_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);
@@ -3184,7 +3236,7 @@ static uiBut *ui_def_but(
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 */
@@ -3212,7 +3264,9 @@ static uiBut *ui_def_but(
}
#ifdef USE_NUMBUTS_LR_ALIGN
else if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER)) {
- but->drawflag |= UI_BUT_TEXT_LEFT;
+ if (slen != 0) {
+ but->drawflag |= UI_BUT_TEXT_LEFT;
+ }
}
#endif
@@ -3227,7 +3281,8 @@ static uiBut *ui_def_but(
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, UI_BTYPE_SEPR_LINE,
+ UI_BTYPE_SEPR_SPACER) ||
(but->type >= UI_BTYPE_SEARCH_MENU))
{
/* pass */
@@ -3237,7 +3292,7 @@ static uiBut *ui_def_but(
}
BLI_addtail(&block->buttons, but);
-
+
if (block->curlayout) {
ui_layout_add_but(block->curlayout, but);
}
@@ -3530,7 +3585,7 @@ static uiBut *ui_def_but_rna(
if (icon) {
ui_def_but_icon(but, icon, UI_HAS_ICON);
}
-
+
if ((type == UI_BTYPE_MENU) && (but->dt == UI_EMBOSS_PULLDOWN)) {
but->flag |= UI_BUT_ICON_SUBMENU;
}
@@ -3607,7 +3662,7 @@ uiBut *uiDefBut(uiBlock *block, int type, int retval, const char *str, int x, in
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;
}
@@ -3649,7 +3704,7 @@ struct AutoComplete {
AutoComplete *UI_autocomplete_begin(const char *startname, size_t maxlen)
{
AutoComplete *autocpl;
-
+
autocpl = MEM_callocN(sizeof(AutoComplete), "AutoComplete");
autocpl->maxlen = maxlen;
autocpl->matches = 0;
@@ -3690,7 +3745,7 @@ void UI_autocomplete_update_name(AutoComplete *autocpl, const char *name)
}
int UI_autocomplete_end(AutoComplete *autocpl, char *autoname)
-{
+{
int match = AUTOCOMPLETE_NO_MATCH;
if (autocpl->truncate[0]) {
if (autocpl->matches == 1) {
@@ -3948,7 +4003,7 @@ uiBut *uiDefIconTextButO_ptr(uiBlock *block, int type, wmOperatorType *ot, int o
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')
+ 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);
}
@@ -3961,11 +4016,11 @@ int UI_blocklist_min_y_get(ListBase *lb)
{
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;
-
+
return min;
}
@@ -3984,7 +4039,7 @@ void UI_block_order_flip(uiBlock *block)
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;
@@ -4139,8 +4194,8 @@ void UI_but_unit_type_set(uiBut *but, const int unit_type)
int UI_but_unit_type_get(const uiBut *but)
{
int ownUnit = (int)but->unit_type;
-
- /* own unit define always takes precedence over RNA provided, allowing for overriding
+
+ /* 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 */
@@ -4302,7 +4357,7 @@ uiBut *uiDefIconMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, int ic
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);
@@ -4313,7 +4368,7 @@ uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg,
but->block_create_func = func;
ui_but_update(but);
-
+
return but;
}
@@ -4321,14 +4376,14 @@ uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg,
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;
}
@@ -4355,13 +4410,13 @@ uiBut *uiDefHotKeyevtButS(uiBlock *block, int retval, const char *str, int x, in
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);
-
+
ui_def_but_icon(but, icon, UI_HAS_ICON);
but->drawflag |= UI_BUT_ICON_LEFT | UI_BUT_TEXT_LEFT;
-
+
ui_but_update(but);
-
+
return but;
}
@@ -4385,7 +4440,7 @@ void UI_but_func_search_set(
but->search_create_func = search_create_func;
but->search_func = search_func;
but->search_arg = arg;
-
+
if (bfunc) {
#ifdef DEBUG
if (but->func) {
@@ -4395,7 +4450,7 @@ void UI_but_func_search_set(
#endif
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 */
@@ -4493,14 +4548,14 @@ uiBut *uiDefSearchButO_ptr(
void UI_but_focus_on_enter_event(wmWindow *win, uiBut *but)
{
wmEvent event;
-
+
wm_event_init_from_window(win, &event);
event.type = EVT_BUT_OPEN;
event.val = KM_PRESS;
event.customdata = but;
event.customdatafree = false;
-
+
wm_event_add(win, &event);
}
@@ -4626,7 +4681,7 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
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 */
@@ -4637,8 +4692,11 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
else if (but->optype) {
PointerRNA *opptr = UI_but_operator_ptr_get(but);
wmOperatorType *ot = but->optype;
-
- /* if the default property of the operator is enum and it is set,
+
+ /* 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
@@ -4651,15 +4709,12 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
}
}
}
-
+
/* get strings from matching enum item */
if (ptr && prop) {
if (!item) {
int i;
- /* so the context is passed to itemf functions */
- WM_operator_properties_sanitize(ptr, false);
-
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)
@@ -4720,10 +4775,10 @@ void UI_init(void)
}
/* after reading userdef file */
-void UI_init_userdef(void)
+void UI_init_userdef(Main *bmain)
{
/* fix saved themes */
- init_userdef_do_versions();
+ init_userdef_do_versions(bmain);
uiStyleInit();
}
@@ -4738,4 +4793,3 @@ void UI_exit(void)
ui_but_clipboard_free();
ui_exit_button_group_types();
}
-
diff --git a/source/blender/editors/interface/interface_align.c b/source/blender/editors/interface/interface_align.c
index 1fc38a27303..c945746c2df 100644
--- a/source/blender/editors/interface/interface_align.c
+++ b/source/blender/editors/interface/interface_align.c
@@ -111,7 +111,7 @@ enum {
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_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));
}
@@ -499,7 +499,8 @@ void ui_block_align_calc(uiBlock *block, const ARegion *region)
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);
+ 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)
@@ -524,7 +525,7 @@ 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) {
@@ -535,7 +536,7 @@ static void ui_block_align_calc_but(uiBut *first, short nr)
}
/* 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;
@@ -544,13 +545,13 @@ static void ui_block_align_calc_but(uiBut *first, short nr)
/* 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
+ else
flag = UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_RIGHT;
}
else {
@@ -597,14 +598,14 @@ static void ui_block_align_calc_but(uiBut *first, short nr)
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))
@@ -614,16 +615,16 @@ static void ui_block_align_calc_but(uiBut *first, short nr)
flag = UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_LEFT;
}
}
- else
+ else
flag |= UI_BUT_ALIGN_DOWN;
}
- else
+ else
flag |= UI_BUT_ALIGN_TOP;
}
}
-
+
but->drawflag |= flag;
-
+
/* merge coordinates */
if (prev) {
/* simple cases */
@@ -646,7 +647,7 @@ static void ui_block_align_calc_but(uiBut *first, short nr)
/* 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;
diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c
index 812f4ef0747..cda70d405ad 100644
--- a/source/blender/editors/interface/interface_anim.c
+++ b/source/blender/editors/interface/interface_anim.c
@@ -41,8 +41,10 @@
#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
+#include "BKE_main.h"
#include "BKE_nla.h"
+#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "ED_keyframing.h"
@@ -72,26 +74,26 @@ void ui_but_anim_flag(uiBut *but, float cfra)
FCurve *fcu;
bool driven;
bool special;
-
+
but->flag &= ~(UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN);
-
+
/* 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,
+
+ /* 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;
}
@@ -101,6 +103,30 @@ void ui_but_anim_flag(uiBut *but, float cfra)
}
}
+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_AUTO;
+ }
+ else if (flag & UI_BUT_ANIMATED_KEY) {
+ but->icon = ICON_SPACE2;
+ }
+ else if (flag & UI_BUT_ANIMATED) {
+ but->icon = ICON_SPACE3;
+ }
+ else if (flag & UI_BUT_OVERRIDEN) {
+ but->icon = ICON_LIBRARY_DATA_OVERRIDE;
+ }
+ else {
+ but->icon = ICON_DOT;
+ }
+
+ const int flag_copy = (UI_BUT_DISABLED | UI_BUT_INACTIVE);
+ but->flag = (but->flag & ~flag_copy) | (flag & flag_copy);
+}
+
/**
* \a str can be NULL to only perform check if \a but has an expression at all.
* \return if button has an expression.
@@ -110,9 +136,9 @@ bool ui_but_anim_expression_get(uiBut *but, char *str, size_t maxlen)
FCurve *fcu;
ChannelDriver *driver;
bool driven, special;
-
+
fcu = ui_but_get_fcurve(but, NULL, NULL, &driven, &special);
-
+
if (fcu && driven) {
driver = fcu->driver;
@@ -137,20 +163,20 @@ bool ui_but_anim_expression_set(uiBut *but, const char *str)
if (fcu && driven) {
driver = fcu->driver;
-
+
if (driver && (driver->type == DRIVER_TYPE_PYTHON)) {
BLI_strncpy_utf8(driver->expression, str, sizeof(driver->expression));
-
+
/* tag driver as needing to be recompiled */
driver->flag |= DRIVER_FLAG_RECOMPILE;
-
+
/* 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);
-
+
return true;
}
}
@@ -166,14 +192,14 @@ bool ui_but_anim_expression_create(uiBut *but, const char *str)
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)
@@ -181,7 +207,7 @@ bool ui_but_anim_expression_create(uiBut *but, const char *str)
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;
@@ -190,18 +216,18 @@ bool ui_but_anim_expression_create(uiBut *but, const char *str)
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;
@@ -217,14 +243,15 @@ bool ui_but_anim_expression_create(uiBut *but, const char *str)
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;
@@ -232,17 +259,18 @@ void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra)
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(reports, but->rnapoin, but->rnaprop, fcu, cfra, ts->keyframe_type, 0);
+
+ insert_keyframe_direct(depsgraph, reports, but->rnapoin, but->rnaprop, fcu, cfra, ts->keyframe_type, 0);
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
}
}
@@ -251,31 +279,34 @@ void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra)
* 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(reports, but->rnapoin, but->rnaprop, fcu, cfra, ts->keyframe_type, INSERTKEY_DRIVER);
+
+ insert_keyframe_direct(depsgraph, reports, but->rnapoin, but->rnaprop, fcu, cfra, ts->keyframe_type, 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(reports, id, action, ((fcu->grp) ? (fcu->grp->name) : (NULL)),
+ insert_keyframe(bmain, depsgraph, reports, id, action,
+ ((fcu->grp) ? (fcu->grp->name) : (NULL)),
fcu->rna_path, but->rnaindex, cfra, ts->keyframe_type, flag);
-
+
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
}
}
@@ -292,3 +323,38 @@ 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);
}
+
+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--;
+}
diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c
new file mode 100644
index 00000000000..d425ba1f985
--- /dev/null
+++ b/source/blender/editors/interface/interface_context_menu.c
@@ -0,0 +1,787 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/interface/interface_context_menu.c
+ * \ingroup edinterface
+ *
+ * Generic context popup menus.
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "BLT_translation.h"
+
+#include "BKE_addon.h"
+#include "BKE_context.h"
+#include "BKE_idprop.h"
+#include "BKE_screen.h"
+
+#include "ED_screen.h"
+#include "ED_keyframing.h"
+
+#include "UI_interface.h"
+
+#include "interface_intern.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+/* This hack is needed because we don't have a good way to re-reference keymap items once added: T42944 */
+#define USE_KEYMAP_ADD_HACK
+
+/* -------------------------------------------------------------------- */
+/** \name Button Context Menu
+ * \{ */
+
+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);
+ }
+ }
+}
+
+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, true, &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, -50, 26);
+
+ return block;
+}
+
+#ifdef USE_KEYMAP_ADD_HACK
+static int g_kmi_id_hack;
+#endif
+
+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;
+
+ /* 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);
+
+ /* 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);
+
+ 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);
+
+ 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, -50, 26);
+
+#ifdef USE_KEYMAP_ADD_HACK
+ g_kmi_id_hack = kmi_id;
+#endif
+ return block;
+}
+
+static void menu_add_shortcut_cancel(struct bContext *C, void *arg1)
+{
+ uiBut *but = (uiBut *)arg1;
+ wmKeyMap *km;
+ wmKeyMapItem *kmi;
+#ifndef USE_KEYMAP_ADD_HACK
+ IDProperty *prop;
+#endif
+ int kmi_id;
+
+#ifdef USE_KEYMAP_ADD_HACK
+ 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);
+#endif
+
+ 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);
+}
+
+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, true, &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);
+}
+
+static bool ui_but_is_user_menu_compatible(uiBut *but)
+{
+ return (but->optype || UI_but_menutype_get(but));
+}
+
+static bUserMenuItem *ui_but_user_menu_find(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 ((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(uiBut *but, bUserMenu *um)
+{
+ BLI_assert(ui_but_is_user_menu_compatible(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) {
+ ED_screen_user_menu_item_add_operator(
+ &um->items, drawstr,
+ but->optype, but->opptr ? but->opptr->data : NULL, but->opcontext);
+ }
+ 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(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);
+}
+
+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);
+}
+
+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);
+ }
+
+ 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);*/ /* XXX does not work as expected, not strictly needed */
+ 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;
+
+ /* Keyframes */
+ if (but->flag & UI_BUT_ANIMATED_KEY) {
+ /* Set the (button_pointer, button_prop) and pointer data for Python access to the hovered ui element. */
+ uiLayoutSetContextFromBut(layout, but);
+
+ /* 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);
+#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_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);
+ }
+ }
+
+ /* 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, false, &km);
+
+ /* We do have a shortcut, but only keyboard ones are editbale 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_NONE,
+ 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 'add' 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, "Add 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);
+ }
+
+ /* Favorites Menu */
+ if (ui_but_is_user_menu_compatible(but)) {
+ uiBlock *block = uiLayoutGetBlock(layout);
+ const int w = uiLayoutGetWidth(layout);
+ uiBut *but2;
+
+ but2 = uiDefIconTextBut(
+ block, UI_BTYPE_BUT, 0, ICON_MENU_PANEL,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add to Favorites Menu"),
+ 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);
+
+ bUserMenu *um = ED_screen_user_menu_find(C);
+ if (um) {
+ bUserMenuItem *umi = ui_but_user_menu_find(but, um);
+ if (umi != NULL) {
+ but2 = uiDefIconTextBut(
+ block, UI_BTYPE_BUT, 0, ICON_CANCEL,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Favorites Menu"),
+ 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+ UI_but_func_set(but2, popup_user_menu_remove_func, um, umi);
+ }
+ }
+ uiItemS(layout);
+ }
+
+ /* Show header tools for header buttons. */
+ if (ui_block_is_menu(but->block) == false) {
+ ARegion *ar = CTX_wm_region(C);
+ if (ar && (ar->regiontype == RGN_TYPE_HEADER)) {
+ uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL);
+ 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");
+
+ 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));
+#endif
+ }
+ }
+
+ if (but->optype) {
+ 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);
+ }
+
+ 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);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Panel Context Menu
+ * \{ */
+
+/**
+ * menu to show when right clicking on the panel header
+ */
+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);
+}
+
+/** \} */
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index ce22dac9e91..ab85a3d5326 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -58,6 +58,7 @@
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "UI_interface.h"
@@ -119,7 +120,7 @@ void UI_draw_roundbox_aa(bool filled, float minx, float miny, float maxx, float
.alpha_discard = 1.0f,
};
- glEnable(GL_BLEND);
+ GPU_blend(true);
if (filled) {
/* plain antialiased filled box */
@@ -135,17 +136,17 @@ void UI_draw_roundbox_aa(bool filled, float minx, float miny, float maxx, float
}
else {
/* plain antialiased unfilled box */
- glEnable(GL_LINE_SMOOTH);
+ GPU_line_smooth(true);
Gwn_Batch *batch = ui_batch_roundbox_get(filled, false);
GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
GWN_batch_draw(batch);
- glDisable(GL_LINE_SMOOTH);
+ GPU_line_smooth(false);
}
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
void UI_draw_roundbox_4fv(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float col[4])
@@ -184,7 +185,7 @@ void UI_draw_roundbox_4fv(bool filled, float minx, float miny, float maxx, float
else {
immVertex2f(pos, maxx, miny);
}
-
+
/* corner right-top */
if (roundboxtype & UI_CNR_TOP_RIGHT) {
immVertex2f(pos, maxx, maxy - rad);
@@ -196,7 +197,7 @@ void UI_draw_roundbox_4fv(bool filled, float minx, float miny, float maxx, float
else {
immVertex2f(pos, maxx, maxy);
}
-
+
/* corner left-top */
if (roundboxtype & UI_CNR_TOP_LEFT) {
immVertex2f(pos, minx + rad, maxy);
@@ -208,7 +209,7 @@ void UI_draw_roundbox_4fv(bool filled, float minx, float miny, float maxx, float
else {
immVertex2f(pos, minx, maxy);
}
-
+
/* corner left-bottom */
if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
immVertex2f(pos, minx, miny + rad);
@@ -220,7 +221,7 @@ void UI_draw_roundbox_4fv(bool filled, float minx, float miny, float maxx, float
else {
immVertex2f(pos, minx, miny);
}
-
+
immEnd();
immUnbindProgram();
#endif
@@ -302,15 +303,15 @@ void UI_draw_roundbox_shade_x(
/* 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);
}
@@ -318,13 +319,13 @@ void UI_draw_roundbox_shade_x(
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]);
@@ -336,18 +337,18 @@ void UI_draw_roundbox_shade_x(
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);
}
@@ -355,18 +356,18 @@ void UI_draw_roundbox_shade_x(
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);
}
@@ -418,7 +419,7 @@ void UI_draw_roundbox_shade_y(
float colLeft[3], colRight[3];
int vert_count = 0;
int a;
-
+
/* mult */
for (a = 0; a < 7; a++) {
mul_v2_fl(vec[a], rad);
@@ -450,12 +451,12 @@ void UI_draw_roundbox_shade_y(
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);
}
@@ -463,14 +464,14 @@ void UI_draw_roundbox_shade_y(
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]);
}
@@ -481,17 +482,17 @@ void UI_draw_roundbox_shade_y(
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);
}
@@ -499,17 +500,17 @@ void UI_draw_roundbox_shade_y(
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);
}
@@ -638,20 +639,20 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w
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 */
- GLint scissor[4];
- glGetIntegerv(GL_SCISSOR_BOX, scissor);
- glScissor(rect->xmin, rect->ymin, w, h);
+ int scissor[4];
+ GPU_scissor_geti(scissor);
+ GPU_scissor(rect->xmin, rect->ymin, w, h);
#endif
-
- glEnable(GL_BLEND);
-
+
+ GPU_blend(true);
+
if (w != ibuf->x || h != ibuf->y) {
facx = (float)w / (float)ibuf->x;
facy = (float)h / (float)ibuf->y;
@@ -660,14 +661,14 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w
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);
-
- glDisable(GL_BLEND);
-
+
+ GPU_blend(false);
+
#if 0
// restore scissortest
- glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
+ GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
#endif
-
+
#endif
}
@@ -710,9 +711,9 @@ void UI_draw_safe_areas(
static void draw_scope_end(const rctf *rect, GLint *scissor)
{
/* restore scissortest */
- glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
+ GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
@@ -731,14 +732,14 @@ static void histogram_draw_one(
if (res == 0)
return;
- glEnable(GL_LINE_SMOOTH);
+ GPU_line_smooth(true);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE, GL_ONE);
immUniformColor4fv(color);
if (is_line) {
/* curve outline */
- glLineWidth(1.5);
+ GPU_line_width(1.5);
immBegin(GWN_PRIM_LINE_STRIP, res);
for (int i = 0; i < res; i++) {
@@ -762,7 +763,7 @@ static void histogram_draw_one(
/* curve outline */
immUniformColor4f(0.0f, 0.0f, 0.0f, 0.25f);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
immBegin(GWN_PRIM_LINE_STRIP, res);
for (int i = 0; i < res; i++) {
float x2 = x + i * (w / (float)res);
@@ -771,7 +772,7 @@ static void histogram_draw_one(
immEnd();
}
- glDisable(GL_LINE_SMOOTH);
+ GPU_line_smooth(false);
}
#define HISTOGRAM_TOT_GRID_LINES 4
@@ -788,12 +789,12 @@ void ui_draw_but_HISTOGRAM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUS
.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;
-
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
float color[4];
UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
@@ -801,9 +802,9 @@ void ui_draw_but_HISTOGRAM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUS
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 */
- GLint scissor[4];
- glGetIntegerv(GL_SCISSOR_BOX, scissor);
- glScissor((rect.xmin - 1),
+ int scissor[4];
+ GPU_scissor_geti(scissor);
+ GPU_scissor((rect.xmin - 1),
(rect.ymin - 1),
(rect.xmax + 1) - (rect.xmin - 1),
(rect.ymax + 1) - (rect.ymin - 1));
@@ -850,7 +851,7 @@ void ui_draw_but_HISTOGRAM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUS
}
immUnbindProgram();
-
+
/* outline */
draw_scope_end(&rect, scissor);
}
@@ -879,14 +880,14 @@ static void waveform_draw_one(float *waveform, int nbr, const float col[3])
void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
{
Scopes *scopes = (Scopes *)but->poin;
- GLint scissor[4];
+ int scissor[4];
float colors[3][3];
float colorsycc[3][3] = {{1, 0, 1}, {1, 1, 0}, {0, 1, 1}};
float colors_alpha[3][3], colorsycc_alpha[3][3]; /* colors pre multiplied by alpha for speed up */
float min, max;
-
+
if (scopes == NULL) return;
-
+
rctf rect = {
.xmin = (float)recti->xmin + 1,
.xmax = (float)recti->xmax - 1,
@@ -900,10 +901,10 @@ void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSE
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++) {
@@ -916,8 +917,8 @@ void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSE
/* Flush text cache before changing scissors. */
BLF_batch_draw_flush();
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
float color[4];
UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
@@ -925,8 +926,8 @@ void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSE
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 */
- glGetIntegerv(GL_SCISSOR_BOX, scissor);
- glScissor((rect.xmin - 1),
+ GPU_scissor_geti(scissor);
+ GPU_scissor((rect.xmin - 1),
(rect.ymin - 1),
(rect.xmax + 1) - (rect.xmin - 1),
(rect.ymax + 1) - (rect.ymin - 1));
@@ -943,8 +944,8 @@ void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSE
/* Flush text cache before drawing things on top. */
BLF_batch_draw_flush();
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -974,7 +975,7 @@ void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSE
immEnd();
}
-
+
/* separate min max zone on the right */
immBegin(GWN_PRIM_LINES, 2);
immVertex2f(pos, rect.xmin + w, rect.ymin);
@@ -1010,7 +1011,7 @@ void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSE
if (scopes->ok && scopes->waveform_1 != NULL) {
glBlendFunc(GL_ONE, GL_ONE);
- glPointSize(1.0);
+ GPU_point_size(1.0);
/* LUMA (1 channel) */
if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) {
@@ -1098,7 +1099,7 @@ void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSE
/* outline */
draw_scope_end(&rect, scissor);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
static float polar_to_x(float center, float diam, float ampli, float angle)
@@ -1171,24 +1172,24 @@ void ui_draw_but_VECTORSCOPE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UN
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;
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
float color[4];
UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
@@ -1196,13 +1197,13 @@ void ui_draw_but_VECTORSCOPE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UN
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 */
- GLint scissor[4];
- glGetIntegerv(GL_SCISSOR_BOX, scissor);
- glScissor((rect.xmin - 1),
+ int scissor[4];
+ GPU_scissor_geti(scissor);
+ GPU_scissor((rect.xmin - 1),
(rect.ymin - 1),
(rect.xmax + 1) - (rect.xmin - 1),
(rect.ymax + 1) - (rect.ymin - 1));
-
+
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -1243,13 +1244,13 @@ void ui_draw_but_VECTORSCOPE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UN
/* 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);
- glPointSize(1.0);
+ GPU_point_size(1.0);
gpuPushMatrix();
gpuTranslate2f(centerx, centery);
@@ -1265,12 +1266,12 @@ void ui_draw_but_VECTORSCOPE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UN
/* outline */
draw_scope_end(&rect, scissor);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
static void ui_draw_colorband_handle_tri_hlight(unsigned int pos, float x1, float y1, float halfwidth, float height)
{
- glEnable(GL_LINE_SMOOTH);
+ GPU_line_smooth(true);
immBegin(GWN_PRIM_LINE_STRIP, 3);
immVertex2f(pos, x1 + halfwidth, y1);
@@ -1278,7 +1279,7 @@ static void ui_draw_colorband_handle_tri_hlight(unsigned int pos, float x1, floa
immVertex2f(pos, x1 - halfwidth, y1);
immEnd();
- glDisable(GL_LINE_SMOOTH);
+ GPU_line_smooth(false);
}
static void ui_draw_colorband_handle_tri(unsigned int pos, float x1, float y1, float halfwidth, float height, bool fill)
@@ -1329,7 +1330,7 @@ static void ui_draw_colorband_handle(
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
immUniform1i("num_colors", 2); /* "advanced" mode */
@@ -1358,7 +1359,7 @@ static void ui_draw_colorband_handle(
ui_draw_colorband_handle_box(shdr_pos, x - half_width, y1 - 1, x + half_width, y1 + height, false);
/* draw all triangles blended */
- glEnable(GL_BLEND);
+ GPU_blend(true);
ui_draw_colorband_handle_tri(shdr_pos, x, y1 + height, half_width, half_width, true);
@@ -1377,7 +1378,7 @@ static void ui_draw_colorband_handle(
immUniformColor3ub(0, 0, 0);
ui_draw_colorband_handle_tri_hlight(shdr_pos, x, y1 + height, half_width, half_width);
- glDisable(GL_BLEND);
+ 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);
@@ -1425,7 +1426,7 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
/* layer: color ramp */
- glEnable(GL_BLEND);
+ GPU_blend(true);
CBData *cbd = coba->data;
@@ -1434,16 +1435,16 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
v1[1] = y1 + sizey_solid;
v2[1] = rect->ymax;
-
+
immBegin(GWN_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;
-
+
immAttrib4fv(color, colf);
immVertex2fv(position, v1);
immVertex2fv(position, v2);
@@ -1471,7 +1472,7 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
immUnbindProgram();
- glDisable(GL_BLEND);
+ GPU_blend(false);
/* New format */
format = immVertexFormat();
@@ -1483,7 +1484,7 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
imm_draw_box_wire_2d(position, x1, y1, x1 + sizex, rect->ymax);
/* layer: box outline */
- glEnable(GL_BLEND);
+ GPU_blend(true);
immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
immBegin(GWN_PRIM_LINES, 2);
@@ -1498,8 +1499,8 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
immVertex2f(position, x1 + sizex, y1 - 1);
immEnd();
- glDisable(GL_BLEND);
-
+ GPU_blend(false);
+
/* layer: draw handles */
for (int a = 0; a < coba->tot; a++, cbd++) {
if (a != coba->cur) {
@@ -1524,20 +1525,20 @@ void ui_draw_but_UNITVEC(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
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, (unsigned char *)wcol->inner, 255);
-
+
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
-
+
/* setup lights */
ui_but_v3_get(but, light);
/* transform to button */
gpuPushMatrix();
-
+
if (BLI_rcti_size_x(rect) < BLI_rcti_size_y(rect))
size = 0.5f * BLI_rcti_size_x(rect);
else
@@ -1554,18 +1555,18 @@ void ui_draw_but_UNITVEC(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
/* restore */
glDisable(GL_CULL_FACE);
-
+
/* AA circle */
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3ubv((unsigned char *)wcol->inner);
- glEnable(GL_BLEND);
- glEnable(GL_LINE_SMOOTH);
+ GPU_blend(true);
+ GPU_line_smooth(true);
imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, 1.0f, 32);
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
+ GPU_blend(false);
+ GPU_line_smooth(false);
/* matrix after circle */
gpuPopMatrix();
@@ -1578,7 +1579,7 @@ static void ui_draw_but_curve_grid(unsigned int pos, const rcti *rect, float zoo
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));
@@ -1598,7 +1599,7 @@ static void ui_draw_but_curve_grid(unsigned int pos, const rcti *rect, float zoo
fy += dy;
}
immEnd();
-
+
}
static void gl_shaded_color(unsigned char *col, int shade)
@@ -1622,8 +1623,8 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
CurveMap *cuma = &cumap->cm[cumap->cur];
/* need scissor test, curve can draw outside of boundary */
- GLint scissor[4];
- glGetIntegerv(GL_SCISSOR_BOX, scissor);
+ int scissor[4];
+ GPU_scissor_geti(scissor);
rcti scissor_new = {
.xmin = rect->xmin,
.ymin = rect->ymin,
@@ -1632,7 +1633,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
};
rcti scissor_region = {0, ar->winx, 0, ar->winy};
BLI_rcti_isect(&scissor_new, &scissor_region, &scissor_new);
- glScissor(scissor_new.xmin,
+ GPU_scissor(scissor_new.xmin,
scissor_new.ymin,
BLI_rcti_size_x(&scissor_new),
BLI_rcti_size_y(&scissor_new));
@@ -1658,7 +1659,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
ui_draw_gradient(&grid, col, UI_GRAD_H, 1.0f);
}
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -1667,11 +1668,11 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
/* backdrop */
if (but->a1 == UI_GRAD_H) {
/* grid, hsv uses different grid */
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
immUniformColor4ub(0, 0, 0, 48);
ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.1666666f);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
else {
if (cumap->flag & CUMA_DO_CLIP) {
@@ -1732,7 +1733,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
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);
}
@@ -1743,7 +1744,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
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);
}
@@ -1752,10 +1753,10 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
/* the curve */
immUniformColor3ubv((unsigned char *)wcol->item);
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
+ GPU_line_smooth(true);
+ GPU_blend(true);
immBegin(GWN_PRIM_LINE_STRIP, (CM_TABLE + 1) + 2);
-
+
if (cuma->table == NULL)
curvemapping_changed(cumap, false);
@@ -1785,8 +1786,8 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
immVertex2f(pos, fx, fy);
}
immEnd();
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
+ GPU_line_smooth(false);
+ GPU_blend(false);
immUnbindProgram();
/* the points, use aspect to make them visible on edges */
@@ -1796,7 +1797,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
cmp = cuma->curve;
- glPointSize(3.0f);
+ GPU_point_size(3.0f);
immBegin(GWN_PRIM_POINTS, cuma->totpoint);
for (int a = 0; a < cuma->totpoint; a++) {
float color[4];
@@ -1811,9 +1812,9 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
}
immEnd();
immUnbindProgram();
-
+
/* restore scissortest */
- glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
+ GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
/* outline */
format = immVertexFormat();
@@ -1841,13 +1842,13 @@ void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *U
int width = BLI_rctf_size_x(&rect) + 1;
int height = BLI_rctf_size_y(&rect);
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
/* need scissor test, preview image can draw outside of boundary */
- GLint scissor[4];
- glGetIntegerv(GL_SCISSOR_BOX, scissor);
- glScissor((rect.xmin - 1),
+ int scissor[4];
+ GPU_scissor_geti(scissor);
+ GPU_scissor((rect.xmin - 1),
(rect.ymin - 1),
(rect.xmax + 1) - (rect.xmin - 1),
(rect.ymax + 1) - (rect.ymin - 1));
@@ -1885,7 +1886,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *U
gpuPushMatrix();
/* draw content of pattern area */
- glScissor(rect.xmin, rect.ymin, scissor[2], scissor[3]);
+ GPU_scissor(rect.xmin, rect.ymin, scissor[2], scissor[3]);
if (width > 0 && height > 0) {
ImBuf *drawibuf = scopes->track_preview;
@@ -1902,7 +1903,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *U
/* draw cross for pixel position */
gpuTranslate2f(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1]);
- glScissor(rect.xmin,
+ GPU_scissor(rect.xmin,
rect.ymin,
BLI_rctf_size_x(&rect),
BLI_rctf_size_y(&rect));
@@ -1953,13 +1954,13 @@ void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *U
/* outline */
draw_scope_end(&rect, scissor);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, 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,
@@ -1974,12 +1975,12 @@ void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol
-0.99486932f, -0.87434661f, -0.61210598f, -0.25065253f,
0.15142777f, 0.52896401f, 0.82076344f, 0.97952994f,
};
-
- GLint scissor[4];
-
+
+ int scissor[4];
+
/* need scissor test, can draw outside of boundary */
- glGetIntegerv(GL_SCISSOR_BOX, scissor);
-
+ GPU_scissor_geti(scissor);
+
rcti scissor_new = {
.xmin = recti->xmin,
.ymin = recti->ymin,
@@ -1990,11 +1991,11 @@ void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol
rcti scissor_region = {0, ar->winx, 0, ar->winy};
BLI_rcti_isect(&scissor_new, &scissor_region, &scissor_new);
- glScissor(scissor_new.xmin,
+ 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);
@@ -2003,26 +2004,26 @@ void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4ubv(but->col);
- glEnable(GL_BLEND);
+ GPU_blend(true);
immBegin(GWN_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);
- glLineWidth(1);
- glEnable(GL_LINE_SMOOTH);
+ GPU_line_width(1);
+ GPU_line_smooth(true);
immBegin(GWN_PRIM_LINE_LOOP, 16);
for (int a = 0; a < 16; a++)
immVertex2f(pos, x + size * si[a], y + size * co[a]);
immEnd();
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
+ GPU_line_smooth(false);
+ GPU_blend(false);
immUnbindProgram();
-
+
/* restore scissortest */
- glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
+ GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
}
/* ****************************************************** */
@@ -2093,7 +2094,7 @@ static void ui_shadowbox(unsigned pos, unsigned color, float minx, float miny, f
void UI_draw_box_shadow(unsigned char alpha, float minx, float miny, float maxx, float maxy)
{
- glEnable(GL_BLEND);
+ GPU_blend(true);
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -2107,19 +2108,19 @@ void UI_draw_box_shadow(unsigned char alpha, float minx, float miny, float maxx,
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();
immUnbindProgram();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int UNUSED(select))
{
float rad;
-
+
if (radius > (BLI_rctf_size_y(rct) - 10.0f) * 0.5f)
rad = (BLI_rctf_size_y(rct) - 10.0f) * 0.5f;
else
@@ -2135,8 +2136,8 @@ void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha
{
a = i * aspect;
}
-
- glEnable(GL_BLEND);
+
+ GPU_blend(true);
const float dalpha = alpha * 2.0f / 255.0f;
float calpha = dalpha;
float visibility = 1.0f;
@@ -2151,7 +2152,7 @@ void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha
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,
@@ -2173,10 +2174,10 @@ void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha
GWN_batch_draw(batch);
/* outline emphasis */
- glEnable(GL_LINE_SMOOTH);
+ 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);
- glDisable(GL_LINE_SMOOTH);
-
- glDisable(GL_BLEND);
+ 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 8cb55b724fb..eb8fff471e2 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -180,4 +180,3 @@ uiBut *eyedropper_get_property_button_under_mouse(bContext *C, const wmEvent *ev
}
/** \} */
-
diff --git a/source/blender/editors/interface/interface_eyedropper_color.c b/source/blender/editors/interface/interface_eyedropper_color.c
index f3301d55284..a60b6f3f60b 100644
--- a/source/blender/editors/interface/interface_eyedropper_color.c
+++ b/source/blender/editors/interface/interface_eyedropper_color.c
@@ -38,6 +38,7 @@
#include "BLI_math_vector.h"
#include "BKE_context.h"
+#include "BKE_main.h"
#include "BKE_screen.h"
#include "RNA_access.h"
@@ -131,6 +132,7 @@ 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;
@@ -156,7 +158,7 @@ void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3])
int mval[2] = {mx - ar->winrct.xmin,
my - ar->winrct.ymin};
- if (ED_space_node_color_sample(snode, ar, mval, r_col)) {
+ if (ED_space_node_color_sample(bmain, snode, ar, mval, r_col)) {
return;
}
}
diff --git a/source/blender/editors/interface/interface_eyedropper_depth.c b/source/blender/editors/interface/interface_eyedropper_depth.c
index fd9c5f1869d..df09c327da1 100644
--- a/source/blender/editors/interface/interface_eyedropper_depth.c
+++ b/source/blender/editors/interface/interface_eyedropper_depth.c
@@ -41,6 +41,7 @@
#include "BLI_math_vector.h"
#include "BKE_context.h"
+#include "BKE_main.h"
#include "BKE_screen.h"
#include "BKE_unit.h"
@@ -169,7 +170,7 @@ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx,
if (sa->spacetype == SPACE_VIEW3D) {
ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my);
if (ar) {
- struct Depsgraph *graph = CTX_data_depsgraph(C);
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
View3D *v3d = sa->spacedata.first;
RegionView3D *rv3d = ar->regiondata;
/* weak, we could pass in some reference point */
@@ -187,7 +188,7 @@ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx,
view3d_operator_needs_opengl(C);
- if (ED_view3d_autodist(graph, ar, v3d, mval, co, true, NULL)) {
+ 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};
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 42e37bc5905..f92058137b2 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -17,7 +17,7 @@
*
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -27,7 +27,6 @@
* \ingroup edinterface
*/
-
#include <float.h>
#include <limits.h>
#include <math.h>
@@ -40,22 +39,18 @@
#include "DNA_brush_types.h"
-#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "BLI_math.h"
#include "BLI_listbase.h"
#include "BLI_linklist.h"
-#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
#include "BLI_string_cursor_utf8.h"
#include "BLI_rect.h"
#include "BLI_utildefines.h"
-#include "BLT_translation.h"
-
#include "PIL_time.h"
#include "BKE_colorband.h"
@@ -63,7 +58,6 @@
#include "BKE_brush.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
-#include "BKE_idprop.h"
#include "BKE_report.h"
#include "BKE_screen.h"
#include "BKE_tracking.h"
@@ -72,7 +66,6 @@
#include "ED_screen.h"
#include "ED_undo.h"
-#include "ED_keyframing.h"
#include "UI_interface.h"
#include "UI_view2d.h"
@@ -89,6 +82,7 @@
#ifdef WITH_INPUT_IME
# include "wm_window.h"
+# include "BLT_translation.h"
# include "BLT_lang.h"
#endif
@@ -111,9 +105,6 @@
#define UI_MAX_PASSWORD_STR 128
-/* This hack is needed because we don't have a good way to re-reference keymap items once added: T42944 */
-#define USE_KEYMAP_ADD_HACK
-
/* proto */
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);
@@ -296,7 +287,7 @@ typedef struct uiHandleButtonData {
/* tooltip */
unsigned int tooltip_force : 1;
-
+
/* auto open */
bool used_mouse;
wmTimer *autoopentimer;
@@ -338,7 +329,7 @@ typedef struct uiHandleButtonData {
/* menu open (watch UI_screen_free_active_but) */
uiPopupBlockHandle *menu;
int menuretval;
-
+
/* search box (watch UI_screen_free_active_but) */
ARegion *searchbox;
#ifdef USE_KEYNAV_LIMIT
@@ -365,14 +356,14 @@ typedef struct uiAfterFunc {
uiButHandleFunc func;
void *func_arg1;
void *func_arg2;
-
+
uiButHandleNFunc funcN;
void *func_argN;
uiButHandleRenameFunc rename_func;
void *rename_arg1;
void *rename_orig;
-
+
uiBlockHandleFunc handle_func;
void *handle_func_arg;
int retval;
@@ -459,38 +450,23 @@ void ui_pan_to_scroll(const wmEvent *event, int *type, int *val)
}
else {
lastdy += dy;
-
+
if (ABS(lastdy) > (int)UI_UNIT_Y) {
if (U.uiflag2 & USER_TRACKPAD_NATURAL)
dy = -dy;
-
+
*val = KM_PRESS;
-
+
if (dy > 0)
*type = WHEELUPMOUSE;
else
*type = WHEELDOWNMOUSE;
-
+
lastdy = 0;
}
}
}
-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);
-}
-
-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);
-
-}
-
static uiBut *ui_but_prev(uiBut *but)
{
while (but->prev) {
@@ -512,7 +488,7 @@ static uiBut *ui_but_next(uiBut *but)
static uiBut *ui_but_first(uiBlock *block)
{
uiBut *but;
-
+
but = block->buttons.first;
while (but) {
if (ui_but_is_editable(but)) return but;
@@ -524,7 +500,7 @@ static uiBut *ui_but_first(uiBlock *block)
static uiBut *ui_but_last(uiBlock *block)
{
uiBut *but;
-
+
but = block->buttons.last;
while (but) {
if (ui_but_is_editable(but)) return but;
@@ -581,7 +557,7 @@ static void ui_mouse_scale_warp(
float *r_mx, float *r_my, const bool 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);
@@ -692,7 +668,7 @@ static void ui_apply_but_func(bContext *C, uiBut *but)
after->butm_func_arg = block->butm_func_arg;
after->a2 = but->a2;
}
-
+
if (block->handle)
after->popup_op = block->handle->popup_op;
@@ -807,17 +783,17 @@ static void ui_apply_but_funcs_after(bContext *C)
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);
}
@@ -855,32 +831,32 @@ static void ui_apply_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data)
{
double value;
int w, lvalue, push;
-
+
value = ui_but_value_get(but);
lvalue = (int)value;
-
+
if (but->bit) {
w = UI_BITBUT_TEST(lvalue, but->bitnr);
if (w) lvalue = UI_BITBUT_CLR(lvalue, but->bitnr);
else lvalue = UI_BITBUT_SET(lvalue, but->bitnr);
-
+
ui_but_value_set(but, (double)lvalue);
if (but->type == UI_BTYPE_ICON_TOGGLE || but->type == UI_BTYPE_ICON_TOGGLE_N) {
ui_but_update_edited(but);
}
}
else {
-
+
if (value == 0.0) push = 1;
else push = 0;
-
+
if (ELEM(but->type, UI_BTYPE_TOGGLE_N, UI_BTYPE_ICON_TOGGLE_N, UI_BTYPE_CHECKBOX_N)) push = !push;
ui_but_value_set(but, (double)push);
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);
data->retval = but->retval;
@@ -1242,12 +1218,39 @@ static void ui_multibut_states_apply(bContext *C, uiHandleButtonData *data, uiBl
#ifdef USE_DRAG_TOGGLE
+/* Helpers that wrap boolean functions, to support different kinds of buttons. */
+
+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_SPACE2, ICON_SPACE3, ICON_DOT, ICON_LIBRARY_DATA_OVERRIDE);
+ }
+ else {
+ return false;
+ }
+}
+
+static bool ui_drag_toggle_but_is_pushed(uiBut *but)
+{
+ if (ui_but_is_bool(but)) {
+ return ui_but_is_pushed(but);
+ }
+ else if (UI_but_is_decorator(but)) {
+ return (but->icon == ICON_SPACE2);
+ }
+ else {
+ return false;
+ }
+}
+
typedef struct uiDragToggleHandle {
/* init */
bool is_init;
bool is_set;
float but_cent_start[2];
- eButType but_type_start;
bool xy_lock[2];
int xy_init[2];
@@ -1255,7 +1258,7 @@ typedef struct uiDragToggleHandle {
} uiDragToggleHandle;
static bool ui_drag_toggle_set_xy_xy(
- bContext *C, ARegion *ar, const bool is_set, const eButType but_type_start,
+ bContext *C, ARegion *ar, const bool is_set,
const int xy_src[2], const int xy_dst[2])
{
/* popups such as layers won't re-evaluate on redraw */
@@ -1279,10 +1282,9 @@ static bool ui_drag_toggle_set_xy_xy(
if (BLI_rctf_isect_segment(&but->rect, xy_a_block, xy_b_block)) {
/* execute the button */
- if (ui_but_is_bool(but) && but->type == but_type_start) {
+ if (ui_drag_toggle_but_is_supported(but)) {
/* is it pressed? */
- bool is_set_but = ui_but_is_pushed(but);
- BLI_assert(ui_but_is_bool(but) == true);
+ bool is_set_but = ui_drag_toggle_but_is_pushed(but);
if (is_set_but != is_set) {
UI_but_execute(C, but);
if (do_check) {
@@ -1352,7 +1354,7 @@ static void ui_drag_toggle_set(bContext *C, uiDragToggleHandle *drag_info, const
/* touch all buttons between last mouse coord and this one */
- do_draw = ui_drag_toggle_set_xy_xy(C, ar, drag_info->is_set, drag_info->but_type_start, drag_info->xy_last, xy);
+ do_draw = ui_drag_toggle_set_xy_xy(C, ar, drag_info->is_set, drag_info->xy_last, xy);
if (do_draw) {
ED_region_tag_redraw(ar);
@@ -1375,7 +1377,7 @@ static int ui_handler_region_drag_toggle(bContext *C, const wmEvent *event, void
switch (event->type) {
case LEFTMOUSE:
{
- if (event->val != KM_PRESS) {
+ if (event->val == KM_RELEASE) {
done = true;
}
break;
@@ -1412,7 +1414,7 @@ static int ui_handler_region_drag_toggle(bContext *C, const wmEvent *event, void
static bool ui_but_is_drag_toggle(const uiBut *but)
{
- return ((ui_but_is_bool(but) == true) &&
+ 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));
}
@@ -1571,6 +1573,7 @@ static void ui_selectcontext_apply(
bool b;
int i;
float f;
+ PointerRNA p;
} delta, min, max;
const bool is_array = RNA_property_array_check(prop);
@@ -1595,6 +1598,9 @@ static void ui_selectcontext_apply(
delta.b = RNA_property_boolean_get(&but->rnapoin, prop); /* not a delta infact */
}
}
+ else if (rna_type == PROP_POINTER) {
+ delta.p = RNA_property_pointer_get(&but->rnapoin, prop); /* not a delta infact */
+ }
#ifdef USE_ALLSELECT_LAYER_HACK
/* make up for not having 'handle_layer_buttons' */
@@ -1667,6 +1673,10 @@ static void ui_selectcontext_apply(
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);
}
@@ -1680,11 +1690,11 @@ static bool ui_but_contains_point_px_icon(uiBut *but, ARegion *ar, const wmEvent
{
rcti rect;
int x = event->x, y = event->y;
-
+
ui_window_to_block(ar, but->block, &x, &y);
-
+
BLI_rcti_rctf_copy(&rect, &but->rect);
-
+
if (but->imb || but->type == UI_BTYPE_COLOR) {
/* use button size itself */
}
@@ -1696,7 +1706,7 @@ static bool ui_but_contains_point_px_icon(uiBut *but, ARegion *ar, const wmEvent
rect.xmin += delta / 2;
rect.xmax -= delta / 2;
}
-
+
return BLI_rcti_isect_pt(&rect, x, y);
}
@@ -1718,7 +1728,7 @@ static bool ui_but_drag_init(
button_activate_state(C, but, BUTTON_STATE_EXIT);
data->cancel = true;
#ifdef USE_DRAG_TOGGLE
- if (ui_but_is_bool(but)) {
+ if (ui_drag_toggle_but_is_supported(but)) {
uiDragToggleHandle *drag_info = MEM_callocN(sizeof(*drag_info), __func__);
ARegion *ar_prev;
@@ -1726,10 +1736,9 @@ static bool ui_but_drag_init(
* typically 'button_activate_exit()' handles this */
ui_apply_but_autokey(C, but);
- drag_info->is_set = ui_but_is_pushed(but);
+ drag_info->is_set = ui_drag_toggle_but_is_pushed(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);
- drag_info->but_type_start = but->type;
copy_v2_v2_int(drag_info->xy_init, &event->x);
copy_v2_v2_int(drag_info->xy_last, &event->x);
@@ -1753,23 +1762,20 @@ static bool ui_but_drag_init(
/* TODO support more button pointer types */
if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
- RNA_property_float_get_array(&but->rnapoin, but->rnaprop, drag_info->color);
+ 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) {
- RNA_property_float_get_array(&but->rnapoin, but->rnaprop, drag_info->color);
+ ui_but_v3_get(but, drag_info->color);
drag_info->gamma_corrected = false;
valid = true;
}
- else if (but->pointype == UI_BUT_POIN_FLOAT) {
+ 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;
}
- else if (but->pointype == UI_BUT_POIN_CHAR) {
- rgb_uchar_to_float(drag_info->color, (unsigned char *)but->poin);
- valid = true;
- }
if (valid) {
WM_event_start_drag(C, ICON_COLOR, WM_DRAG_COLOR, drag_info, 0.0, WM_DRAG_FREE_DATA);
@@ -1809,7 +1815,7 @@ static bool ui_but_drag_init(
}
return true;
}
-
+
return false;
}
@@ -2117,13 +2123,13 @@ static void ui_but_drop(bContext *C, const wmEvent *event, uiBut *but, uiHandleB
{
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 = (ID *)wmd->poin;
-
+
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
ui_textedit_string_set(but, data, id->name + 2);
@@ -2137,7 +2143,7 @@ static void ui_but_drop(bContext *C, const wmEvent *event, uiBut *but, uiHandleB
}
}
}
-
+
}
/* ******************* copy and paste ******************** */
@@ -2175,7 +2181,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
/* numeric value */
if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER)) {
-
+
if (but->poin == NULL && but->rnapoin.data == NULL) {
/* pass */
}
@@ -2278,7 +2284,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
/* RGB triple */
else if (but->type == UI_BTYPE_COLOR) {
float rgba[4];
-
+
if (but->poin == NULL && but->rnapoin.data == NULL) {
/* pass */
}
@@ -2289,7 +2295,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
rgba[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3);
else
rgba[3] = 1.0f;
-
+
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)
@@ -2297,7 +2303,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
BLI_snprintf(buf_copy, sizeof(buf_copy), "[%f, %f, %f, %f]", rgba[0], rgba[1], rgba[2], rgba[3]);
WM_clipboard_text_set(buf_copy, 0);
-
+
}
else {
if (sscanf(buf_paste, "[%f, %f, %f, %f]", &rgba[0], &rgba[1], &rgba[2], &rgba[3]) == 4) {
@@ -2439,7 +2445,7 @@ static int ui_text_position_from_hidden(uiBut *but, int pos)
for (i = 0, strpos = butstr; i < pos; i++)
strpos = BLI_str_find_next_char_utf8(strpos, NULL);
-
+
return (strpos - butstr);
}
@@ -2537,7 +2543,7 @@ static bool ui_textedit_delete_selection(uiBut *but, uiHandleButtonData *data)
memmove(str + but->selsta, str + but->selend, (len - but->selend) + 1);
changed = true;
}
-
+
but->pos = but->selend = but->selsta;
return changed;
}
@@ -2568,7 +2574,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
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)) {
@@ -2578,13 +2584,13 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
}
/* 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 */
@@ -2606,7 +2612,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
/* 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);
@@ -2639,10 +2645,10 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
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;
@@ -2878,7 +2884,7 @@ static bool ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, const in
char *pbuf;
bool changed = false;
int buf_len;
-
+
/* paste */
if (mode == UI_TEXTEDIT_PASTE) {
/* extract the first line from the clipboard */
@@ -2905,7 +2911,7 @@ static bool ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, const in
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) {
@@ -3061,7 +3067,7 @@ static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data)
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) &&
@@ -3080,11 +3086,11 @@ static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data)
MEM_SAFE_FREE(but->search_arg);
}
}
-
+
but->editstr = NULL;
but->pos = -1;
}
-
+
WM_cursor_modal_restore(win);
#ifdef WITH_INPUT_IME
@@ -3181,7 +3187,7 @@ static void ui_do_but_textedit(
ui_searchbox_event(C, data->searchbox, but, event);
#endif
}
-
+
break;
case RIGHTMOUSE:
case ESCKEY:
@@ -3201,7 +3207,7 @@ static void ui_do_but_textedit(
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);
@@ -3231,7 +3237,7 @@ static void ui_do_but_textedit(
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);
@@ -3328,7 +3334,7 @@ static void ui_do_but_textedit(
event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
retval = WM_UI_HANDLER_BREAK;
break;
-
+
case AKEY:
/* Ctrl + A: Select all */
@@ -3406,7 +3412,7 @@ static void ui_do_but_textedit(
}
retval = WM_UI_HANDLER_BREAK;
-
+
}
/* textbutton with this flag: do live update (e.g. for search buttons) */
if (but->flag & UI_BUT_TEXTEDIT_UPDATE) {
@@ -3442,7 +3448,7 @@ static void ui_do_but_textedit(
ui_but_update_edited(but);
}
but->changed = true;
-
+
if (data->searchbox)
ui_searchbox_update(C, data->searchbox, but, true); /* true = reset */
}
@@ -3639,7 +3645,7 @@ int ui_but_menu_direction(uiBut *but)
if (data && data->menu)
return data->menu->direction;
-
+
return 0;
}
@@ -3669,16 +3675,56 @@ static uiBut *ui_but_list_row_text_activate(
/* ***************** events for different button types *************** */
+#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)
{
+#ifdef USE_DRAG_TOGGLE
+ {
+ 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 && but->block->handle) {
+ 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;
@@ -3691,7 +3737,7 @@ static int ui_do_but_BUT(
}
}
else if (data->state == BUTTON_STATE_WAIT_RELEASE) {
- if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
+ if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
if (!(but->flag & UI_SELECT))
data->cancel = true;
button_activate_state(C, but, BUTTON_STATE_EXIT);
@@ -3731,7 +3777,7 @@ static int ui_do_but_HOTKEYEVT(
return WM_UI_HANDLER_BREAK;
}
}
-
+
/* always set */
but->modifier_key = 0;
if (event->shift) but->modifier_key |= KM_SHIFT;
@@ -3741,15 +3787,15 @@ static int ui_do_but_HOTKEYEVT(
ui_but_update(but);
ED_region_tag_redraw(data->region);
-
+
if (event->val == KM_PRESS) {
if (ISHOTKEY(event->type)) {
-
+
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;
}
@@ -3760,10 +3806,10 @@ static int ui_do_but_HOTKEYEVT(
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
}
-
+
}
}
-
+
return WM_UI_HANDLER_CONTINUE;
}
@@ -3929,25 +3975,14 @@ static int ui_do_but_TOG(
uiHandleButtonData *data, const wmEvent *event)
{
#ifdef USE_DRAG_TOGGLE
- 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;
- return WM_UI_HANDLER_BREAK;
+ {
+ int retval;
+ if (ui_do_but_ANY_drag_toggle(C, but, data, event, &retval)) {
+ return retval;
}
}
- 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;
- return ui_do_but_EXIT(C, but, data, event);
- }
#endif
+
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
#if 0 /* UNUSED */
@@ -3997,13 +4032,13 @@ 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);
@@ -4032,25 +4067,25 @@ static int ui_do_but_EXIT(
}
}
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
+
+ /* 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
+
+ /* 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;
}
@@ -4064,7 +4099,7 @@ static float ui_numedit_apply_snapf(
}
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));
@@ -4112,7 +4147,7 @@ static float ui_numedit_apply_snapf(
else {
BLI_assert(0);
}
-
+
if (fac != 1.0f)
tempf *= fac;
}
@@ -4257,7 +4292,7 @@ static bool ui_numedit_but_NUM(
}
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);
@@ -4270,7 +4305,7 @@ static bool ui_numedit_but_NUM(
CLAMP(temp, softmin, softmax);
lvalue = (int)data->value;
-
+
if (temp != lvalue) {
data->dragchange = true;
data->value = (double)temp;
@@ -4360,20 +4395,24 @@ static int ui_do_but_NUM(
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)
retval = WM_UI_HANDLER_BREAK; /* allow accumulating values, otherwise scrolling gets preference */
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) {
@@ -4400,7 +4439,7 @@ static int ui_do_but_NUM(
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) {
@@ -4410,7 +4449,7 @@ static int ui_do_but_NUM(
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
}
- else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
+ else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
if (data->dragchange) {
#ifdef USE_DRAG_MULTINUM
/* if we started multibutton but didnt drag, then edit */
@@ -4461,7 +4500,7 @@ static int ui_do_but_NUM(
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 */
@@ -4524,7 +4563,7 @@ static int ui_do_but_NUM(
retval = WM_UI_HANDLER_BREAK;
}
-
+
data->draglastx = mx;
data->draglasty = my;
@@ -4718,7 +4757,7 @@ static int ui_do_but_SLI(
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
}
- else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
+ else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
if (data->dragchange) {
#ifdef USE_DRAG_MULTINUM
/* if we started multibutton but didnt drag, then edit */
@@ -4773,13 +4812,13 @@ static int ui_do_but_SLI(
/* 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;
@@ -4792,13 +4831,13 @@ static int ui_do_but_SLI(
{
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
@@ -4807,13 +4846,13 @@ static int ui_do_but_SLI(
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;
}
@@ -4826,7 +4865,7 @@ static int ui_do_but_SLI(
data->draglastx = mx;
data->draglasty = my;
-
+
return retval;
}
@@ -4837,7 +4876,7 @@ static int ui_do_but_SCROLL(
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);
@@ -4871,7 +4910,7 @@ static int ui_do_but_SCROLL(
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
}
- else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
+ else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
else if (event->type == MOUSEMOVE) {
@@ -4883,7 +4922,7 @@ static int ui_do_but_SCROLL(
retval = WM_UI_HANDLER_BREAK;
}
-
+
return retval;
}
@@ -4923,7 +4962,7 @@ static int ui_do_but_GRIP(
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
}
- else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
+ else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
else if (event->type == MOUSEMOVE) {
@@ -4966,9 +5005,9 @@ 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)) {
@@ -5025,19 +5064,19 @@ static int ui_do_but_BLOCK(
}
}
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;
@@ -5056,7 +5095,7 @@ static bool ui_numedit_but_UNITVEC(
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 */
@@ -5066,21 +5105,21 @@ static bool ui_numedit_but_UNITVEC(
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);
@@ -5092,12 +5131,12 @@ static bool ui_numedit_but_UNITVEC(
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;
@@ -5179,12 +5218,12 @@ static int ui_do_but_COLOR(
rgb_to_hsv_compat_v(col, hsv);
if (event->type == WHEELDOWNMOUSE)
- hsv[2] = CLAMPIS(hsv[2] - 0.05f, 0.0f, 1.0f);
+ hsv[2] = clamp_f(hsv[2] - 0.05f, 0.0f, 1.0f);
else if (event->type == WHEELUPMOUSE)
- hsv[2] = CLAMPIS(hsv[2] + 0.05f, 0.0f, 1.0f);
+ hsv[2] = clamp_f(hsv[2] + 0.05f, 0.0f, 1.0f);
else {
float fac = 0.005 * (event->y - event->prevy);
- hsv[2] = CLAMPIS(hsv[2] + fac, 0.0f, 1.0f);
+ hsv[2] = clamp_f(hsv[2] + fac, 0.0f, 1.0f);
}
hsv_to_rgb_v(hsv, data->vec);
@@ -5297,7 +5336,7 @@ static int ui_do_but_UNITVEC(
/* 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;
}
}
@@ -5309,13 +5348,13 @@ static int ui_do_but_UNITVEC(
ui_numedit_apply(C, block, but, data);
}
}
- else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
+ 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;
}
@@ -5386,30 +5425,30 @@ static bool ui_numedit_but_HSVCUBE(
ui_block_cm_to_display_space_v3(but->block, 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);
if (use_display_colorspace)
ui_block_cm_to_display_space_v3(but->block, 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);
@@ -5526,10 +5565,10 @@ static void ui_ndofedit_but_HSVCUBE(
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:
@@ -5579,19 +5618,19 @@ static int ui_do_but_HSVCUBE(
/* 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;
}
#ifdef WITH_INPUT_NDOF
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);
-
+
button_activate_state(C, but, BUTTON_STATE_EXIT);
ui_apply_but(C, but->block, but, data, true);
-
+
return WM_UI_HANDLER_BREAK;
}
#endif /* WITH_INPUT_NDOF */
@@ -5599,9 +5638,9 @@ static int ui_do_but_HSVCUBE(
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];
@@ -5617,10 +5656,10 @@ static int ui_do_but_HSVCUBE(
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;
}
@@ -5643,10 +5682,10 @@ static int ui_do_but_HSVCUBE(
ui_numedit_apply(C, block, but, data);
}
}
- else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
+ else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
-
+
return WM_UI_HANDLER_BREAK;
}
@@ -5667,7 +5706,7 @@ static bool ui_numedit_but_HSVCIRCLE(
bool use_display_colorspace = ui_but_is_colorpicker_display_space(but);
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 */
@@ -5707,7 +5746,7 @@ static bool ui_numedit_but_HSVCIRCLE(
/* only apply the delta motion, not absolute */
if (shift) {
float xpos, ypos, hsvo[3], rgbo[3];
-
+
/* calculate original hsv again */
copy_v3_v3(hsvo, hsv);
copy_v3_v3(rgbo, data->origvec);
@@ -5721,9 +5760,9 @@ static bool ui_numedit_but_HSVCIRCLE(
mx_fl = xpos - (data->dragstartx - mx_fl);
my_fl = ypos - (data->dragstarty - my_fl);
-
+
}
-
+
ui_hsvcircle_vals_from_pos(hsv, hsv + 1, &rect, mx_fl, my_fl);
if ((but->flag & UI_BUT_COLOR_CUBIC) && (U.color_picker_type == USER_CP_CIRCLE_HSV))
@@ -5743,10 +5782,10 @@ static bool ui_numedit_but_HSVCIRCLE(
ui_block_cm_to_scene_linear_v3(but->block, rgb);
ui_but_v3_set(but, rgb);
-
+
data->draglastx = mx;
data->draglasty = my;
-
+
return changed;
}
@@ -5762,28 +5801,28 @@ static void ui_ndofedit_but_HSVCIRCLE(
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);
if (use_display_colorspace)
ui_block_cm_to_display_space_v3(but->block, 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);
@@ -5811,14 +5850,14 @@ static void ui_ndofedit_but_HSVCIRCLE(
hsv_clamp_v(hsv, FLT_MAX);
ui_color_picker_to_rgb_v(hsv, data->vec);
-
+
if ((but->flag & UI_BUT_VEC_SIZE_LOCK) && (data->vec[0] || data->vec[1] || data->vec[2])) {
normalize_v3_length(data->vec, but->a2);
}
if (use_display_colorspace)
ui_block_cm_to_scene_linear_v3(but->block, data->vec);
-
+
ui_but_v3_set(but, data->vec);
}
#endif /* WITH_INPUT_NDOF */
@@ -5833,7 +5872,7 @@ static int ui_do_but_HSVCIRCLE(
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);
@@ -5842,52 +5881,52 @@ static int ui_do_but_HSVCIRCLE(
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;
-
+
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);
-
+
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;
@@ -5903,12 +5942,12 @@ static int ui_do_but_HSVCIRCLE(
}
/* XXX hardcoded keymap check.... */
else if (event->type == WHEELDOWNMOUSE) {
- hsv[2] = CLAMPIS(hsv[2] - 0.05f, 0.0f, 1.0f);
+ 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] = CLAMPIS(hsv[2] + 0.05f, 0.0f, 1.0f);
+ 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);
}
@@ -5921,12 +5960,12 @@ static int ui_do_but_HSVCIRCLE(
}
}
}
- else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
+ 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;
}
@@ -5945,10 +5984,10 @@ static bool ui_numedit_but_COLORBAND(uiBut *but, uiHandleButtonData *data, int m
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 */
-
+
data->draglastx = mx;
changed = true;
@@ -5995,7 +6034,7 @@ static int ui_do_but_COLORBAND(
mindist = xco;
}
}
-
+
data->dragcbd = coba->data + coba->cur;
data->dragfstart = data->dragcbd->pos;
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
@@ -6011,7 +6050,7 @@ static int ui_do_but_COLORBAND(
ui_numedit_apply(C, block, but, data);
}
}
- else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
+ else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
else if (ELEM(event->type, ESCKEY, RIGHTMOUSE)) {
@@ -6049,10 +6088,10 @@ static bool ui_numedit_but_CURVE(
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];
@@ -6091,7 +6130,7 @@ static bool ui_numedit_but_CURVE(
}
curvemapping_changed(cumap, false);
-
+
if (moved_point) {
data->draglastx = evtx;
data->draglasty = evty;
@@ -6115,7 +6154,7 @@ static bool ui_numedit_but_CURVE(
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)
@@ -6132,7 +6171,7 @@ static bool ui_numedit_but_CURVE(
cumap->curr.ymin -= fy;
cumap->curr.xmax -= fx;
cumap->curr.ymax -= fy;
-
+
data->draglastx = evtx;
data->draglasty = evty;
@@ -6154,7 +6193,7 @@ static int ui_do_but_CURVE(
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;
@@ -6167,7 +6206,7 @@ static int ui_do_but_CURVE(
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;
@@ -6189,7 +6228,7 @@ static int ui_do_but_CURVE(
int i;
float f_xy[2], f_xy_prev[2];
- /* if the click didn't select anything, check if it's clicked on the
+ /* 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;
@@ -6210,10 +6249,10 @@ static int ui_do_but_CURVE(
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]) {
@@ -6244,7 +6283,7 @@ static int ui_do_but_CURVE(
}
data->dragsel = sel;
-
+
data->dragstartx = event->x;
data->dragstarty = event->y;
data->draglastx = event->x;
@@ -6257,12 +6296,12 @@ static int ui_do_but_CURVE(
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_PRESS) {
+ else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
if (data->dragsel != -1) {
CurveMapping *cumap = (CurveMapping *)but->poin;
CurveMap *cuma = cumap->cm + cumap->cur;
@@ -6318,11 +6357,11 @@ static int ui_do_but_HISTOGRAM(
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;
@@ -6330,18 +6369,18 @@ static int ui_do_but_HISTOGRAM(
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;
}
@@ -6360,12 +6399,12 @@ static int ui_do_but_HISTOGRAM(
ui_numedit_apply(C, block, but, data);
}
}
- else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
+ 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;
}
@@ -6435,7 +6474,7 @@ static int ui_do_but_WAVEFORM(
ui_numedit_apply(C, block, but, data);
}
}
- else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
+ else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
return WM_UI_HANDLER_BREAK;
@@ -6519,7 +6558,7 @@ static int ui_do_but_TRACKPREVIEW(
ui_numedit_apply(C, block, but, data);
}
}
- else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
+ else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
return WM_UI_HANDLER_BREAK;
@@ -6528,592 +6567,6 @@ static int ui_do_but_TRACKPREVIEW(
return WM_UI_HANDLER_CONTINUE;
}
-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);
- }
- }
-}
-
-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, true, &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, -50, 26);
-
- return block;
-}
-
-#ifdef USE_KEYMAP_ADD_HACK
-static int g_kmi_id_hack;
-#endif
-
-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;
-
- /* 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);
-
- /* 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);
-
- 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);
-
- 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, -50, 26);
-
-#ifdef USE_KEYMAP_ADD_HACK
- g_kmi_id_hack = kmi_id;
-#endif
- return block;
-}
-
-static void menu_add_shortcut_cancel(struct bContext *C, void *arg1)
-{
- uiBut *but = (uiBut *)arg1;
- wmKeyMap *km;
- wmKeyMapItem *kmi;
-#ifndef USE_KEYMAP_ADD_HACK
- IDProperty *prop;
-#endif
- int kmi_id;
-
-#ifdef USE_KEYMAP_ADD_HACK
- 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);
-#endif
-
- 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);
-}
-
-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, true, &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);
-}
-
-/**
- * menu to chow when right clicking on the panel header
- */
-void ui_panel_menu(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);
-}
-
-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);
-}
-
-static bool ui_but_menu(bContext *C, uiBut *but)
-{
- uiPopupMenu *pup;
- uiLayout *layout;
- MenuType *mt = WM_menutype_find("WM_MT_button_context", true);
- bool is_array, is_array_component;
- uiStringInfo label = {BUT_GET_LABEL, NULL};
- wmOperatorType *ot;
- PointerRNA op_ptr;
-
-/* if ((but->rnapoin.data && but->rnaprop) == 0 && but->optype == NULL)*/
-/* return 0;*/
-
- /* having this menu for some buttons makes no sense */
- if (but->type == UI_BTYPE_IMAGE) {
- return false;
- }
-
- /* 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);
-
- 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);*/ /* XXX does not work as expected, not strictly needed */
- bool is_set = RNA_property_is_set(ptr, prop);
-
- const int override_status = RNA_property_static_override_status(ptr, prop, -1);
- const bool is_overridable = (override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE) != 0;
-
- /* 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 */
- is_array = RNA_property_array_length(&but->rnapoin, but->rnaprop) != 0;
- is_array_component = (is_array && but->rnaindex != -1);
-
- /* 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");
- }
- }
- else if (but->flag & (UI_BUT_ANIMATED_KEY | UI_BUT_ANIMATED)) {
- /* pass */
- }
- else if (is_anim) {
- uiItemS(layout);
-
- if (is_array_component) {
- uiItemMenuEnumO(layout, C, "ANIM_OT_driver_button_add", "mapping_type",
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Drivers"),
- ICON_DRIVER);
- }
- else {
- uiItemMenuEnumO(layout, C, "ANIM_OT_driver_button_add", "mapping_type",
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Driver"),
- ICON_DRIVER);
- }
-
- if (ANIM_driver_can_paste()) {
- uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"),
- ICON_NONE, "ANIM_OT_paste_driver_button");
- }
- }
-
- /* 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) {
- /* 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);
-#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_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);
- }
- }
-
- /* 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, false, &km);
-
- /* We do have a shortcut, but only keyboard ones are editbale 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_NONE,
- 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 'add' 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, "Add 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);
- }
-
- /* Show header tools for header buttons. */
- if (ui_block_is_menu(but->block) == false) {
- ARegion *ar = CTX_wm_region(C);
- if (ar && (ar->regiontype == RGN_TYPE_HEADER)) {
- uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL);
- 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");
-
- 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));
-#endif
- }
- }
-
- if (but->optype) {
- uiItemO(layout, NULL,
- ICON_NONE, "UI_OT_copy_python_command_button");
- }
-
- /* perhaps we should move this into (G.debug & G_DEBUG) - campbell */
- if (ui_block_is_menu(but->block) == false) {
- uiItemFullO(layout, "UI_OT_editsource", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL);
- }
- uiItemFullO(layout, "UI_OT_edittranslation_init", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL);
-
- mt = WM_menutype_find("WM_MT_button_context", true);
- if (mt) {
- UI_menutype_draw(C, mt, uiLayoutColumn(layout, false));
- }
-
- UI_popup_menu_end(C, pup);
-
- return true;
-}
-
static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *event)
{
uiHandleButtonData *data;
@@ -7157,7 +6610,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
(event->val == KM_PRESS))
{
/* RMB has two options now */
- if (ui_but_menu(C, but)) {
+ if (ui_popup_context_menu_for_button(C, but)) {
return WM_UI_HANDLER_BREAK;
}
}
@@ -7269,6 +6722,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
/* quiet warnings for unhandled types */
case UI_BTYPE_SEPR:
case UI_BTYPE_SEPR_LINE:
+ case UI_BTYPE_SEPR_SPACER:
case UI_BTYPE_EXTRA:
break;
}
@@ -7474,7 +6928,7 @@ bool UI_but_active_drop_name(bContext *C)
if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU))
return 1;
}
-
+
return 0;
}
@@ -7516,11 +6970,11 @@ static bool ui_region_contains_point_px(ARegion *ar, int x, int y)
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
+ /* 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
@@ -7528,7 +6982,7 @@ static bool ui_region_contains_point_px(ARegion *ar, int x, int y)
if (ar->v2d.mask.xmin != ar->v2d.mask.xmax) {
View2D *v2d = &ar->v2d;
int mx, my;
-
+
/* convert window coordinates to region coordinates */
mx = x;
my = y;
@@ -7539,7 +6993,7 @@ static bool ui_region_contains_point_px(ARegion *ar, int x, int y)
return false;
}
}
-
+
return true;
}
@@ -7563,7 +7017,7 @@ static bool ui_but_contains_point_px(ARegion *ar, uiBut *but, int x, int y)
else if (!ui_but_contains_pt(but, mx, my)) {
return false;
}
-
+
return true;
}
@@ -7751,10 +7205,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
/* highlight has timers for tooltips and auto open */
if (state == BUTTON_STATE_HIGHLIGHT) {
- /* for list-items (that are not drawn with regular emboss), don't change selection based on hovering */
- if (((but->flag & UI_BUT_LIST_ITEM) == 0) && (but->dragflag & UI_EMBOSS_NONE)) {
- but->flag &= ~UI_SELECT;
- }
+ but->flag &= ~UI_SELECT;
button_tooltip_timer_reset(C, but);
@@ -7788,7 +7239,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
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);
@@ -7796,7 +7247,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
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))
@@ -7873,7 +7324,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
}
}
}
-
+
/* wait for mousemove to enable drag */
if (state == BUTTON_STATE_WAIT_DRAG) {
but->flag &= ~UI_SELECT;
@@ -7917,7 +7368,7 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
data->interactive = true;
}
}
-
+
data->state = BUTTON_STATE_INIT;
/* activate button */
@@ -7935,14 +7386,14 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
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);
@@ -7951,7 +7402,7 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
ARegion *subar = data->menu->region;
uiBlock *subblock = subar->uiblocks.first;
uiBut *subbut;
-
+
if (subblock) {
subbut = ui_but_first(subblock);
@@ -8258,8 +7709,12 @@ void UI_context_update_anim_flag(const bContext *C)
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;
}
@@ -8292,7 +7747,7 @@ static uiBut *ui_but_find_open_event(ARegion *ar, const wmEvent *event)
{
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)
@@ -8332,15 +7787,15 @@ void ui_but_activate_event(bContext *C, ARegion *ar, uiBut *but)
{
wmWindow *win = CTX_wm_window(C);
wmEvent event;
-
+
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;
-
+
ui_do_button(C, but->block, but, &event);
}
@@ -8438,7 +7893,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
ar = data->region;
retval = WM_UI_HANDLER_CONTINUE;
-
+
if (data->state == BUTTON_STATE_HIGHLIGHT) {
switch (event->type) {
case WINDEACTIVATE:
@@ -8446,6 +7901,28 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
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;
+ block->handle->menuretval = UI_RETURN_OK;
+ }
+ 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);
@@ -8594,7 +8071,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
}
bt = ui_but_find_mouse_over(ar, event);
-
+
if (bt && bt->active != data) {
if (but->type != UI_BTYPE_COLOR) { /* exception */
data->cancel = true;
@@ -8823,7 +8300,7 @@ static void ui_handle_button_return_submenu(bContext *C, const wmEvent *event, u
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)
@@ -8934,7 +8411,7 @@ static bool ui_mouse_motion_towards_check(
p2[0] = rect_px.xmax + margin;
p2[1] = rect_px.ymin - margin;
-
+
p3[0] = rect_px.xmax + margin;
p3[1] = rect_px.ymax + margin;
@@ -8992,7 +8469,7 @@ 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 (block->flag & UI_BLOCK_CLIPTOP)
if (my > block->rect.ymax - UI_MENU_SCROLL_MOUSE)
return 't';
if (block->flag & UI_BLOCK_CLIPBOTTOM)
@@ -9050,6 +8527,9 @@ static int ui_menu_scroll(ARegion *ar, uiBlock *block, int my, uiBut *to_bt)
dy = block->rect.ymin - ymin + UI_MENU_SCROLL_PAD;
}
+ /* remember scroll offset for refreshes */
+ block->handle->scrolloffset += dy;
+
/* apply scroll offset */
for (bt = block->buttons.first; bt; bt = bt->next) {
bt->rect.ymin += dy;
@@ -9058,12 +8538,12 @@ static int ui_menu_scroll(ARegion *ar, uiBlock *block, int my, uiBut *to_bt)
/* set flags again */
ui_popup_block_scrolltest(block);
-
+
ED_region_tag_redraw(ar);
-
+
return 1;
}
-
+
return 0;
}
@@ -9202,7 +8682,7 @@ static int ui_handle_menu_event(
add_v2_v2v2_int(menu->popup_create_vars.event_xy, menu->popup_create_vars.event_xy, mdiff);
- ui_popup_translate(C, ar, mdiff);
+ ui_popup_translate(ar, mdiff);
}
return retval;
@@ -9228,14 +8708,14 @@ static int ui_handle_menu_event(
if (block->flag & UI_BLOCK_MOVEMOUSE_QUIT) {
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 */
@@ -9275,7 +8755,7 @@ static int ui_handle_menu_event(
retval = WM_UI_HANDLER_BREAK;
break;
-
+
case UPARROWKEY:
case DOWNARROWKEY:
case WHEELUPMOUSE:
@@ -9288,11 +8768,11 @@ static int ui_handle_menu_event(
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) ==
@@ -9363,10 +8843,10 @@ static int ui_handle_menu_event(
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))
@@ -9466,7 +8946,7 @@ static int ui_handle_menu_event(
}
}
}
-
+
/* 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
@@ -9546,7 +9026,7 @@ static int ui_handle_menu_event(
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
@@ -9586,6 +9066,20 @@ static int ui_handle_menu_event(
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;
+ }
+ }
+#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 */
@@ -10133,7 +9627,7 @@ static int ui_region_handler(bContext *C, const wmEvent *event, void *UNUSED(use
/* 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);
@@ -10149,7 +9643,7 @@ static void ui_region_handler_remove(bContext *C, void *UNUSED(userdata))
if (ar == NULL) return;
UI_blocklist_free(C, &ar->uiblocks);
-
+
sc = CTX_wm_screen(C);
if (sc == NULL) return;
@@ -10166,6 +9660,7 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE
{
ARegion *ar;
uiBut *but;
+ int retval = WM_UI_HANDLER_CONTINUE;
ar = CTX_wm_menu(C);
if (!ar)
@@ -10209,29 +9704,32 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE
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) {
- int retval;
-
/* handle events for menus and their buttons recursively,
* this will handle events from the top to the bottom menu */
- if (data->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)
+ if (data->menu && data->menu->menuretval) {
ui_handle_button_return_submenu(C, event, but);
- else
- ui_handle_button_event(C, event, but);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else {
+ retval = ui_handle_button_event(C, event, but);
+ }
}
}
else {
/* handle events for the activated button */
- ui_handle_button_event(C, event, but);
+ retval = ui_handle_button_event(C, event, but);
}
}
@@ -10242,6 +9740,14 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE
/* 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;
}
@@ -10285,7 +9791,7 @@ static int ui_popup_handler(bContext *C, const wmEvent *event, void *userdata)
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);
@@ -10395,7 +9901,7 @@ bool UI_textbutton_activate_rna(
{
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) {
@@ -10409,7 +9915,7 @@ bool UI_textbutton_activate_rna(
if (but)
break;
}
-
+
if (but) {
UI_but_active_only(C, ar, block, but);
return true;
@@ -10424,7 +9930,7 @@ bool UI_textbutton_activate_but(const bContext *C, uiBut *actbut)
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)
@@ -10433,7 +9939,7 @@ bool UI_textbutton_activate_but(const bContext *C, uiBut *actbut)
if (but)
break;
}
-
+
if (but) {
UI_but_active_only(C, ar, block, but);
return true;
@@ -10448,18 +9954,3 @@ void ui_but_clipboard_free(void)
{
curvemapping_free_data(&but_copypaste_curve);
}
-
-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_name", false);
- }
- if (but->optype == ot) {
- return true;
- }
- }
- return false;
-}
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 9f5c2005878..083f94a41b2 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -37,6 +37,7 @@
#include "GPU_matrix.h"
#include "GPU_batch.h"
#include "GPU_immediate.h"
+#include "GPU_state.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -77,6 +78,9 @@
#include "UI_interface.h"
#include "UI_interface_icons.h"
+#include "WM_api.h"
+#include "WM_types.h"
+
#include "interface_intern.h"
#ifndef WITH_HEADLESS
@@ -133,7 +137,7 @@ typedef struct IconTexture {
} IconTexture;
/* ******************* STATIC LOCAL VARS ******************* */
-/* static here to cache results of icon directory scan, so it's not
+/* static here to cache results of icon directory scan, so it's not
* scanning the filesystem each time the menu is drawn */
static struct ListBase iconfilelist = {NULL, NULL};
static IconTexture icongltex = {0, 0, 0, 0.0f, 0.0f};
@@ -170,9 +174,9 @@ static DrawInfo *def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs,
/* icon buffers can get initialized runtime now, via datatoc */
if (bbuf) {
int y, imgsize;
-
+
iimg->rect = MEM_mallocN(size * size * sizeof(unsigned int), "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));
@@ -191,7 +195,7 @@ static DrawInfo *def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs,
new_icon->drawinfo = di;
BKE_icon_set(icon_id, new_icon);
-
+
return di;
}
@@ -255,10 +259,10 @@ static void vicon_keytype_draw_wrapper(int x, int y, int w, int h, float alpha,
* (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
@@ -353,7 +357,7 @@ static void vicon_colorset_draw(int index, int x, int y, int w, int h, float UNU
{ \
vicon_colorset_draw(index, x, y, w, h, alpha); \
}
-
+
DEF_VICON_COLORSET_DRAW_NTH(01, 0)
DEF_VICON_COLORSET_DRAW_NTH(02, 1)
DEF_VICON_COLORSET_DRAW_NTH(03, 2)
@@ -437,63 +441,20 @@ static void icon_verify_datatoc(IconImage *iimg)
/* 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);
-
+
iimg->rect = bbuf->rect;
bbuf->rect = NULL;
IMB_freeImBuf(bbuf);
}
}
-static void init_matcap_icons(void)
-{
- /* dynamic allocation now, tucking datatoc pointers in DrawInfo */
-#define INIT_MATCAP_ICON(icon_id, name) \
- { \
- unsigned char *rect = (unsigned char *)datatoc_ ##name## _jpg; \
- int size = datatoc_ ##name## _jpg_size; \
- DrawInfo *di; \
- \
- di = def_internal_icon(NULL, icon_id, 0, 0, 96, ICON_TYPE_BUFFER); \
- di->data.buffer.image->datatoc_rect = rect; \
- di->data.buffer.image->datatoc_size = size; \
- } (void)0
-
- INIT_MATCAP_ICON(ICON_MATCAP_01, mc01);
- INIT_MATCAP_ICON(ICON_MATCAP_02, mc02);
- INIT_MATCAP_ICON(ICON_MATCAP_03, mc03);
- INIT_MATCAP_ICON(ICON_MATCAP_04, mc04);
- INIT_MATCAP_ICON(ICON_MATCAP_05, mc05);
- INIT_MATCAP_ICON(ICON_MATCAP_06, mc06);
- INIT_MATCAP_ICON(ICON_MATCAP_07, mc07);
- INIT_MATCAP_ICON(ICON_MATCAP_08, mc08);
- INIT_MATCAP_ICON(ICON_MATCAP_09, mc09);
- INIT_MATCAP_ICON(ICON_MATCAP_10, mc10);
- INIT_MATCAP_ICON(ICON_MATCAP_11, mc11);
- INIT_MATCAP_ICON(ICON_MATCAP_12, mc12);
- INIT_MATCAP_ICON(ICON_MATCAP_13, mc13);
- INIT_MATCAP_ICON(ICON_MATCAP_14, mc14);
- INIT_MATCAP_ICON(ICON_MATCAP_15, mc15);
- INIT_MATCAP_ICON(ICON_MATCAP_16, mc16);
- INIT_MATCAP_ICON(ICON_MATCAP_17, mc17);
- INIT_MATCAP_ICON(ICON_MATCAP_18, mc18);
- INIT_MATCAP_ICON(ICON_MATCAP_19, mc19);
- INIT_MATCAP_ICON(ICON_MATCAP_20, mc20);
- INIT_MATCAP_ICON(ICON_MATCAP_21, mc21);
- INIT_MATCAP_ICON(ICON_MATCAP_22, mc22);
- INIT_MATCAP_ICON(ICON_MATCAP_23, mc23);
- INIT_MATCAP_ICON(ICON_MATCAP_24, mc24);
-
-#undef INIT_MATCAP_ICON
-
-}
-
static void init_internal_icons(void)
{
// bTheme *btheme = UI_GetTheme();
@@ -504,7 +465,7 @@ static void init_internal_icons(void)
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);
bbuf = IMB_loadiffname(iconfilestr, IB_rect, NULL); /* if the image is missing bbuf will just be NULL */
@@ -530,7 +491,7 @@ static void init_internal_icons(void)
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) {
@@ -548,17 +509,17 @@ static void init_internal_icons(void)
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);
@@ -566,10 +527,10 @@ static void init_internal_icons(void)
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);
}
}
@@ -579,7 +540,7 @@ static void init_internal_icons(void)
icontype = ICON_TYPE_TEXTURE;
else
icontype = ICON_TYPE_BUFFER;
-
+
if (b32buf) {
for (y = 0; y < ICON_GRID_ROWS; y++) {
for (x = 0; x < ICON_GRID_COLS; x++) {
@@ -592,13 +553,13 @@ static void init_internal_icons(void)
}
def_internal_vicon(VICO_SMALL_TRI_RIGHT_VEC, vicon_small_tri_right_draw);
-
+
def_internal_vicon(VICO_KEYTYPE_KEYFRAME_VEC, vicon_keytype_keyframe_draw);
def_internal_vicon(VICO_KEYTYPE_BREAKDOWN_VEC, vicon_keytype_breakdown_draw);
def_internal_vicon(VICO_KEYTYPE_EXTREME_VEC, vicon_keytype_extreme_draw);
def_internal_vicon(VICO_KEYTYPE_JITTER_VEC, vicon_keytype_jitter_draw);
def_internal_vicon(VICO_KEYTYPE_MOVING_HOLD_VEC, vicon_keytype_moving_hold_draw);
-
+
def_internal_vicon(VICO_COLORSET_01_VEC, vicon_colorset_draw_01);
def_internal_vicon(VICO_COLORSET_02_VEC, vicon_colorset_draw_02);
def_internal_vicon(VICO_COLORSET_03_VEC, vicon_colorset_draw_03);
@@ -622,7 +583,7 @@ static void init_internal_icons(void)
IMB_freeImBuf(b16buf);
IMB_freeImBuf(b32buf);
-
+
}
#endif /* WITH_HEADLESS */
@@ -638,14 +599,14 @@ static void init_iconfile_list(struct ListBase *list)
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_testextensie(filename, ".png")) {
+
+ 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
@@ -666,7 +627,7 @@ static void init_iconfile_list(struct ListBase *list)
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);
@@ -676,12 +637,12 @@ static void init_iconfile_list(struct ListBase *list)
/* 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++;
}
}
@@ -694,7 +655,7 @@ static void init_iconfile_list(struct ListBase *list)
static void free_iconfile_list(struct ListBase *list)
{
IconFile *ifile = NULL, *next_ifile = NULL;
-
+
for (ifile = list->first; ifile; ifile = next_ifile) {
next_ifile = ifile->next;
BLI_freelinkN(list, ifile);
@@ -707,20 +668,20 @@ int UI_iconfile_get_index(const char *filename)
{
IconFile *ifile;
ListBase *list = &(iconfilelist);
-
+
for (ifile = list->first; ifile; ifile = ifile->next) {
if (BLI_path_cmp(filename, ifile->filename) == 0) {
return ifile->index;
}
}
-
+
return 0;
}
ListBase *UI_iconfile_list(void)
{
ListBase *list = &(iconfilelist);
-
+
return list;
}
@@ -777,14 +738,7 @@ static DrawInfo *icon_create_drawinfo(Icon *icon)
di->type = ICON_TYPE_GEOM;
}
else if (icon_data_type == ICON_DATA_STUDIOLIGHT) {
- const int STUDIOLIGHT_SIZE = 96;
- StudioLight *sl = icon->obj;
di->type = ICON_TYPE_BUFFER;
- IconImage *img = MEM_mallocN(sizeof(IconImage), __func__);
- img->w = STUDIOLIGHT_SIZE;
- img->h = STUDIOLIGHT_SIZE;
- img->rect = BKE_studiolight_preview(sl, STUDIOLIGHT_SIZE);
- di->data.buffer.image = img;
}
else {
BLI_assert(0);
@@ -811,13 +765,13 @@ int UI_icon_get_width(int icon_id)
DrawInfo *di = NULL;
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;
}
-
+
di = icon_ensure_drawinfo(icon);
if (di) {
return ICON_DEFAULT_WIDTH;
@@ -850,7 +804,6 @@ void UI_icons_init(int first_dyn_id)
init_iconfile_list(&iconfilelist);
init_internal_icons();
init_brush_icons();
- init_matcap_icons();
#endif
}
@@ -890,6 +843,41 @@ static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size)
static void ui_id_preview_image_render_size(
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))
+{
+ 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;
+}
+
+static void ui_studiolight_free_function(StudioLight *sl, void *data)
+{
+ wmWindowManager *wm = data;
+
+ // 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);
+ }
+}
+
void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool big)
{
Icon *icon = BKE_icon_get(icon_id);
@@ -916,6 +904,33 @@ void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool bi
}
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, NULL);
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+ }
+ }
+ break;
+ }
}
}
}
@@ -955,7 +970,7 @@ static void icon_set_image(
PreviewImage *UI_icon_to_preview(int icon_id)
{
Icon *icon = BKE_icon_get(icon_id);
-
+
if (icon) {
DrawInfo *di = (DrawInfo *)icon->drawinfo;
if (di) {
@@ -1092,10 +1107,10 @@ static void icon_draw_cache_flush_ex(void)
return;
/* We need to flush widget base first to ensure correct ordering. */
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
UI_widgetbase_draw_cache_flush();
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, icongltex.id);
@@ -1125,12 +1140,12 @@ void UI_icon_draw_cache_end(void)
if (g_icon_draw_cache.calls == 0)
return;
- glEnable(GL_BLEND);
+ GPU_blend(true);
icon_draw_cache_flush_ex();
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glDisable(GL_BLEND);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(false);
}
static void icon_draw_texture_cached(
@@ -1173,7 +1188,7 @@ static void icon_draw_texture(
}
/* We need to flush widget base first to ensure correct ordering. */
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
UI_widgetbase_draw_cache_flush();
float x1, x2, y1, y2;
@@ -1225,10 +1240,10 @@ static void icon_draw_size(
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);
@@ -1252,7 +1267,7 @@ static void icon_draw_size(
/* We need to flush widget base first to ensure correct ordering. */
UI_widgetbase_draw_cache_flush();
-#ifdef USE_TOOLBAR_HACK
+#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;
@@ -1277,14 +1292,14 @@ static void icon_draw_size(
}
glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
icon_draw_rect(x, y, w, h, aspect, w, h, ibuf->rect, alpha, rgb, desaturate);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ 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_TEXTURE) {
/* texture image use premul alpha for correct scaling */
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_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, alpha, rgb);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ 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_BUFFER) {
/* it is a builtin icon */
@@ -1294,9 +1309,9 @@ static void icon_draw_size(
#endif
if (!iimg->rect) return; /* something has gone wrong! */
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
icon_draw_rect(x, y, w, h, aspect, iimg->w, iimg->h, iimg->rect, alpha, rgb, desaturate);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ 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_PREVIEW) {
PreviewImage *pi = (icon->id_type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj;
@@ -1304,12 +1319,12 @@ static void icon_draw_size(
if (pi) {
/* no create icon on this level in code */
if (!pi->rect[size]) return; /* something has gone wrong! */
-
+
/* preview images use premul alpha ... */
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, 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);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
}
}
}
@@ -1341,10 +1356,10 @@ static void ui_id_icon_render(const bContext *C, ID *id, bool use_jobs)
{
PreviewImage *pi = BKE_previewimg_id_ensure(id);
enum eIconSizes i;
-
+
if (!pi)
return;
-
+
for (i = 0; i < NUM_ICON_SIZES; i++) {
/* check if rect needs to be created; changed
* only set by dynamic icons */
@@ -1365,16 +1380,22 @@ static int ui_id_brush_get_icon(const bContext *C, ID *id)
ui_id_icon_render(C, id, true);
}
else {
+ WorkSpace *workspace = CTX_wm_workspace(C);
Object *ob = CTX_data_active_object(C);
- SpaceImage *sima;
const EnumPropertyItem *items = NULL;
int tool = PAINT_TOOL_DRAW, mode = 0;
+ 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 (CTX_wm_view3d(C) && ob) {
+ if ((space_type == SPACE_VIEW3D) && ob) {
if (ob->mode & OB_MODE_SCULPT)
mode = OB_MODE_SCULPT;
else if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT))
@@ -1382,10 +1403,19 @@ static int ui_id_brush_get_icon(const bContext *C, ID *id)
else if (ob->mode & OB_MODE_TEXTURE_PAINT)
mode = OB_MODE_TEXTURE_PAINT;
}
- else if ((sima = CTX_wm_space_image(C)) &&
- (sima->mode == SI_MODE_PAINT))
- {
- mode = OB_MODE_TEXTURE_PAINT;
+ 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) {
+ mode = OB_MODE_TEXTURE_PAINT;
+ }
}
/* reset the icon */
@@ -1421,7 +1451,7 @@ static int ui_id_screen_get_icon(const bContext *C, ID *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:
@@ -1464,7 +1494,7 @@ int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, const bool big
id = RNA_pointer_get(ptr, "texture").data;
}
else if (RNA_struct_is_a(ptr->type, &RNA_DynamicPaintSurface)) {
- DynamicPaintSurface *surface = (DynamicPaintSurface *)ptr->data;
+ DynamicPaintSurface *surface = ptr->data;
if (surface->format == MOD_DPAINT_SURFACE_F_PTEX)
return ICON_TEXTURE_SHADED;
@@ -1473,6 +1503,18 @@ int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, const bool big
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_ORIENTATION_CAMERA:
+ return sl->icon_id_irradiance;
+ case STUDIOLIGHT_ORIENTATION_WORLD:
+ default:
+ return sl->icon_id_radiance;
+ case STUDIOLIGHT_ORIENTATION_VIEWNORMAL:
+ return sl->icon_id_matcap;
+ }
+ }
/* get icon from ID */
if (id) {
@@ -1606,4 +1648,3 @@ void UI_icon_draw_preview_aspect_size(float x, float y, int icon_id, float aspec
{
icon_draw_size(x, y, icon_id, aspect, alpha, NULL, ICON_SIZE_PREVIEW, size, false);
}
-
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 66d9033ba99..23a7718ead0 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -75,19 +75,19 @@ typedef enum {
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,
@@ -245,7 +245,7 @@ struct uiBut {
uiButCompleteFunc autocomplete_func;
void *autofunc_arg;
-
+
uiButSearchCreateFunc search_create_func;
uiButSearchFunc search_func;
bool free_search_arg;
@@ -302,7 +302,7 @@ struct uiBut {
void *dragpoin;
struct ImBuf *imb;
float imb_scale;
-
+
/* active button data */
struct uiHandleButtonData *active;
@@ -314,7 +314,7 @@ struct uiBut {
float *editvec;
void *editcoba;
void *editcumap;
-
+
/* pointer back */
uiBlock *block;
uiButtonGroup *group;
@@ -364,9 +364,9 @@ struct uiBlock {
struct uiLayout *curlayout;
ListBase contexts;
-
+
char name[UI_MAX_NAME_STR];
-
+
float winmat[4][4];
rctf rect;
@@ -386,10 +386,10 @@ struct uiBlock {
uiBlockHandleFunc handle_func;
void *handle_func_arg;
-
+
/* 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;
@@ -446,8 +446,6 @@ typedef struct uiSafetyRct {
void ui_fontscale(short *points, float aspect);
-extern bool ui_block_is_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT;
-extern bool ui_block_is_pie_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT;
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);
@@ -503,7 +501,6 @@ extern int ui_but_is_pushed(uiBut *but) ATTR_WARN_UNUSED_RESULT;
void ui_but_override_flag(uiBut *but);
extern void ui_block_bounds_calc(uiBlock *block);
-extern void ui_block_translate(uiBlock *block, int x, int y);
extern struct ColorManagedDisplay *ui_block_cm_display_get(uiBlock *block);
void ui_block_cm_to_display_space_v3(uiBlock *block, float pixel[3]);
@@ -548,7 +545,7 @@ struct uiPopupBlockHandle {
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' */
@@ -556,6 +553,7 @@ struct uiPopupBlockHandle {
bool refresh;
struct wmTimer *scrolltimer;
+ float scrolloffset;
struct uiKeyNavLock keynav_state;
@@ -565,7 +563,7 @@ struct uiPopupBlockHandle {
ScrArea *ctx_area;
ARegion *ctx_region;
int opcontext;
-
+
/* return values */
int butretval;
int menuretval;
@@ -654,7 +652,7 @@ void ui_pie_menu_level_create(
const EnumPropertyItem *items, int totitem, int context, int flag);
/* interface_region_popup.c */
-void ui_popup_translate(struct bContext *C, struct ARegion *ar, const int mdiff[2]);
+void ui_popup_translate(struct ARegion *ar, const int mdiff[2]);
void ui_popup_block_free(struct bContext *C, uiPopupBlockHandle *handle);
void ui_popup_block_scrolltest(struct uiBlock *block);
@@ -698,15 +696,12 @@ extern void ui_but_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut
extern uiBut *ui_but_find_select_in_enum(uiBut *but, int direction);
extern uiBut *ui_but_find_active_in_region(struct ARegion *ar);
extern uiBut *ui_but_find_mouse_over(struct ARegion *ar, const struct wmEvent *event);
-bool ui_but_is_editable(const uiBut *but);
-bool ui_but_is_editable_as_text(const uiBut *but);
void ui_but_pie_dir_visual(RadialDirection dir, float vec[2]);
void ui_but_pie_dir(RadialDirection dir, float vec[2]);
float ui_block_calc_pie_segment(struct uiBlock *block, const float event_xy[2]);
void ui_but_add_shortcut(uiBut *but, const char *key_str, const bool do_strip);
void ui_but_clipboard_free(void);
-void ui_panel_menu(struct bContext *C, ARegion *ar, Panel *pa);
uiBut *ui_but_find_old(uiBlock *block_old, const uiBut *but_new);
uiBut *ui_but_find_new(uiBlock *block_old, const uiBut *but_new);
@@ -756,14 +751,16 @@ void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float m
void ui_draw_menu_back(struct uiStyle *style, uiBlock *block, rcti *rect);
void ui_draw_popover_back(ARegion *ar, struct uiStyle *style, uiBlock *block, rcti *rect);
void ui_draw_pie_center(uiBlock *block);
-uiWidgetColors *ui_tooltip_get_theme(void);
-void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *block, rcti *rect);
-void ui_draw_search_back(struct uiStyle *style, uiBlock *block, rcti *rect);
+struct uiWidgetColors *ui_tooltip_get_theme(void);
+
+void ui_draw_widget_back_color(
+ uiWidgetTypeEnum type, bool use_shadow, const rcti *rect,
+ const float color[4]);
+void ui_draw_widget_back(
+ uiWidgetTypeEnum type, bool use_shadow, const rcti *rect);
+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);
-/* theme color init */
-struct ThemeUI;
-void ui_widget_color_init(struct ThemeUI *tui);
void ui_draw_menu_item(struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state, bool use_sep);
void ui_draw_preview_item(struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state);
@@ -784,7 +781,7 @@ void ui_icon_ensure_deferred(const struct bContext *C, const int icon_id, const
int ui_id_icon_get(const struct bContext *C, struct ID *id, const bool big);
/* resources.c */
-void init_userdef_do_versions(void);
+void init_userdef_do_versions(struct Main *bmain);
void ui_theme_init_default(void);
void ui_style_init_default(void);
void ui_resources_init(void);
@@ -794,6 +791,8 @@ void ui_resources_free(void);
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_layout_list_set_labels_active(uiLayout *layout);
+/* menu callback */
+void ui_item_paneltype_func(struct bContext *C, struct uiLayout *layout, void *arg_pt);
/* interface_templates.c */
struct uiButtonGroupType *UI_BGT_sortable_id_tabs(void);
@@ -815,6 +814,22 @@ bool ui_but_anim_expression_set(uiBut *but, const char *str);
bool ui_but_anim_expression_create(uiBut *but, const char *str);
void ui_but_anim_autokey(struct bContext *C, uiBut *but, struct Scene *scene, float cfra);
+void ui_but_anim_decorate_cb(struct bContext *C, void *arg_but, void *arg_dummy);
+void ui_but_anim_decorate_update_from_flag(uiBut *but);
+
+/* interface_query.c */
+bool ui_but_is_editable(const uiBut *but);
+bool ui_but_is_editable_as_text(const uiBut *but);
+bool ui_but_is_toggle(const uiBut *but);
+bool ui_but_is_popover_once_compat(const uiBut *but);
+
+extern bool ui_block_is_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT;
+extern bool ui_block_is_pie_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT;
+
+/* interface_context_menu.c */
+bool ui_popup_context_menu_for_button(struct bContext *C, uiBut *but);
+void ui_popup_context_menu_for_panel(struct bContext *C, struct ARegion *ar, struct Panel *pa);
+
/* interface_eyedropper.c */
struct wmKeyMap *eyedropper_modal_keymap(struct wmKeyConfig *keyconf);
struct wmKeyMap *eyedropper_colorband_modal_keymap(struct wmKeyConfig *keyconf);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index d9db5c930fc..63f51b991ae 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -37,6 +37,7 @@
#include "DNA_armature_types.h"
#include "DNA_userdef_types.h"
+#include "BLI_alloca.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_rect.h"
@@ -49,6 +50,7 @@
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_screen.h"
+#include "BKE_animsys.h"
#include "RNA_access.h"
@@ -62,6 +64,13 @@
#include "interface_intern.h"
+/* Show an icon button after each RNA button to use to quickly set keyframes,
+ * this is a way to display animation/driven/override status, see T54951. */
+#define UI_PROP_DECORATE
+/* Alternate draw mode where some buttons can use single icon width,
+ * giving more room for the text at the expense of nicely aligned text. */
+#define UI_PROP_SEP_ICON_WIDTH_EXCEPTION
+
/************************ Structs and Defines *************************/
#define UI_OPERATOR_ERROR_RET(_ot, _opname, return_statement) \
@@ -71,6 +80,7 @@
return_statement; \
} (void)0 \
+#define UI_ITEM_PROP_SEP_DIVIDE 0.5f
/* uiLayoutRoot */
@@ -100,6 +110,7 @@ typedef enum uiItemType {
ITEM_LAYOUT_COLUMN,
ITEM_LAYOUT_COLUMN_FLOW,
ITEM_LAYOUT_ROW_FLOW,
+ ITEM_LAYOUT_GRID_FLOW,
ITEM_LAYOUT_BOX,
ITEM_LAYOUT_ABSOLUTE,
ITEM_LAYOUT_SPLIT,
@@ -128,6 +139,10 @@ enum {
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,
};
typedef struct uiButtonItem {
@@ -150,6 +165,7 @@ struct uiLayout {
bool enabled;
bool redalert;
bool keepaspect;
+ bool variable_size; /* For layouts inside gridflow, they and their items shall never have a fixed maximal size. */
char alignment;
char emboss;
};
@@ -160,6 +176,22 @@ typedef struct uiLayoutItemFlow {
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 num_columns;
+
+ /* Pure internal runtime storage. */
+ int tot_items, tot_columns, tot_rows;
+} uiLayoutItemGridFlow;
+
typedef struct uiLayoutItemBx {
uiLayout litem;
uiBut *roundbox;
@@ -181,7 +213,7 @@ static const char *ui_item_name_add_colon(const char *name, char namestr[UI_MAX_
int len = strlen(name);
if (len != 0 && len + 1 < UI_MAX_NAME_STR) {
- BLI_strncpy(namestr, name, UI_MAX_NAME_STR);
+ memcpy(namestr, name, len);
namestr[len] = ':';
namestr[len + 1] = '\0';
return namestr;
@@ -235,6 +267,13 @@ static int ui_layout_vary_direction(uiLayout *layout)
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;
+}
+
/* estimated size of text + icon */
static int ui_text_icon_width(uiLayout *layout, const char *name, int icon, bool compact)
{
@@ -244,7 +283,7 @@ static int ui_text_icon_width(uiLayout *layout, const char *name, int icon, bool
if (icon && !name[0])
return unit_x; /* icon only */
- variable = (ui_layout_vary_direction(layout) == UI_ITEM_VARY_X);
+ variable = ui_layout_variable_size(layout);
if (variable) {
if (layout->alignment != UI_LAYOUT_ALIGN_EXPAND) {
@@ -301,7 +340,7 @@ static void ui_item_position(uiItem *item, int x, int y, int w, int h)
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 {
@@ -321,7 +360,7 @@ static void ui_item_move(uiItem *item, int delta_xmin, int delta_xmax)
bitem->but->rect.xmin += delta_xmin;
bitem->but->rect.xmax += delta_xmax;
-
+
ui_but_update(bitem->but); /* for strlen */
}
else {
@@ -345,6 +384,7 @@ static int ui_layout_local_dir(uiLayout *layout)
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:
@@ -361,7 +401,7 @@ static uiLayout *ui_item_local_sublayout(uiLayout *test, uiLayout *layout, int a
sub = uiLayoutRow(layout, align);
else
sub = uiLayoutColumn(layout, align);
-
+
sub->space = 0;
return sub;
}
@@ -394,7 +434,7 @@ static void ui_layer_but_cb(bContext *C, void *arg_but, void *arg_index)
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 expand, bool slider, bool toggle, bool icon_only, bool compact, bool show_text)
{
uiStyle *style = layout->root->style;
uiBut *but;
@@ -411,8 +451,9 @@ static void ui_item_array(
UI_block_layout_set_current(block, sub);
/* create label */
- if (name[0])
+ 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)) {
@@ -431,9 +472,9 @@ static void ui_item_array(
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;
@@ -452,7 +493,7 @@ static void ui_item_array(
for (a = 0; a < colbuts; a++) {
const int layer_num = a + b * colbuts;
const unsigned int layer_flag = (1u << layer_num);
-
+
if (layer_used & layer_flag) {
if (layer_active & layer_flag)
icon = ICON_LAYER_ACTIVE;
@@ -470,7 +511,7 @@ static void ui_item_array(
for (a = 0; a < colbuts; a++) {
const int layer_num = a + len / 2 + b * colbuts;
const unsigned int layer_flag = (1u << layer_num);
-
+
if (layer_used & layer_flag) {
if (layer_active & layer_flag)
icon = ICON_LAYER_ACTIVE;
@@ -498,7 +539,7 @@ static void ui_item_array(
totdim = RNA_property_array_dimension(ptr, prop, dim_size);
if (totdim != 2) return; /* only 2D matrices supported in UI so far */
-
+
w /= dim_size[0];
/* h /= dim_size[1]; */ /* UNUSED */
@@ -530,7 +571,7 @@ static void ui_item_array(
/* layout for known array subtypes */
char str[3] = {'\0'};
- if (!icon_only) {
+ if (!icon_only && show_text) {
if (type != PROP_BOOLEAN) {
str[1] = ':';
}
@@ -542,19 +583,21 @@ static void ui_item_array(
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) {
+ 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, icon, false)) : w;
+ min_ii(w, ui_text_icon_width(layout, str_buf, icon, false)) : w;
- but = uiDefAutoButR(block, ptr, prop, a, str, icon, 0, 0, width_item, UI_UNIT_Y);
+ 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)
@@ -696,6 +739,7 @@ static uiBut *ui_item_with_label(
PropertyType type;
PropertySubType subtype;
int prop_but_width = w_hint;
+ const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
sub = uiLayoutRow(layout, layout->align);
UI_block_layout_set_current(block, sub);
@@ -703,15 +747,25 @@ static uiBut *ui_item_with_label(
if (name[0]) {
int w_label;
- if (ui_layout_vary_direction(layout) == UI_ITEM_VARY_X) {
- /* 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;
+ if (use_prop_sep) {
+ w_label = (int)((w_hint * 2) * UI_ITEM_PROP_SEP_DIVIDE);
}
else {
- w_label = w_hint / 3;
+ 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;
}
- uiDefBut(block, UI_BTYPE_LABEL, 0, name, x, y, w_label, h, NULL, 0.0, 0.0, 0, 0, "");
}
type = RNA_property_type(prop);
@@ -1401,7 +1455,8 @@ static void ui_item_rna_size(
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)
@@ -1409,7 +1464,7 @@ static void ui_item_rna_size(
else
h += len * UI_UNIT_Y;
}
- else if (ui_layout_vary_direction(layout) == UI_ITEM_VARY_X) {
+ 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)
@@ -1431,6 +1486,20 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
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);
+
+#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);
@@ -1451,22 +1520,28 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
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)) {
- name = ui_item_name_add_colon(name, namestr);
+ if (use_prop_sep == false) {
+ name = ui_item_name_add_colon(name, namestr);
+ }
}
else if (type == PROP_BOOLEAN && is_array && index == RNA_NO_INDEX) {
- name = ui_item_name_add_colon(name, namestr);
+ 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 {
- name = ui_item_name_add_colon(name, namestr);
+ if (use_prop_sep == false) {
+ name = ui_item_name_add_colon(name, namestr);
+ }
}
}
@@ -1504,12 +1579,102 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
if (no_bg) {
layout->emboss = UI_EMBOSS_NONE;
}
-
+
+ /* Split the label / property. */
+ 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') {
+ /* 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;
+#ifdef UI_PROP_SEP_ICON_WIDTH_EXCEPTION
+ if (type == PROP_BOOLEAN && (icon == ICON_NONE) && !icon_only) {
+ w = UI_UNIT_X;
+ layout_split = uiLayoutRow(layout_row ? layout_row : layout, true);
+ }
+ else
+#endif /* UI_PROP_SEP_ICON_WIDTH_EXCEPTION */
+ {
+ 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;
+ }
+ }
+
+ /* Watch out! We can only write into the new column now. */
+ layout = uiLayoutColumn(layout_split, true);
+ layout->space = 0;
+ if ((type == PROP_ENUM) && (flag & UI_ITEM_R_EXPAND)) {
+ /* pass (expanded enums each have their own name) */
+ }
+ else {
+ name = "";
+ }
+ }
+
+#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;
+ }
+#endif /* UI_PROP_DECORATE */
+ }
+ /* End split. */
+
/* array property */
- if (index == RNA_NO_INDEX && is_array)
+ 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);
+ layout, block, name, icon, ptr, prop, len, 0, 0, w, h,
+ expand, slider, toggle, icon_only, compact, !use_prop_sep);
+ }
/* enum item */
else if (type == PROP_ENUM && index == RNA_ENUM_VALUE) {
if (icon && name[0] && !icon_only)
@@ -1526,7 +1691,7 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
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);
}
@@ -1539,16 +1704,50 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
if (toggle && but->type == UI_BTYPE_CHECKBOX)
but->type = UI_BTYPE_TOGGLE;
-
+
if (layout->redalert)
UI_but_flag_enable(but, UI_BUT_REDALERT);
}
/* Mark non-embossed textfields inside a listbox. */
- if (but && (block->flag & UI_BLOCK_LIST_ITEM) && (but->dt & UI_EMBOSS_NONE)) {
+ 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));
+ }
+#endif /* UI_PROP_DECORATE */
+
if (no_bg) {
layout->emboss = prev_emboss;
}
@@ -1705,7 +1904,8 @@ static void search_id_collection(StructRNA *ptype, PointerRNA *ptr, PropertyRNA
StructRNA *srna;
/* look for collection property in Main */
- RNA_main_pointer_create(G.main, ptr);
+ /* Note: using global Main is OK-ish here, UI shall not access other Mains anyay... */
+ RNA_main_pointer_create(G_MAIN, ptr);
*prop = NULL;
@@ -1783,7 +1983,8 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna
StructRNA *icontype;
int w, h;
char namestr[UI_MAX_NAME_STR];
-
+ const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
+
/* validate arguments */
prop = RNA_struct_find_property(ptr, propname);
@@ -1792,7 +1993,7 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna
RNA_struct_identifier(ptr->type), propname);
return;
}
-
+
type = RNA_property_type(prop);
if (!ELEM(type, PROP_POINTER, PROP_STRING, PROP_ENUM)) {
RNA_warning("Property %s must be a pointer, string or enum", propname);
@@ -1825,7 +2026,9 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna
if (!name)
name = RNA_property_ui_name(prop);
- name = ui_item_name_add_colon(name, namestr);
+ if (use_prop_sep == false) {
+ name = ui_item_name_add_colon(name, namestr);
+ }
/* create button */
block = uiLayoutGetBlock(layout);
@@ -1848,33 +2051,13 @@ static void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt)
layout->root->block->flag ^= UI_BLOCK_IS_FLIP;
}
-static void ui_item_paneltype_func(bContext *C, uiLayout *layout, void *arg_mt)
+void ui_item_paneltype_func(bContext *C, uiLayout *layout, void *arg_pt)
{
- PanelType *pt = (PanelType *)arg_mt;
-
- /* TODO: move into UI_paneltype_draw */
- Panel *panel = MEM_callocN(sizeof(Panel), "popover panel");
- panel->type = pt;
-
- if (layout->context) {
- CTX_store_set(C, layout->context);
- }
-
- if (pt->draw_header) {
- panel->layout = uiLayoutRow(layout, false);
- pt->draw_header(C, panel);
- panel->layout = NULL;
- }
-
- panel->layout = layout;
- pt->draw(C, panel);
- panel->layout = NULL;
-
- if (layout->context) {
- CTX_store_set(C, NULL);
- }
+ PanelType *pt = (PanelType *)arg_pt;
+ UI_paneltype_draw(C, pt, layout);
- MEM_freeN(panel);
+ /* panels are created flipped (from event handling pov) */
+ layout->root->block->flag ^= UI_BLOCK_IS_FLIP;
}
static uiBut *ui_item_menu(
@@ -1896,12 +2079,15 @@ static uiBut *ui_item_menu(
h = UI_UNIT_Y;
if (layout->root->type == UI_LAYOUT_HEADER) { /* ugly .. */
- if (force_menu) {
- w += UI_UNIT_Y;
+ if (icon == ICON_NONE && force_menu) {
+ /* pass */
+ }
+ else if (force_menu) {
+ w += UI_UNIT_X;
}
else {
if (name[0]) {
- w -= UI_UNIT_Y / 2;
+ w -= UI_UNIT_X / 2;
}
}
}
@@ -1927,7 +2113,7 @@ static uiBut *ui_item_menu(
return but;
}
-void uiItemM(uiLayout *layout, bContext *UNUSED(C), const char *menuname, const char *name, int icon)
+void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon)
{
MenuType *mt;
@@ -1955,12 +2141,23 @@ void uiItemPopoverPanel_ptr(uiLayout *layout, bContext *C, PanelType *pt, const
name = CTX_IFACE_(pt->translation_context, pt->label);
}
- if (layout->root->type == UI_LAYOUT_MENU && !icon)
+ 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 (pt->poll && (pt->poll(C, pt) == false)) {
+ if (!ok) {
but->flag |= UI_BUT_DISABLED;
}
}
@@ -2013,10 +2210,12 @@ void uiItemPopoverPanelFromGroup(
for (PanelType *pt = art->paneltypes.first; pt; pt = pt->next) {
/* Causes too many panels, check context. */
- 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);
+ 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);
+ }
}
}
}
@@ -2114,6 +2313,26 @@ void uiItemS(uiLayout *layout)
uiDefBut(block, (is_menu) ? UI_BTYPE_SEPR_LINE : UI_BTYPE_SEPR, 0, "", 0, 0, space, space, NULL, 0.0, 0.0, 0, 0, "");
}
+/* Flexible spacing. */
+void uiItemSpacer(uiLayout *layout)
+{
+ uiBlock *block = layout->root->block;
+ bool is_menu = ui_block_is_menu(block);
+
+ if (is_menu) {
+ printf("Error: separator_spacer() not supported in menus.\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)
{
@@ -2296,7 +2515,7 @@ static void ui_litem_layout_row(uiLayout *litem)
if (totw == 0)
return;
-
+
if (w != 0)
w -= (tot - 1) * litem->space;
fixedw = 0;
@@ -2327,7 +2546,7 @@ static void ui_litem_layout_row(uiLayout *litem)
/* 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 &&
+ litem->alignment == UI_LAYOUT_ALIGN_EXPAND &&
((uiItem *)litem)->flag & UI_ITEM_MIN)
{
min_flag = false;
@@ -2435,7 +2654,7 @@ static void ui_litem_estimate_column(uiLayout *litem, bool is_box)
if (item->next && (!is_box || item != litem->items.first))
litem->h += litem->space;
}
-
+
if (min_size_flag) {
litem->item.flag |= UI_ITEM_MIN;
}
@@ -2497,7 +2716,7 @@ static bool ui_item_is_radial_displayable(uiItem *item)
static bool ui_item_is_radial_drawable(uiButtonItem *bitem)
{
- if (ELEM(bitem->but->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE))
+ if (ELEM(bitem->but->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_SEPR_SPACER))
return false;
return true;
@@ -2770,6 +2989,364 @@ static void ui_litem_layout_column_flow(uiLayout *litem)
litem->y = miny;
}
+/* multi-column and multi-row layout. */
+typedef struct UILayoutGridFlowInput {
+ /* General layout controll 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. */
+} 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_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 resonable cases... */
+ if (gflow->num_columns > 0) {
+ gflow->tot_columns = gflow->num_columns;
+ }
+ 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->num_columns < -1) ? -gflow->num_columns : 0;
+ const int step = modulo ? modulo : 1;
+
+ if (gflow->row_major) {
+ /* Adjust number of columns to be mutiple 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);
+ }
+ else {
+ /* Adjust number of rows to be mutiple 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);
+ }
+ }
+
+ /* 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;
+}
+
/* free layout */
static void ui_litem_estimate_absolute(uiLayout *litem)
{
@@ -2825,7 +3402,7 @@ static void ui_litem_layout_absolute(uiLayout *litem)
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;
@@ -2876,7 +3453,7 @@ static void ui_litem_layout_split(uiLayout *litem)
y = litem->y;
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);
@@ -2943,12 +3520,15 @@ static void ui_litem_init_from_parent(uiLayout *litem, uiLayout *layout, int ali
{
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));
BLI_addtail(&layout->items, litem);
}
@@ -2999,6 +3579,26 @@ uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align)
return &flow->litem;
}
+uiLayout *uiLayoutGridFlow(
+ uiLayout *layout, int row_major, int num_columns, int even_columns, int even_rows, int align)
+{
+ 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->litem.space = (flow->litem.align) ? 0 : layout->root->style->columnspace;
+ flow->row_major = row_major;
+ flow->num_columns = num_columns;
+ flow->even_columns = even_columns;
+ flow->even_rows = even_rows;
+
+ UI_block_layout_set_current(layout->root->block, &flow->litem);
+
+ return &flow->litem;
+}
+
static uiLayoutItemBx *ui_layout_box(uiLayout *layout, int type)
{
uiLayoutItemBx *box;
@@ -3183,6 +3783,26 @@ void uiLayoutSetEmboss(uiLayout *layout, char emboss)
layout->emboss = emboss;
}
+bool uiLayoutGetPropSep(uiLayout *layout)
+{
+ 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);
+}
+
+bool uiLayoutGetPropDecorate(uiLayout *layout)
+{
+ 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);
+}
+
bool uiLayoutGetActive(uiLayout *layout)
{
return layout->active;
@@ -3241,6 +3861,11 @@ static void ui_item_scale(uiLayout *litem, const float scale[2])
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);
+ }
+
ui_item_size(item, &w, &h);
ui_item_offset(item, &x, &y);
@@ -3284,6 +3909,9 @@ static void ui_item_estimate(uiItem *item)
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;
@@ -3383,6 +4011,9 @@ static void ui_item_layout(uiItem *item)
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;
@@ -3479,6 +4110,9 @@ uiLayout *UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int s
layout = MEM_callocN(sizeof(uiLayout), "uiLayout");
layout->item.type = ITEM_LAYOUT_ROOT;
+ /* 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;
@@ -3509,7 +4143,7 @@ uiLayout *UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int s
BLI_addtail(&block->layouts, root);
ui_layout_add_padding_button(root);
-
+
return layout;
}
@@ -3532,7 +4166,7 @@ void UI_block_layout_set_current(uiBlock *block, uiLayout *layout)
void ui_layout_add_but(uiLayout *layout, uiBut *but)
{
uiButtonItem *bitem;
-
+
bitem = MEM_callocN(sizeof(uiButtonItem), "uiButtonItem");
bitem->item.type = ITEM_BUTTON;
bitem->but = but;
@@ -3623,93 +4257,6 @@ void uiLayoutSetContextFromBut(uiLayout *layout, uiBut *but)
}
}
-/* introspect funcs */
-#include "BLI_dynstr.h"
-
-static void ui_intro_button(DynStr *ds, uiButtonItem *bitem)
-{
- uiBut *but = bitem->but;
- BLI_dynstr_appendf(ds, "'type':%d, ", (int)but->type);
- BLI_dynstr_appendf(ds, "'draw_string':'''%s''', ", but->drawstr);
- BLI_dynstr_appendf(ds, "'tip':'''%s''', ", but->tip ? but->tip : ""); /* not exactly needed, rna has this */
-
- if (but->optype) {
- char *opstr = WM_operator_pystring_ex(but->block->evil_C, NULL, false, true, but->optype, but->opptr);
- BLI_dynstr_appendf(ds, "'operator':'''%s''', ", opstr ? opstr : "");
- MEM_freeN(opstr);
- }
-
- if (but->rnaprop) {
- BLI_dynstr_appendf(ds, "'rna':'%s.%s[%d]', ", RNA_struct_identifier(but->rnapoin.type), RNA_property_identifier(but->rnaprop), but->rnaindex);
- }
-
-}
-
-static void ui_intro_items(DynStr *ds, ListBase *lb)
-{
- uiItem *item;
-
- BLI_dynstr_append(ds, "[");
-
- for (item = lb->first; item; item = item->next) {
-
- BLI_dynstr_append(ds, "{");
-
- /* could also use the INT but this is nicer*/
- switch (item->type) {
- case ITEM_BUTTON: BLI_dynstr_append(ds, "'type':'BUTTON', "); break;
- case ITEM_LAYOUT_ROW: BLI_dynstr_append(ds, "'type':'UI_BTYPE_ROW', "); break;
- case ITEM_LAYOUT_COLUMN: BLI_dynstr_append(ds, "'type':'COLUMN', "); break;
- case ITEM_LAYOUT_COLUMN_FLOW: BLI_dynstr_append(ds, "'type':'COLUMN_FLOW', "); break;
- case ITEM_LAYOUT_ROW_FLOW: BLI_dynstr_append(ds, "'type':'ROW_FLOW', "); break;
- case ITEM_LAYOUT_BOX: BLI_dynstr_append(ds, "'type':'BOX', "); break;
- case ITEM_LAYOUT_ABSOLUTE: BLI_dynstr_append(ds, "'type':'ABSOLUTE', "); break;
- case ITEM_LAYOUT_SPLIT: BLI_dynstr_append(ds, "'type':'SPLIT', "); break;
- case ITEM_LAYOUT_OVERLAP: BLI_dynstr_append(ds, "'type':'OVERLAP', "); break;
- case ITEM_LAYOUT_ROOT: BLI_dynstr_append(ds, "'type':'ROOT', "); break;
- default: BLI_dynstr_append(ds, "'type':'UNKNOWN', "); break;
- }
-
- switch (item->type) {
- case ITEM_BUTTON:
- ui_intro_button(ds, (uiButtonItem *)item);
- break;
- default:
- BLI_dynstr_append(ds, "'items':");
- ui_intro_items(ds, &((uiLayout *)item)->items);
- break;
- }
-
- BLI_dynstr_append(ds, "}");
-
- if (item != lb->last)
- BLI_dynstr_append(ds, ", ");
- }
- BLI_dynstr_append(ds, "], ");
-}
-
-static void ui_intro_uiLayout(DynStr *ds, uiLayout *layout)
-{
- ui_intro_items(ds, &layout->items);
-}
-
-static char *str = NULL; /* XXX, constant re-freeing, far from ideal. */
-const char *uiLayoutIntrospect(uiLayout *layout)
-{
- DynStr *ds = BLI_dynstr_new();
-
- if (str) {
- MEM_freeN(str);
- }
-
- ui_intro_uiLayout(ds, layout);
-
- str = BLI_dynstr_get_cstring(ds);
- BLI_dynstr_free(ds);
-
- return str;
-}
-
/* this is a bit of a hack but best keep it in one place at least */
MenuType *UI_but_menutype_get(uiBut *but)
{
@@ -3754,3 +4301,64 @@ void UI_menutype_draw(bContext *C, MenuType *mt, struct uiLayout *layout)
CTX_store_set(C, NULL);
}
}
+
+
+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;
+
+ 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);
+ }
+
+ panel->layout = layout;
+ pt->draw(C, panel);
+ panel->layout = NULL;
+
+ MEM_freeN(panel);
+
+ /* 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;
+ }
+
+ uiLayout *col = uiLayoutColumn(layout, false);
+ ui_paneltype_draw_impl(C, child_pt, col, true);
+ }
+ }
+}
+
+/**
+ * Used for popup panels only.
+ */
+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, NULL);
+ }
+
+}
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 00fc38f1351..911508ebbfc 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -17,7 +17,7 @@
*
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
- *
+ *
* Contributor(s): Blender Foundation, Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
@@ -78,7 +78,7 @@ static int reset_default_theme_exec(bContext *C, wmOperator *UNUSED(op))
ui_theme_init_default();
ui_style_init_default();
WM_event_add_notifier(C, NC_WINDOW, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -88,10 +88,10 @@ static void UI_OT_reset_default_theme(wmOperatorType *ot)
ot->name = "Reset to Default Theme";
ot->idname = "UI_OT_reset_default_theme";
ot->description = "Reset to the default theme colors";
-
+
/* callbacks */
ot->exec = reset_default_theme_exec;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER;
}
@@ -109,7 +109,7 @@ static int copy_data_path_button_poll(bContext *C)
if (ptr.id.data && ptr.data && prop) {
path = RNA_path_from_ID_to_property(&ptr, prop);
-
+
if (path) {
MEM_freeN(path);
return 1;
@@ -255,7 +255,7 @@ static int reset_default_button_poll(bContext *C)
int index;
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
-
+
return (ptr.data && prop && RNA_property_editable(&ptr, prop));
}
@@ -268,7 +268,7 @@ static int reset_default_button_exec(bContext *C, wmOperator *op)
/* 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))
@@ -291,7 +291,7 @@ static void UI_OT_reset_default_button(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_UNDO;
-
+
/* properties */
RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array");
}
@@ -464,6 +464,7 @@ static int override_remove_button_poll(bContext *C)
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;
@@ -505,7 +506,7 @@ static int override_remove_button_exec(bContext *C, wmOperator *op)
}
BKE_override_static_property_operation_delete(oprop, opop);
if (!is_template) {
- RNA_property_copy(&ptr, &src, prop, index);
+ RNA_property_copy(bmain, &ptr, &src, prop, index);
}
if (BLI_listbase_is_empty(&oprop->operations)) {
BKE_override_static_property_delete(id->override_static, oprop);
@@ -515,7 +516,7 @@ static int override_remove_button_exec(bContext *C, wmOperator *op)
/* Just remove whole generic override operation of this property. */
BKE_override_static_property_delete(id->override_static, oprop);
if (!is_template) {
- RNA_property_copy(&ptr, &src, prop, -1);
+ RNA_property_copy(bmain, &ptr, &src, prop, -1);
}
}
@@ -699,6 +700,7 @@ 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;
@@ -747,7 +749,7 @@ static bool copy_to_selected_button(bContext *C, bool all, bool poll)
break;
}
else {
- if (RNA_property_copy(&lptr, &ptr, prop, (all) ? -1 : index)) {
+ if (RNA_property_copy(bmain, &lptr, &ptr, prop, (all) ? -1 : index)) {
RNA_property_update(C, &lptr, prop);
success = true;
}
@@ -800,7 +802,7 @@ static void UI_OT_copy_to_selected_button(wmOperatorType *ot)
/* Reports to Textblock Operator ------------------------ */
-/* FIXME: this is just a temporary operator so that we can see all the reports somewhere
+/* FIXME: this is just a temporary operator so that we can see all the reports somewhere
* when there are too many to display...
*/
@@ -815,10 +817,10 @@ static int reports_to_text_exec(bContext *C, wmOperator *UNUSED(op))
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)
@@ -843,7 +845,7 @@ static void UI_OT_reports_to_textblock(wmOperatorType *ot)
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;
@@ -957,7 +959,7 @@ static int editsource_text_edit(
}
if (text == NULL) {
- text = BKE_text_load(bmain, filepath, bmain->name);
+ text = BKE_text_load(bmain, filepath, BKE_main_blendfile_path(bmain));
id_us_ensure_real(&text->id);
}
@@ -1004,6 +1006,7 @@ static int editsource_exec(bContext *C, wmOperator *op)
ui_editsource_active_but_set(but);
/* redraw and get active button python info */
+ ED_region_do_layout(C, ar);
ED_region_do_draw(C, ar);
ar->do_draw = false;
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index f621a906789..1e3a080c097 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -29,7 +29,7 @@
/* a full doc with API notes can be found in bf-blender/trunk/blender/doc/guides/interface_API.txt */
-
+
#include <math.h>
#include <stdlib.h>
#include <string.h>
@@ -63,6 +63,7 @@
#include "UI_resources.h"
#include "GPU_immediate.h"
+#include "GPU_state.h"
#include "interface_intern.h"
@@ -110,6 +111,7 @@ typedef struct uiHandlePanelData {
int startsizex, startsizey;
} uiHandlePanelData;
+static int get_panel_real_size_y(const Panel *pa);
static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelState state);
/*********************** space specific code ************************/
@@ -129,49 +131,84 @@ static int panel_aligned(ScrArea *sa, ARegion *ar)
return BUT_VERTICAL;
else if (ELEM(ar->regiontype, RGN_TYPE_UI, RGN_TYPE_TOOLS, RGN_TYPE_TOOL_PROPS))
return BUT_VERTICAL;
-
+
return 0;
}
-static int panels_re_align(ScrArea *sa, ARegion *ar, Panel **r_pa)
+static bool panel_active_animation_changed(ListBase *lb, Panel **pa_animation, bool *no_animation)
{
- Panel *pa;
- int active = 0;
+ 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;
+ }
+ }
- *r_pa = NULL;
+ 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 **pa_animate)
+{
+ *pa_animate = NULL;
if (sa->spacetype == SPACE_BUTS && ar->regiontype == RGN_TYPE_WINDOW) {
SpaceButs *sbuts = sa->spacedata.first;
- if (sbuts->align)
- if (sbuts->re_align || sbuts->mainbo != sbuts->mainb)
- return 1;
+ if (sbuts->align) {
+ if (sbuts->re_align || 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;
}
- else if (sa->spacetype == SPACE_IMAGE && ar->regiontype == RGN_TYPE_PREVIEW)
- return 1;
- else if (sa->spacetype == SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS)
- return 1;
- /* in case panel is added or disappears */
- for (pa = ar->panels.first; pa; pa = pa->next) {
- if ((pa->runtime_flag & PNL_WAS_ACTIVE) && !(pa->runtime_flag & PNL_ACTIVE))
- return 1;
- if (!(pa->runtime_flag & PNL_WAS_ACTIVE) && (pa->runtime_flag & PNL_ACTIVE))
- return 1;
- if (pa->activedata)
- active = 1;
+ /* 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;
}
- /* in case we need to do an animation (size changes) */
- for (pa = ar->panels.first; pa; pa = pa->next) {
- if (pa->runtime_flag & PNL_ANIM_ALIGN) {
- if (!active)
- *r_pa = pa;
- return 1;
+ /* Detect panel marked for animation, if we're not already animating. */
+ if (pa_animation) {
+ if (!no_animation) {
+ *pa_animate = pa_animation;
}
+ return true;
}
-
- return 0;
+
+ return false;
}
/****************************** panels ******************************/
@@ -215,14 +252,14 @@ static void ui_panel_copy_offset(Panel *pa, Panel *papar)
*/
/* #define UI_USE_PANELTAB */
-Panel *UI_panel_find_by_type(ARegion *ar, PanelType *pt)
+Panel *UI_panel_find_by_type(ListBase *lb, PanelType *pt)
{
Panel *pa;
const char *idname = pt->idname;
#ifdef UI_USE_PANELTAB
const char *tabname = pt->idname;
- for (pa = ar->panels.first; pa; pa = pa->next) {
+ 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;
@@ -230,7 +267,7 @@ Panel *UI_panel_find_by_type(ARegion *ar, PanelType *pt)
}
}
#else
- for (pa = ar->panels.first; pa; pa = pa->next) {
+ for (pa = lb->first; pa; pa = pa->next) {
if (STREQLEN(pa->panelname, idname, sizeof(pa->panelname))) {
return pa;
}
@@ -243,7 +280,7 @@ Panel *UI_panel_find_by_type(ARegion *ar, PanelType *pt)
/**
* \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, 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);
@@ -270,14 +307,16 @@ Panel *UI_panel_begin(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, P
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(&ar->panels, pa);
+ BLI_addtail(lb, pa);
#ifdef UI_USE_PANELTAB
BLI_strncpy(pa->tabname, tabname, sizeof(pa->tabname));
@@ -285,7 +324,7 @@ Panel *UI_panel_begin(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, P
/* make new Panel tabbed? */
if (hookname) {
Panel *patab;
- for (patab = ar->panels.first; patab; patab = patab->next) {
+ 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))) {
@@ -308,6 +347,8 @@ Panel *UI_panel_begin(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, P
/* 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));
@@ -315,14 +356,18 @@ Panel *UI_panel_begin(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, P
/* 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 = ar->panels.first; palast; palast = palast->next)
- if (palast->runtime_flag & PNL_LAST_ADDED)
+ 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 = ar->panels.first; panext; panext = panext->next)
+ for (panext = lb->first; panext; panext = panext->next)
if (panext != pa && panext->sortorder >= pa->sortorder)
panext->sortorder++;
}
@@ -340,7 +385,7 @@ Panel *UI_panel_begin(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, P
if (pa->flag & PNL_CLOSED) return pa;
*r_open = true;
-
+
return pa;
}
@@ -348,6 +393,19 @@ 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;
@@ -372,15 +430,13 @@ void UI_panel_end(uiBlock *block, int width, int height)
static void ui_offset_panel_block(uiBlock *block)
{
uiStyle *style = UI_style_get_dpi();
- uiBut *but;
- int ofsy;
/* compute bounds and offset */
ui_block_bounds_calc(block);
- ofsy = block->panel->sizey - style->panelspace;
+ int ofsy = block->panel->sizey - style->panelspace;
- for (but = block->buttons.first; but; but = but->next) {
+ for (uiBut *but = block->buttons.first; but; but = but->next) {
but->rect.ymin += ofsy;
but->rect.ymax += ofsy;
}
@@ -398,7 +454,7 @@ void UI_draw_icon_tri(float x, float y, char dir, const float color[4])
float f3 = 0.15 * U.widget_unit;
float f5 = 0.25 * U.widget_unit;
float f7 = 0.35 * U.widget_unit;
-
+
if (dir == 'h') {
UI_draw_anti_tria(x - f3, y - f5, x - f3, y + f5, x + f7, y, color);
}
@@ -431,10 +487,10 @@ static void ui_draw_anti_x(unsigned int pos, float x1, float y1, float x2, float
{
/* set antialias line */
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
+ GPU_line_smooth(true);
+ GPU_blend(true);
- glLineWidth(2.0);
+ GPU_line_width(2.0);
immBegin(GWN_PRIM_LINES, 4);
@@ -445,10 +501,10 @@ static void ui_draw_anti_x(unsigned int pos, float x1, float y1, float x2, float
immVertex2f(pos, x2, y1);
immEnd();
-
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
-
+
+ GPU_line_smooth(false);
+ GPU_blend(false);
+
}
/* x 'icon' for panel header */
@@ -465,16 +521,16 @@ static void ui_draw_panel_scalewidget(unsigned int pos, const rcti *rect)
{
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;
-
+
dx = 0.5f * (xmax - xmin);
dy = 0.5f * (ymax - ymin);
-
- glEnable(GL_BLEND);
+
+ GPU_blend(true);
immUniformColor4ub(255, 255, 255, 50);
immBegin(GWN_PRIM_LINES, 4);
@@ -486,7 +542,7 @@ static void ui_draw_panel_scalewidget(unsigned int pos, const rcti *rect)
immVertex2f(pos, xmax, ymax - dy);
immEnd();
-
+
immUniformColor4ub(0, 0, 0, 50);
immBegin(GWN_PRIM_LINES, 4);
@@ -499,7 +555,7 @@ static void ui_draw_panel_scalewidget(unsigned int pos, const rcti *rect)
immEnd();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
static void immRectf_tris_color_ex(unsigned int pos, float x1, float y1, float x2, float y2,
@@ -557,6 +613,20 @@ static void ui_draw_panel_dragwidget(unsigned int pos, unsigned int col, const r
immEnd();
}
+/* For button layout next to label. */
+void UI_panel_label_offset(uiBlock *block, int *x, int *y)
+{
+ Panel *panel = block->panel;
+ uiStyle *style = UI_style_get_dpi();
+ const bool is_subpanel = (panel->type && panel->type->parent);
+
+ *x = UI_UNIT_X * 1.1f;
+ *y = (UI_UNIT_Y * 1.1f) + style->panelspace;
+
+ if (is_subpanel) {
+ *x += 5.0f / block->aspect;
+ }
+}
static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, const rcti *rect, char dir)
{
@@ -564,6 +634,8 @@ static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, const r
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;
unsigned char col_title[4];
/* + 0.001f to avoid flirting with float inaccuracy */
@@ -580,14 +652,14 @@ static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, const r
if (dir == 'h') {
hrect.xmin = rect->xmin + pnl_icons;
hrect.ymin += 2.0f / block->aspect;
- UI_fontstyle_draw(&style->paneltitle, &hrect, activename, col_title);
+ UI_fontstyle_draw(fontstyle, &hrect, activename, col_title);
}
else {
- /* ignore 'pnl_icons', otherwise the text gets offset horizontally
+ /* 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(&style->paneltitle, &hrect, activename, col_title);
+ UI_fontstyle_draw_rotated(fontstyle, &hrect, activename, col_title);
}
}
@@ -600,6 +672,8 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
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;
if (panel->paneltab) return;
if (panel->type && (panel->type->flag & PNL_NO_HEADER)) return;
@@ -610,15 +684,20 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
headrect.ymin = headrect.ymax;
headrect.ymax = headrect.ymin + floor(PNL_HEADER / block->aspect + 0.001f);
+ rcti titlerect = headrect;
+ if (is_subpanel) {
+ titlerect.xmin += 5.0f / block->aspect;
+ }
+
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- {
+ if (!is_subpanel) {
float minx = rect->xmin;
float maxx = is_closed_x ? (minx + PNL_HEADER / block->aspect) : rect->xmax;
float y = headrect.ymax;
- glEnable(GL_BLEND);
+ GPU_blend(true);
if (UI_GetThemeValue(TH_PANEL_SHOW_HEADER)) {
/* draw with background color */
@@ -658,7 +737,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
immEnd();
}
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
immUnbindProgram();
@@ -671,35 +750,38 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
if (show_pin)
#endif
{
- glEnable(GL_BLEND);
+ 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);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
/* horizontal title */
if (is_closed_x == false) {
- unsigned int col;
- ui_draw_aligned_panel_header(style, block, &headrect, 'h');
- Gwn_VertFormat *format = immVertexFormat();
- pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
-
- /* itemrect smaller */
- itemrect.xmax = headrect.xmax - 5.0f / block->aspect;
- 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();
+ ui_draw_aligned_panel_header(style, block, &titlerect, 'h');
+
+ if (show_drag) {
+ unsigned int col;
+ Gwn_VertFormat *format = immVertexFormat();
+ pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+
+ /* itemrect smaller */
+ itemrect.xmax = headrect.xmax - 5.0f / block->aspect;
+ 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 = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ /* Restore format for the following draws. */
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ }
}
/* if the panel is minimized vertically:
@@ -727,9 +809,13 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* panel backdrop */
- if (UI_GetThemeValue(TH_PANEL_SHOW_BACK)) {
- /* draw with background color */
- glEnable(GL_BLEND);
+ if (is_subpanel) {
+ GPU_blend(true);
+ immUniformThemeColor(TH_PANEL_SUB_BACK);
+ immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ }
+ else if (UI_GetThemeValue(TH_PANEL_SHOW_BACK)) {
+ GPU_blend(true);
immUniformThemeColor(TH_PANEL_BACK);
immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
}
@@ -753,12 +839,12 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
/* draw collapse icon */
/* itemrect smaller */
- itemrect.xmin = headrect.xmin + 5.0f / block->aspect;
- itemrect.xmax = itemrect.xmin + BLI_rcti_size_y(&headrect);
- itemrect.ymin = headrect.ymin;
- itemrect.ymax = headrect.ymax;
+ itemrect.xmin = titlerect.xmin + 3.0f / block->aspect;
+ itemrect.xmax = itemrect.xmin + BLI_rcti_size_y(&titlerect);
+ itemrect.ymin = titlerect.ymin;
+ itemrect.ymax = titlerect.ymax;
- BLI_rctf_scale(&itemrect, 0.35f);
+ BLI_rctf_scale(&itemrect, 0.25f);
if (is_closed_y)
ui_draw_tria_rect(&itemrect, 'h');
@@ -770,7 +856,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
/************************** panel alignment *************************/
-static int get_panel_header(Panel *pa)
+static int get_panel_header(const Panel *pa)
{
if (pa->type && (pa->type->flag & PNL_NO_HEADER))
return 0;
@@ -778,7 +864,7 @@ static int get_panel_header(Panel *pa)
return PNL_HEADER;
}
-static int get_panel_size_y(Panel *pa)
+static int get_panel_size_y(const Panel *pa)
{
if (pa->type && (pa->type->flag & PNL_NO_HEADER))
return pa->sizey;
@@ -786,6 +872,21 @@ static int get_panel_size_y(Panel *pa)
return PNL_HEADER + pa->sizey;
}
+static int get_panel_real_size_y(const Panel *pa)
+{
+ int sizey = (pa->flag & PNL_CLOSED) ? 0 : pa->sizey;
+
+ if (pa->type && (pa->type->flag & PNL_NO_HEADER))
+ return sizey;
+
+ return PNL_HEADER + sizey;
+}
+
+int UI_panel_size_y(const Panel *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)
@@ -818,7 +919,7 @@ 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;
@@ -831,7 +932,7 @@ static int find_leftmost_panel(const void *a1, const void *a2)
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) {
@@ -844,20 +945,38 @@ static int find_highest_panel(const void *a1, const void *a2)
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;
-
+
if (ps1->pa->sortorder > ps2->pa->sortorder) return 1;
else if (ps1->pa->sortorder < ps2->pa->sortorder) return -1;
-
+
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);
+ }
+ }
+ }
+}
+
/* this doesnt draw */
/* returns 1 when it did something */
static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bool drag)
@@ -868,7 +987,7 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo
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)
@@ -888,7 +1007,7 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo
/* 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) {
@@ -897,7 +1016,7 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo
ps++;
}
}
-
+
if (drag) {
/* while we are dragging, we sort on location and update sortorder */
if (align == BUT_VERTICAL)
@@ -911,7 +1030,7 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo
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;
@@ -935,7 +1054,7 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo
psnext->pa->ofsy = ps->pa->ofsy + get_panel_size_y(ps->pa) - get_panel_size_y(psnext->pa);
}
}
-
+
/* we interpolate */
done = false;
ps = panelsort;
@@ -949,17 +1068,24 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo
}
}
- /* copy locations to tabs */
- for (pa = ar->panels.first; pa; pa = pa->next)
- if (pa->paneltab && (pa->runtime_flag & PNL_ACTIVE))
- ui_panel_copy_offset(pa, pa->paneltab);
+ /* 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;
}
@@ -993,7 +1119,7 @@ static void ui_panels_size(ScrArea *sa, ARegion *ar, int *x, int *y)
sizex = UI_PANEL_WIDTH;
if (sizey == 0)
sizey = -UI_PANEL_WIDTH;
-
+
*x = sizex;
*y = sizey;
}
@@ -1022,27 +1148,34 @@ static void ui_do_animate(const bContext *C, Panel *panel)
}
}
-void UI_panels_begin(const bContext *UNUSED(C), ARegion *ar)
+static void panel_list_clear_active(ListBase *lb)
{
- Panel *pa;
-
/* set all panels as inactive, so that at the end we know
* which ones were used */
- for (pa = ar->panels.first; pa; pa = pa->next) {
- if (pa->runtime_flag & PNL_ACTIVE)
+ for (Panel *pa = lb->first; pa; pa = pa->next) {
+ if (pa->runtime_flag & PNL_ACTIVE) {
pa->runtime_flag = PNL_WAS_ACTIVE;
- else
+ }
+ 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);
+}
+
/* only draws blocks with panels */
void UI_panels_end(const bContext *C, ARegion *ar, int *x, int *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)
@@ -1074,8 +1207,7 @@ void UI_panels_end(const bContext *C, ARegion *ar, int *x, int *y)
}
/* re-align, possibly with animation */
- if (panels_re_align(sa, ar, &pa)) {
- /* XXX code never gets here... PNL_ANIM_ALIGN flag is never set */
+ if (panels_need_realign(sa, ar, &pa)) {
if (pa)
panel_activate_state(C, pa, PANEL_STATE_ANIMATION);
else
@@ -1088,10 +1220,10 @@ void UI_panels_end(const bContext *C, ARegion *ar, int *x, int *y)
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, x, y);
}
@@ -1101,15 +1233,17 @@ void UI_panels_draw(const bContext *C, ARegion *ar)
uiBlock *block;
UI_ThemeClearColor(TH_BACK);
-
- /* draw panels, selected on top */
- for (block = ar->uiblocks.first; block; block = block->next) {
+
+ /* 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.first; block; block = block->next) {
+ for (block = ar->uiblocks.last; block; block = block->prev) {
if (block->active && block->panel && (block->panel->flag & PNL_SELECT)) {
UI_block_draw(C, block);
}
@@ -1120,12 +1254,12 @@ 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;
@@ -1141,13 +1275,13 @@ 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;
@@ -1171,7 +1305,7 @@ static void ui_do_drag(const bContext *C, const wmEvent *event, Panel *panel)
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;
@@ -1181,10 +1315,10 @@ static void ui_do_drag(const bContext *C, const wmEvent *event, Panel *panel)
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;
@@ -1194,11 +1328,11 @@ static void ui_do_drag(const bContext *C, const wmEvent *event, Panel *panel)
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);
}
@@ -1371,6 +1505,8 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
#else
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;
@@ -1388,9 +1524,9 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
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;
@@ -1411,7 +1547,7 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
else if (mx < rect_leftmost) {
button = 1;
}
-
+
if (button) {
if (button == 2) { /* close */
ED_region_tag_redraw(ar);
@@ -1427,7 +1563,7 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
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)
+ if (block->panel->snap & PNL_SNAP_BOTTOM)
block->panel->ofsy = 0;
if (event == LEFTMOUSE) {
@@ -1444,14 +1580,14 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
else {
/* snap down to bottom screen edge */
block->panel->flag |= PNL_CLOSEDY;
- if (block->panel->snap & PNL_SNAP_BOTTOM)
+ 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;
@@ -1465,7 +1601,11 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
else
ED_region_tag_redraw(ar);
}
- else if (BLI_rctf_isect_x(&rect_drag, mx)) {
+ 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)) {
@@ -1820,14 +1960,14 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
/* begin drawing */
- glEnable(GL_LINE_SMOOTH);
+ GPU_line_smooth(true);
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* draw the background */
if (is_alpha) {
- glEnable(GL_BLEND);
+ GPU_blend(true);
immUniformColor4ubv(theme_col_tab_bg);
}
else {
@@ -1837,7 +1977,7 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
immRecti(pos, v2d->mask.xmin, v2d->mask.ymin, v2d->mask.xmin + category_tabs_width, v2d->mask.ymax);
if (is_alpha) {
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
immUnbindProgram();
@@ -1858,7 +1998,7 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
}
#endif
- glEnable(GL_BLEND);
+ GPU_blend(true);
#ifdef USE_FLAT_INACTIVE
if (is_active)
@@ -1908,7 +2048,7 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
/* main tab title */
BLF_draw(fontid, category_id_draw, category_draw_len);
- glDisable(GL_BLEND);
+ GPU_blend(false);
/* tab blackline remaining (last tab) */
pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
@@ -1946,7 +2086,7 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
pc_dyn->rect.xmin = v2d->mask.xmin;
}
- glDisable(GL_LINE_SMOOTH);
+ GPU_line_smooth(false);
BLF_disable(fontid, BLF_ROTATION);
@@ -2068,27 +2208,27 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar, cons
/* 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_but_is_active(ar))
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) {
@@ -2100,7 +2240,7 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar, cons
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;
@@ -2115,7 +2255,7 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar, cons
}
else if (event->type == RIGHTMOUSE) {
if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) {
- ui_panel_menu(C, ar, block->panel);
+ ui_popup_context_menu_for_panel(C, ar, block->panel);
retval = WM_UI_HANDLER_BREAK;
break;
}
@@ -2133,7 +2273,7 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar, cons
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)
@@ -2175,7 +2315,7 @@ static int ui_handler_panel(bContext *C, const wmEvent *event, void *userdata)
uiHandlePanelData *data = panel->activedata;
/* verify if we can stop */
- if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
+ 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);
@@ -2216,7 +2356,7 @@ static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelStat
uiHandlePanelData *data = pa->activedata;
wmWindow *win = CTX_wm_window(C);
ARegion *ar = CTX_wm_region(C);
-
+
if (data && data->state == state)
return;
@@ -2272,3 +2412,14 @@ static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelStat
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;
+}
diff --git a/source/blender/editors/interface/interface_query.c b/source/blender/editors/interface/interface_query.c
new file mode 100644
index 00000000000..bdd2de05ab4
--- /dev/null
+++ b/source/blender/editors/interface/interface_query.c
@@ -0,0 +1,125 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/interface/interface_query.c
+ * \ingroup edinterface
+ *
+ * Utilities to inspect the interface, extract information.
+ */
+
+#include "BLI_utildefines.h"
+
+#include "DNA_screen_types.h"
+
+#include "UI_interface.h"
+
+#include "interface_intern.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Button (uiBut)
+ * \{ */
+
+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);
+}
+
+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);
+
+}
+
+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
+ );
+}
+
+#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)
+ );
+}
+#endif
+
+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_name", false);
+ }
+ if (but->optype == ot) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Block (uiBlock)
+ * \{ */
+
+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));
+}
+
+bool ui_block_is_pie_menu(const uiBlock *block)
+{
+ return ((block->flag & UI_BLOCK_RADIAL) != 0);
+}
+
+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;
+}
+
+/** \} */
diff --git a/source/blender/editors/interface/interface_region_color_picker.c b/source/blender/editors/interface/interface_region_color_picker.c
index 4309e913d9e..00462b456ea 100644
--- a/source/blender/editors/interface/interface_region_color_picker.c
+++ b/source/blender/editors/interface/interface_region_color_picker.c
@@ -585,7 +585,7 @@ static int ui_colorpicker_small_wheel_cb(const bContext *UNUSED(C), uiBlock *blo
ui_rgb_to_color_picker_compat_v(rgb, hsv);
- hsv[2] = CLAMPIS(hsv[2] + add, 0.0f, 1.0f);
+ hsv[2] = clamp_f(hsv[2] + add, 0.0f, 1.0f);
ui_color_picker_to_rgb_v(hsv, rgb);
if (use_display_colorspace)
diff --git a/source/blender/editors/interface/interface_region_hud.c b/source/blender/editors/interface/interface_region_hud.c
new file mode 100644
index 00000000000..3ac9932fdc9
--- /dev/null
+++ b/source/blender/editors/interface/interface_region_hud.c
@@ -0,0 +1,339 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/interface/interface_region_hud.c
+ * \ingroup edinterface
+ *
+ * Floating Persistent Region
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_userdef_types.h"
+
+#include "BLI_string.h"
+#include "BLI_rect.h"
+#include "BLI_listbase.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_screen.h"
+#include "BKE_main.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+
+#include "BIF_gl.h"
+
+#include "UI_interface.h"
+#include "UI_view2d.h"
+
+#include "BLT_translation.h"
+
+#include "ED_screen.h"
+#include "ED_undo.h"
+
+#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;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Redo Panel
+ * \{ */
+
+static int hud_panel_operator_redo_poll(const bContext *C, PanelType *UNUSED(pt))
+{
+ 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));
+}
+
+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);
+}
+
+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;
+ BLI_addtail(&art->paneltypes, pt);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Callbacks for Floating Region
+ * \{ */
+
+struct HudRegionData {
+ 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;
+}
+
+static void hud_region_free(ARegion *ar)
+{
+ 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);
+ ar->flag |= RGN_FLAG_HIDDEN;
+ return;
+ }
+
+ int size_y = ar->sizey;
+
+ ED_region_panels_layout(C, ar);
+
+ if (ar->panels.first && (ar->sizey != size_y)) {
+ View2D *v2d = &ar->v2d;
+ ar->winx = ar->sizex;
+ ar->winy = ar->sizey;
+
+ 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);
+ }
+
+ /* 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) {
+ float color[4];
+ UI_GetThemeColor4fv(TH_BUTBACK, color);
+ if ((U.uiflag2 & USER_REGION_OVERLAP) == 0) {
+ color[3] = 1.0f;
+ }
+ ui_draw_widget_back_color(UI_WTYPE_BOX, false, &(rcti){.xmax = ar->winx, .ymax = ar->winy}, color);
+ 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;
+}
+
+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;
+}
+
+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) {
+ ar->flag |= RGN_FLAG_HIDDEN;
+ 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;
+ }
+
+ bool init = false;
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_HUD);
+ if (!last_redo_poll(C)) {
+ if (ar) {
+ ED_region_tag_redraw(ar);
+ ar->flag |= RGN_FLAG_HIDDEN;
+ }
+ return;
+ }
+
+ if (ar == NULL) {
+ init = true;
+ ar = hud_region_add(sa);
+ ar->type = art;
+ }
+
+ 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;
+
+ /* 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;
+ }
+ }
+
+ /* XXX, should be handled in more general way. */
+ ar->visible = !((ar->flag & RGN_FLAG_HIDDEN) || (ar->flag & RGN_FLAG_TOO_SMALL));
+
+ /* We shouldn't need to do this every time :S */
+ /* XXX, this is evil! - it also makes the menu show on first draw. :( */
+ ARegion *ar_prev = CTX_wm_region(C);
+ CTX_wm_region_set((bContext *)C, ar);
+ hud_region_layout(C, ar);
+ CTX_wm_region_set((bContext *)C, ar_prev);
+}
+
+/** \} */
diff --git a/source/blender/editors/interface/interface_region_menu_pie.c b/source/blender/editors/interface/interface_region_menu_pie.c
index 0c43b787a84..504e1807a8f 100644
--- a/source/blender/editors/interface/interface_region_menu_pie.c
+++ b/source/blender/editors/interface/interface_region_menu_pie.c
@@ -150,8 +150,16 @@ uiPieMenu *UI_pie_menu_begin(struct bContext *C, const char *title, int icon, co
}
pie->layout = UI_block_layout(pie->block_radial, UI_LAYOUT_VERTICAL, UI_LAYOUT_PIEMENU, 0, 0, 200, 0, 0, style);
- pie->mx = event->x;
- pie->my = event->y;
+
+ /* Open from where we started dragging. */
+ if (event->val == KM_CLICK_DRAG) {
+ pie->mx = event->prevclickx;
+ pie->my = event->prevclicky;
+ }
+ else {
+ pie->mx = event->x;
+ pie->my = event->y;
+ }
/* create title button */
if (title[0]) {
diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c
index a6046e551c6..b9222a75803 100644
--- a/source/blender/editors/interface/interface_region_menu_popup.c
+++ b/source/blender/editors/interface/interface_region_menu_popup.c
@@ -458,6 +458,21 @@ void UI_popup_menu_end(bContext *C, uiPopupMenu *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;
+ }
+}
+
uiLayout *UI_popup_menu_layout(uiPopupMenu *pup)
{
return pup->layout;
diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c
index 219a4fc8ed5..fb14ca745c6 100644
--- a/source/blender/editors/interface/interface_region_popover.c
+++ b/source/blender/editors/interface/interface_region_popover.c
@@ -56,6 +56,8 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
+#include "BKE_screen.h"
+#include "BKE_report.h"
#include "ED_screen.h"
@@ -77,8 +79,17 @@ struct uiPopover {
uiLayout *layout;
uiBut *but;
+ /* Needed for keymap removal. */
+ wmWindow *window;
+ wmKeyMap *keymap;
+ struct wmEventHandler *keymap_handler;
+
uiMenuCreateFunc menu_func;
void *menu_arg;
+
+#ifdef USE_UI_POPOVER_ONCE
+ bool is_once;
+#endif
};
static void ui_popover_create_block(bContext *C, uiPopover *pup, int opcontext)
@@ -124,7 +135,12 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v
UI_block_region_set(block, handle->region);
UI_block_layout_resolve(block, &width, &height);
- UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_KEEP_OPEN | UI_BLOCK_POPOVER);
+ UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_POPOVER);
+#ifdef USE_UI_POPOVER_ONCE
+ if (pup->is_once) {
+ UI_block_flag_enable(block, UI_BLOCK_POPOVER_ONCE);
+ }
+#endif
UI_block_direction_set(block, UI_DIR_DOWN | UI_DIR_CENTER_X);
const int block_margin = U.widget_unit / 2;
@@ -152,11 +168,17 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v
block->my = handle->prev_my;
}
- /* Prefer popover from header to be positioned into the editor. */
if (!slideout) {
ScrArea *sa = CTX_wm_area(C);
- if (sa && ED_area_header_alignment(sa) == RGN_ALIGN_BOTTOM) {
- ARegion *ar = CTX_wm_region(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);
+ }
+ else if (sa && ED_area_header_alignment(sa) == RGN_ALIGN_BOTTOM) {
+ /* Prefer popover from header to be positioned into the editor. */
if (ar && ar->regiontype == RGN_TYPE_HEADER) {
UI_block_direction_set(block, UI_DIR_UP | UI_DIR_CENTER_X);
}
@@ -169,10 +191,26 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v
}
else {
/* Not attached to a button. */
- int offset[2] = {0, 0}; /* Dummy. */
+ int offset[2] = {0, 0};
UI_block_flag_enable(block, UI_BLOCK_LOOP);
UI_block_direction_set(block, block->direction);
block->minbounds = UI_MENU_WIDTH_MIN;
+ bool use_place_under_active = !handle->refresh;
+
+ if (use_place_under_active) {
+ uiBut *but = NULL;
+ for (but = block->buttons.first; but; but = but->next) {
+ if (but->flag & (UI_SELECT | UI_SELECT_DRAW)) {
+ break;
+ }
+ }
+
+ if (but) {
+ offset[0] = -(but->rect.xmin + 0.8f * BLI_rctf_size_x(&but->rect));
+ offset[1] = -(but->rect.ymin + 0.5f * BLI_rctf_size_y(&but->rect));
+ }
+ }
+
UI_block_bounds_set_popup(block, block_margin, offset[0], offset[1]);
}
@@ -182,6 +220,10 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v
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);
}
@@ -195,6 +237,10 @@ uiPopupBlockHandle *ui_popover_panel_create(
pup->menu_func = menu_func;
pup->menu_arg = arg;
+#ifdef USE_UI_POPOVER_ONCE
+ pup->is_once = true;
+#endif
+
/* Create popup block. */
uiPopupBlockHandle *handle;
handle = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPOVER, pup);
@@ -216,6 +262,44 @@ uiPopupBlockHandle *ui_popover_panel_create(
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Standard Popover Panels
+ * \{ */
+
+int UI_popover_panel_invoke(
+ bContext *C, int space_id, int region_id, const char *idname,
+ bool keep_open, ReportList *reports)
+{
+ uiLayout *layout;
+ PanelType *pt = UI_paneltype_find(space_id, region_id, idname);
+ if (pt == NULL) {
+ BKE_reportf(
+ reports, RPT_ERROR,
+ "Panel \"%s\" not found (space %d, region %d)",
+ idname, space_id, region_id);
+ 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);
+ }
+
+ if (keep_open) {
+ ui_popover_panel_create(C, NULL, NULL, ui_item_paneltype_func, pt);
+ }
+ else {
+ uiPopover *pup = UI_popover_begin(C);
+ layout = UI_popover_layout(pup);
+ UI_paneltype_draw(C, pt, layout);
+ UI_popover_end(C, pup, NULL);
+ }
+
+ return OPERATOR_INTERFACE;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Popup Menu API with begin & end
* \{ */
@@ -235,21 +319,51 @@ uiPopover *UI_popover_begin(bContext *C)
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;
+}
+
/* set the whole structure to work */
-void UI_popover_end(bContext *C, uiPopover *pup)
+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_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. */
- wmWindow *window = CTX_wm_window(C);
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)
@@ -257,8 +371,11 @@ uiLayout *UI_popover_layout(uiPopover *pup)
return pup->layout;
}
-/** \} */
+#ifdef USE_UI_POPOVER_ONCE
+void UI_popover_once_clear(uiPopover *pup)
+{
+ pup->is_once = false;
+}
+#endif
-/* We may want to support this in future */
-/* Similar to UI_popup_menu_invoke */
-// int UI_popover_panel_invoke(bContext *C, const char *idname, ReportList *reports);
+/** \} */
diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c
index e971edb95cb..0ac4d4d28ec 100644
--- a/source/blender/editors/interface/interface_region_popup.c
+++ b/source/blender/editors/interface/interface_region_popup.c
@@ -63,13 +63,13 @@
/**
* Translate any popup regions (so we can drag them).
*/
-void ui_popup_translate(bContext *C, ARegion *ar, const int mdiff[2])
+void ui_popup_translate(ARegion *ar, const int mdiff[2])
{
uiBlock *block;
BLI_rcti_translate(&ar->winrct, UNPACK2(mdiff));
- ED_region_update_rect(C, ar);
+ ED_region_update_rect(ar);
ED_region_tag_redraw(ar);
@@ -560,7 +560,7 @@ uiBlock *ui_popup_block_refresh(
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);
+ UI_block_translate(block, x_offset, y_offset);
if (U.pie_initial_timeout > 0)
block->pie_data.flags |= UI_PIE_INITIAL_DIRECTION;
@@ -590,7 +590,7 @@ uiBlock *ui_popup_block_refresh(
* 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);
+ UI_block_translate(block, 0, offset);
block->rect.ymin = handle->prev_block_rect.ymin;
}
@@ -604,7 +604,15 @@ uiBlock *ui_popup_block_refresh(
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);
+ 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) {
@@ -617,7 +625,7 @@ uiBlock *ui_popup_block_refresh(
ui_popup_block_scrolltest(block);
/* adds subwindow */
- ED_region_init(C, ar);
+ ED_region_init(ar);
/* get winmat now that we actually have the subwindow */
wmGetProjectionMatrix(block->winmat, &ar->winrct);
@@ -625,7 +633,7 @@ uiBlock *ui_popup_block_refresh(
/* notify change and redraw */
ED_region_tag_redraw(ar);
- ED_region_update_rect(C, ar);
+ ED_region_update_rect(ar);
#ifdef DEBUG
window->eventstate = event_back;
@@ -696,6 +704,21 @@ uiPopupBlockHandle *ui_popup_block_create(
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);
}
diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c
index f14f9af8785..257455be27e 100644
--- a/source/blender/editors/interface/interface_region_search.c
+++ b/source/blender/editors/interface/interface_region_search.c
@@ -64,6 +64,7 @@
#include "interface_intern.h"
#include "interface_regions_intern.h"
+#include "GPU_state.h"
#define MENU_BORDER (int)(0.3f * U.widget_unit)
@@ -404,8 +405,9 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *ar)
/* pixel space */
wmOrtho2_region_pixelspace(ar);
- if (data->noback == false)
- ui_draw_search_back(NULL, NULL, &data->bbox); /* style not used yet */
+ if (data->noback == false) {
+ ui_draw_widget_back(UI_WTYPE_BOX, true, &data->bbox);
+ }
/* draw text */
if (data->items.totitem) {
@@ -428,15 +430,15 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *ar)
/* indicate more */
if (data->items.more) {
ui_searchbox_butrect(&rect, data, data->items.maxitem - 1);
- glEnable(GL_BLEND);
+ GPU_blend(true);
UI_icon_draw(rect.xmax - 18, rect.ymin - 7, ICON_TRIA_DOWN);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
if (data->items.offset) {
ui_searchbox_butrect(&rect, data, 0);
- glEnable(GL_BLEND);
+ GPU_blend(true);
UI_icon_draw(rect.xmin, rect.ymax - 9, ICON_TRIA_UP);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
}
@@ -453,15 +455,15 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *ar)
/* indicate more */
if (data->items.more) {
ui_searchbox_butrect(&rect, data, data->items.maxitem - 1);
- glEnable(GL_BLEND);
+ GPU_blend(true);
UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymin - 9, ICON_TRIA_DOWN);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
if (data->items.offset) {
ui_searchbox_butrect(&rect, data, 0);
- glEnable(GL_BLEND);
+ GPU_blend(true);
UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymax - 7, ICON_TRIA_UP);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
}
}
@@ -625,7 +627,7 @@ ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiBut *but
}
/* adds subwindow */
- ED_region_init(C, ar);
+ ED_region_init(ar);
/* notify change and redraw */
ED_region_tag_redraw(ar);
@@ -681,8 +683,9 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe
/* pixel space */
wmOrtho2_region_pixelspace(ar);
- if (data->noback == false)
- ui_draw_search_back(NULL, NULL, &data->bbox); /* style not used yet */
+ if (data->noback == false) {
+ ui_draw_widget_back(UI_WTYPE_BOX, true, &data->bbox);
+ }
/* draw text */
if (data->items.totitem) {
@@ -730,15 +733,15 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe
/* indicate more */
if (data->items.more) {
ui_searchbox_butrect(&rect, data, data->items.maxitem - 1);
- glEnable(GL_BLEND);
+ GPU_blend(true);
UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymin - 9, ICON_TRIA_DOWN);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
if (data->items.offset) {
ui_searchbox_butrect(&rect, data, 0);
- glEnable(GL_BLEND);
+ GPU_blend(true);
UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymax - 7, ICON_TRIA_UP);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
}
}
diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c
index 3a1c0e7c06e..ed83a715c7e 100644
--- a/source/blender/editors/interface/interface_region_tooltip.c
+++ b/source/blender/editors/interface/interface_region_tooltip.c
@@ -513,7 +513,7 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
WM_operator_pystring_abbreviate(str, 32);
/* operator info */
- if ((U.flag & USER_TOOLTIPS_PYTHON) == 0) {
+ if (U.flag & USER_TOOLTIPS_PYTHON) {
uiTooltipField *field = text_field_add(
data, &(uiTooltipFormat){
.style = UI_TIP_STYLE_MONO,
@@ -551,7 +551,7 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
}
}
- if ((U.flag & USER_TOOLTIPS_PYTHON) == 0 && !but->optype && rna_struct.strinfo) {
+ if ((U.flag & USER_TOOLTIPS_PYTHON) && !but->optype && rna_struct.strinfo) {
{
uiTooltipField *field = text_field_add(
data, &(uiTooltipFormat){
@@ -867,7 +867,7 @@ static ARegion *ui_tooltip_create_with_data(
}
/* adds subwindow */
- ED_region_init(C, ar);
+ ED_region_init(ar);
/* notify change and redraw */
ED_region_tag_redraw(ar);
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index fa25a119ada..0decc937e19 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -17,7 +17,7 @@
*
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index 01456e2e122..36ad516bf7f 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -17,7 +17,7 @@
*
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -65,10 +65,10 @@
/* style + theme + layout-engine = UI */
/**
- * This is a complete set of layout rules, the 'state' of the Layout
- * Engine. Multiple styles are possible, defined via C or Python. Styles
- * get a name, and will typically get activated per region type, like
- * "Header", or "Listview" or "Toolbar". Properties of Style definitions
+ * This is a complete set of layout rules, the 'state' of the Layout
+ * Engine. Multiple styles are possible, defined via C or Python. Styles
+ * get a name, and will typically get activated per region type, like
+ * "Header", or "Listview" or "Toolbar". Properties of Style definitions
* are:
*
* - default column properties, internal spacing, aligning, min/max width
@@ -85,10 +85,10 @@
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;
@@ -129,14 +129,14 @@ static uiStyle *ui_style_new(ListBase *styles, const char *name, short uifont_id
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;
@@ -154,7 +154,7 @@ void UI_fontstyle_draw_ex(
{
int xofs = 0, yofs;
int font_flag = BLF_CLIPPING;
-
+
UI_fontstyle_set(fs);
/* set the flag */
@@ -192,7 +192,7 @@ void UI_fontstyle_draw_ex(
else if (fs->align == UI_STYLE_TEXT_RIGHT) {
xofs = BLI_rcti_size_x(rect) - BLF_width(fs->uifont_id, str, len) - 0.1f * U.widget_unit;
}
-
+
/* clip is very strict, so we give it some space */
BLF_clipping(fs->uifont_id, rect->xmin - 2, rect->ymin - 4, rect->xmax + 1, rect->ymax + 4);
BLF_position(fs->uifont_id, rect->xmin + xofs, rect->ymin + yofs, 0.0f);
@@ -349,16 +349,16 @@ 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);
@@ -366,23 +366,23 @@ uiStyle *UI_style_get_dpi(void)
_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;
-
+
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);
-
+
if (fs->kerning == 1)
BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
-
+
return width;
}
@@ -403,12 +403,12 @@ void uiStyleInit(void)
uiStyle *style = U.uistyles.first;
int monofont_size = datatoc_bmonofont_ttf_size;
unsigned char *monofont_ttf = (unsigned char *)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);
}
@@ -439,9 +439,9 @@ void uiStyleInit(void)
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;
@@ -493,11 +493,11 @@ void uiStyleInit(void)
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) {
@@ -521,7 +521,7 @@ void uiStyleInit(void)
}
BLF_size(blf_mono_font, 12 * U.pixelsize, 72);
-
+
/**
* Second for rendering else we get threading problems,
*
@@ -537,7 +537,6 @@ void uiStyleInit(void)
void UI_fontstyle_set(const uiFontStyle *fs)
{
uiFont *font = uifont_to_blfont(fs->uifont_id);
-
+
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 3c53b4f411b..53a59a12b89 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -608,7 +608,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
PointerRNA idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
ID *id = idptr.data;
int event = GET_INT_FROM_POINTER(arg_event);
-
+
switch (event) {
case UI_ID_BROWSE:
case UI_ID_PIN:
@@ -682,6 +682,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ED_object_single_user(bmain, scene, (struct Object *)id);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
DEG_relations_tag_update(bmain);
}
@@ -909,14 +910,14 @@ static void template_ID(
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))) {
uiDefButR(block, UI_BTYPE_TOGGLE, 0, "F", 0, 0, UI_UNIT_X, UI_UNIT_Y, &idptr, "use_fake_user", -1, 0, 0, -1, -1, NULL);
}
}
-
+
if (flag & UI_ID_ADD_NEW) {
template_id_def_new_but(block, id, template_ui, type, newop, editable, flag & UI_ID_OPEN, false, UI_UNIT_X);
}
@@ -927,14 +928,14 @@ static void template_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_FILESEL, (id) ? "" : IFACE_("Open"),
0, 0, w, UI_UNIT_Y, NULL);
@@ -949,7 +950,7 @@ static void template_ID(
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)) {
@@ -1135,7 +1136,7 @@ void uiTemplateAnyID(
{
PropertyRNA *propID, *propType;
uiLayout *split, *row, *sub;
-
+
/* get properties... */
propID = RNA_struct_find_property(ptr, propname);
propType = RNA_struct_find_property(ptr, proptypename);
@@ -1148,13 +1149,13 @@ void uiTemplateAnyID(
RNA_warning("pointer-type property not found: %s.%s", RNA_struct_identifier(ptr->type), proptypename);
return;
}
-
+
/* Start drawing UI Elements using standard defines */
split = uiLayoutSplit(layout, 0.33f, false); /* NOTE: split amount here needs to be synced with normal labels */
-
+
/* FIRST PART ................................................ */
row = uiLayoutRow(split, false);
-
+
/* Label - either use the provided text, or will become "ID-Block:" */
if (text) {
if (text[0])
@@ -1163,20 +1164,20 @@ void uiTemplateAnyID(
else {
uiItemL(row, IFACE_("ID-Block:"), ICON_NONE);
}
-
+
/* SECOND PART ................................................ */
row = uiLayoutRow(split, true);
-
+
/* ID-Type Selector - just have a menu of icons */
sub = uiLayoutRow(row, true); /* HACK: special group just for the enum, otherwise we */
uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT); /* we get ugly layout with text included too... */
-
+
uiItemFullR(sub, ptr, propType, 0, 0, UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
-
+
/* ID-Block Selector - just use pointer widget... */
sub = uiLayoutRow(row, true); /* HACK: special group to counteract the effects of the previous */
uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_EXPAND); /* enum, which now pushes everything too far right */
-
+
uiItemFullR(sub, ptr, propID, 0, 0, 0, "", ICON_NONE);
}
@@ -1398,20 +1399,20 @@ void uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const char *propna
{
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;
}
-
+
/* Start drawing UI Elements using standard defines */
row = uiLayoutRow(layout, true);
-
+
/* 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 */
}
@@ -1429,7 +1430,7 @@ static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v)
nmd->mode &= ~eModifierMode_Virtual;
BLI_addhead(&ob->modifiers, nmd);
-
+
modifier_unique_name(&ob->modifiers, nmd);
ob->partype = PAROBJECT;
@@ -1489,7 +1490,7 @@ static uiLayout *draw_modifier(
/* rounded header ------------------------------------------------------------------- */
box = uiLayoutBox(column);
-
+
if (isVirtual) {
row = uiLayoutRow(box, false);
uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_EXPAND);
@@ -1498,7 +1499,7 @@ static uiLayout *draw_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);
@@ -1507,23 +1508,22 @@ static uiLayout *draw_modifier(
/* 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 */
- md->scene = scene;
- if (mti->isDisabled && mti->isDisabled(md, 0)) {
+ 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! */
@@ -1532,7 +1532,7 @@ static uiLayout *draw_modifier(
{
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)) {
@@ -1568,13 +1568,13 @@ static uiLayout *draw_modifier(
}
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) &&
@@ -1591,20 +1591,20 @@ static uiLayout *draw_modifier(
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,
@@ -1618,17 +1618,17 @@ static uiLayout *draw_modifier(
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))
{
@@ -1636,19 +1636,19 @@ static uiLayout *draw_modifier(
"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;
}
@@ -1673,9 +1673,9 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
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);
@@ -1740,12 +1740,16 @@ void uiTemplateOperatorRedoProperties(uiLayout *layout, const bContext *C)
#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 0
bool has_advanced = false;
#endif
UI_block_func_set(block, ED_undo_operator_repeat_cb, op, NULL);
- template_operator_redo_property_buts_draw(C, op, layout, UI_TEMPLATE_OP_PROPS_COMPACT, NULL /* &has_advanced */ );
+ template_operator_redo_property_buts_draw(C, op, layout, layout_flags, NULL /* &has_advanced */ );
UI_block_func_set(block, NULL, NULL, NULL); /* may want to reset to old state instead of NULLing all */
#if 0
@@ -1792,7 +1796,7 @@ static void do_constraint_panels(bContext *C, void *ob_pt, int event)
*
* object_test_constraints(ob);
* if (ob->pose) BKE_pose_update_constraint_flags(ob->pose); */
-
+
if (ob->type == OB_ARMATURE) DEG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB);
else DEG_id_tag_update(&ob->id, OB_RECALC_OB);
@@ -1824,7 +1828,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
}
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;
@@ -1858,34 +1862,34 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
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, B_CONSTRAINT_TEST, ICON_GHOST, 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, B_CONSTRAINT_TEST, 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:
+
+ /* 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.
+ * it may cause this situation.
*
* Up/Down buttons should only be shown (or not grayed - todo) if they serve some purpose.
*/
@@ -1898,29 +1902,29 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
}
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_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF);
+ (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");
@@ -1965,7 +1969,7 @@ uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr)
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! */
@@ -2084,7 +2088,7 @@ void uiTemplatePreview(
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);
@@ -2096,7 +2100,7 @@ void uiTemplatePreview(
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, "");
@@ -2118,7 +2122,7 @@ void uiTemplatePreview(
}
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);
@@ -2342,6 +2346,19 @@ void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname
MEM_freeN(cb);
}
+/********************* Icon Template ************************/
+/**
+ * \param icon_scale: Scale of the icon, 1x == button height.
+ */
+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);
+}
/********************* Icon viewer Template ************************/
typedef struct IconViewMenuArgs {
@@ -2400,7 +2417,7 @@ static uiBlock *ui_icon_view_menu_cb(bContext *C, ARegion *ar, void *arg_litem)
if (free) {
MEM_freeN((void *)item);
}
-
+
return block;
}
@@ -2428,13 +2445,20 @@ void uiTemplateIconView(uiLayout *layout, PointerRNA *ptr, const char *propname,
value = RNA_property_enum_get(ptr, prop);
RNA_enum_icon_from_value(items, value, &icon);
- 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;
- but = uiDefBlockButN(block, ui_icon_view_menu_cb, cb_args, "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, "");
+ 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;
+
+ but = uiDefBlockButN(block, ui_icon_view_menu_cb, cb_args, "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, "");
+ }
+ else {
+ but = uiDefIconBut(block, UI_BTYPE_LABEL, 0, ICON_X, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, NULL, 0.0, 0.0, 0.0, 0.0, "");
+ }
+
ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
@@ -2578,26 +2602,26 @@ static void curvemap_buttons_zoom_out(bContext *C, void *cumap_v, void *UNUSED(u
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->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->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->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->flag & CUMA_DO_CLIP)
if (cumap->curr.ymax + d > cumap->clipr.ymax)
d1 = -cumap->curr.ymax + cumap->clipr.ymax;
cumap->curr.ymax += d1;
@@ -2611,7 +2635,7 @@ static void curvemap_buttons_setclip(bContext *UNUSED(C), void *cumap_v, void *U
CurveMapping *cumap = cumap_v;
curvemapping_changed(cumap, false);
-}
+}
static void curvemap_buttons_delete(bContext *C, void *cb_v, void *cumap_v)
{
@@ -2784,15 +2808,15 @@ static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v)
{
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->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);
rna_update_cb(C, cb_v, NULL);
@@ -2862,7 +2886,7 @@ static void curvemap_buttons_layout(
/* 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);
@@ -2878,7 +2902,7 @@ static void curvemap_buttons_layout(
}
else
uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
-
+
if (labeltype == 'h')
bg = UI_GRAD_H;
@@ -3068,7 +3092,7 @@ void uiTemplateColorPicker(
if (cubic)
but->flag |= UI_BUT_COLOR_CUBIC;
-
+
if (value_slider) {
switch (U.color_picker_type) {
case USER_CP_CIRCLE_HSL:
@@ -3167,7 +3191,7 @@ static void handle_layer_buttons(bContext *C, void *arg1, void *arg2)
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) {
@@ -3199,8 +3223,8 @@ void uiTemplateLayers(
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
+
+ /* 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
@@ -3220,12 +3244,12 @@ void uiTemplateLayers(
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;
@@ -3233,7 +3257,7 @@ void uiTemplateLayers(
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;
@@ -3243,7 +3267,7 @@ void uiTemplateLayers(
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, SET_INT_IN_POINTER(layer));
but->type = UI_BTYPE_TOGGLE;
@@ -3940,7 +3964,7 @@ void uiTemplateList(
static void operator_call_cb(bContext *C, void *UNUSED(arg1), void *arg2)
{
wmOperatorType *ot = arg2;
-
+
if (ot)
WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, NULL);
}
@@ -3989,10 +4013,10 @@ static void operator_search_cb(const bContext *C, void *UNUSED(arg), const char
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(
@@ -4002,7 +4026,7 @@ static void operator_search_cb(const bContext *C, void *UNUSED(arg), const char
name[len] = UI_SEP_CHAR;
}
}
-
+
if (false == UI_search_item_add(items, name, ot, 0))
break;
}
@@ -4022,7 +4046,7 @@ void uiTemplateOperatorSearch(uiLayout *layout)
uiBlock *block;
uiBut *but;
static char search[256] = "";
-
+
block = uiLayoutGetBlock(layout);
UI_block_layout_set_current(block, layout);
@@ -4082,7 +4106,7 @@ eAutoPropButsReturn uiTemplateOperatorPropertyButs(
block->ui_operator = op;
row = uiLayoutRow(layout, true);
- uiItemM(row, (bContext *)C, "WM_MT_operator_presets", NULL, ICON_NONE);
+ 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_ZOOMIN, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
@@ -4107,6 +4131,8 @@ eAutoPropButsReturn uiTemplateOperatorPropertyButs(
RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
+ uiLayoutSetPropSep(layout, true);
+
/* main draw call */
return_info = uiDefAutoButsRNA(layout, &ptr, check_prop, label_align, (flag & UI_TEMPLATE_OP_PROPS_COMPACT));
@@ -4132,7 +4158,9 @@ eAutoPropButsReturn uiTemplateOperatorPropertyButs(
#endif
/* set various special settings for buttons */
- {
+
+ /* Only do this if we're not refreshing an existing UI. */
+ if (block->oldblock == NULL) {
const bool is_popup = (block->flag & UI_BLOCK_KEEP_OPEN) != 0;
uiBut *but;
@@ -4235,7 +4263,7 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
uiBlock *block;
void *owner = NULL;
int handle_event, icon = 0;
-
+
block = uiLayoutGetBlock(layout);
UI_block_layout_set_current(block, layout);
@@ -4319,7 +4347,7 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
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);
@@ -4356,9 +4384,6 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop this job"));
}
- if (WM_jobs_test(wm, screen, WM_JOB_TYPE_SCREENCAST))
- uiDefIconTextBut(block, UI_BTYPE_BUT, B_STOPCAST, ICON_CANCEL, IFACE_("Capture"), 0, 0, UI_UNIT_X * 4.25f, UI_UNIT_Y,
- NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop screencast"));
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"));
@@ -4371,48 +4396,48 @@ 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);
-
+
/* 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 + 10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
+ 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 */
rgb_float_to_uchar(but->col, rti->col);
but->col[3] = 255;
- but = uiDefBut(block, UI_BTYPE_ROUNDBOX, 0, "", UI_UNIT_X + 10, 0, UI_UNIT_X + width, UI_UNIT_Y,
+ 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, "");
- but->col[0] = but->col[1] = but->col[2] = unit_float_to_uchar_clamp(rti->grayscale);
- but->col[3] = 255;
UI_block_align_end(block);
-
-
+
+ UI_GetThemeColorShade3ubv(TH_BACK, 20, but->col);
+ but->col[3] = 255;
+
/* 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
+
+ /* 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);
@@ -4424,11 +4449,45 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
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 + 10, 0, UI_UNIT_X + width, UI_UNIT_Y,
+
+ 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;
+ }
+
+ /* 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);
+
+ uiItemL(row, msg ? msg : "", (ICON_MOUSE_LMB + i));
+
+ if (msg_drag) {
+ uiItemL(row, msg_drag, ICON_MOUSE_DRAG);
+ }
+
+ /* 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))
@@ -4445,7 +4504,7 @@ static void template_keymap_item_properties(uiLayout *layout, const char *title,
if (title)
uiItemL(layout, title, ICON_NONE);
-
+
flow = uiLayoutColumnFlow(layout, 2, false);
RNA_STRUCT_BEGIN (ptr, prop)
@@ -4575,17 +4634,17 @@ 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;
}
void uiTemplateComponentMenu(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *name)
@@ -4593,10 +4652,10 @@ void uiTemplateComponentMenu(uiLayout *layout, PointerRNA *ptr, const char *prop
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));
-
+
block = uiLayoutGetBlock(layout);
UI_block_align_begin(block);
@@ -4605,7 +4664,7 @@ void uiTemplateComponentMenu(uiLayout *layout, PointerRNA *ptr, const char *prop
but->rnapoin = *ptr;
but->rnaprop = RNA_struct_find_property(ptr, propname);
but->rnaindex = 0;
-
+
UI_block_align_end(block);
}
@@ -4615,17 +4674,17 @@ void uiTemplateNodeSocket(uiLayout *layout, bContext *UNUSED(C), float *color)
{
uiBlock *block;
uiBut *but;
-
+
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);
-
+
UI_block_align_end(block);
}
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index 5841a61acc5..e049416ce07 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -17,7 +17,7 @@
*
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -71,7 +71,7 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
if (arraylen && 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)
@@ -309,7 +309,7 @@ void ui_rna_collection_search_cb(const struct bContext *C, void *arg, const char
}
-/***************************** ID Utilities *******************************/
+/***************************** ID Utilities *******************************/
int UI_icon_from_id(ID *id)
{
Object *ob;
@@ -318,7 +318,7 @@ int UI_icon_from_id(ID *id)
if (id == NULL)
return ICON_NONE;
-
+
idcode = GS(id->name);
/* exception for objects */
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 6c558bcc961..b81825eba6e 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -17,7 +17,7 @@
*
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -58,6 +58,7 @@
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#ifdef WITH_INPUT_IME
# include "WM_types.h"
@@ -106,10 +107,10 @@ typedef struct uiWidgetTrias {
unsigned int tot;
int type;
float size, center[2];
-
+
float vec[16][2];
const unsigned int (*index)[3];
-
+
} uiWidgetTrias;
/* max as used by round_box__edges */
@@ -123,9 +124,9 @@ typedef struct uiWidgetBase {
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;
-
+
uiWidgetTrias tria1;
uiWidgetTrias tria2;
@@ -134,22 +135,22 @@ typedef struct uiWidgetBase {
} uiWidgetBase;
/** uiWidgetType: for time being only for visual appearance,
- * later, a handling callback can be added too
+ * later, a handling callback can be added too
*/
typedef struct uiWidgetType {
-
+
/* pointer to theme color definition */
uiWidgetColors *wcol_theme;
uiWidgetStateColors *wcol_state;
-
+
/* converted colors for state */
uiWidgetColors wcol;
-
+
void (*state)(struct uiWidgetType *, int state);
void (*draw)(uiWidgetColors *, rcti *, int state, int roundboxalign);
void (*custom)(uiBut *, uiWidgetColors *, rcti *, int state, int roundboxalign);
void (*text)(uiFontStyle *, uiWidgetColors *, uiBut *, rcti *);
-
+
} uiWidgetType;
@@ -230,16 +231,16 @@ static const uint g_shape_preset_hold_action_face[2][3] = {{2, 0, 1}, {3, 5, 4}}
static const int tria_ofs[ROUNDBOX_TRIA_MAX] = {
[ROUNDBOX_TRIA_NONE] = 0,
[ROUNDBOX_TRIA_ARROWS] = 0,
- [ROUNDBOX_TRIA_SCROLL] = 6,
- [ROUNDBOX_TRIA_MENU] = 22,
- [ROUNDBOX_TRIA_CHECK] = 28,
- [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 34,
+ [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] = 3,
+ [ROUNDBOX_TRIA_ARROWS] = 6,
[ROUNDBOX_TRIA_SCROLL] = 16,
- [ROUNDBOX_TRIA_MENU] = 3,
+ [ROUNDBOX_TRIA_MENU] = 6,
[ROUNDBOX_TRIA_CHECK] = 6,
[ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 3,
};
@@ -296,8 +297,8 @@ static uint32_t set_tria_vertex(
int tria_type, int tria_v, int tria_id, int jit_v)
{
uint32_t *data = GWN_vertbuf_raw_step(vflag_step);
- if (ELEM(tria_type, ROUNDBOX_TRIA_ARROWS, ROUNDBOX_TRIA_MENU)) {
- tria_v += tria_id * 3;
+ 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;
@@ -308,7 +309,7 @@ static uint32_t set_tria_vertex(
static void roundbox_batch_add_tria(Gwn_VertBufRaw *vflag_step, int tria, uint32_t last_data)
{
- const int tria_num = ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW) ? 1 : 2;
+ 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++) {
@@ -335,7 +336,7 @@ Gwn_Batch *ui_batch_roundbox_widget_get(int tria)
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)) {
+ if (!ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW, ROUNDBOX_TRIA_MENU)) {
vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria2 */
}
}
@@ -509,7 +510,7 @@ void UI_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y
/* Note: This won't give back the original color. */
draw_color[3] *= 1.0f / WIDGET_AA_JITTER;
- glEnable(GL_BLEND);
+ GPU_blend(true);
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -528,7 +529,7 @@ void UI_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y
immUnbindProgram();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
void UI_draw_anti_fan(float tri_array[][2], unsigned int length, const float color[4])
@@ -538,7 +539,7 @@ void UI_draw_anti_fan(float tri_array[][2], unsigned int length, const float col
copy_v4_v4(draw_color, color);
draw_color[3] *= 2.0f / WIDGET_AA_JITTER;
- glEnable(GL_BLEND);
+ GPU_blend(true);
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -562,7 +563,7 @@ void UI_draw_anti_fan(float tri_array[][2], unsigned int length, const float col
immUnbindProgram();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
static void widget_init(uiWidgetBase *wtb)
@@ -589,9 +590,9 @@ static int round_box_shadow_edges(float (*vert)[2], const rcti *rect, float rad,
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);
@@ -599,13 +600,13 @@ static int round_box_shadow_edges(float (*vert)[2], const rcti *rect, float rad,
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++) {
@@ -619,7 +620,7 @@ static int round_box_shadow_edges(float (*vert)[2], const rcti *rect, float rad,
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];
@@ -632,7 +633,7 @@ static int round_box_shadow_edges(float (*vert)[2], const rcti *rect, float rad,
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];
@@ -645,7 +646,7 @@ static int round_box_shadow_edges(float (*vert)[2], const rcti *rect, float rad,
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];
@@ -680,7 +681,7 @@ static void round_box__edges(uiWidgetBase *wt, int roundboxalign, const rcti *re
minsize = min_ii(BLI_rcti_size_x(rect) * hnum,
BLI_rcti_size_y(rect) * vnum);
-
+
if (2.0f * rad > minsize)
rad = 0.5f * minsize;
@@ -705,17 +706,17 @@ static void round_box__edges(uiWidgetBase *wt, int roundboxalign, const rcti *re
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);
}
@@ -723,26 +724,26 @@ static void round_box__edges(uiWidgetBase *wt, int roundboxalign, const rcti *re
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);
}
@@ -750,28 +751,28 @@ static void round_box__edges(uiWidgetBase *wt, int roundboxalign, const rcti *re
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);
}
@@ -779,42 +780,42 @@ static void round_box__edges(uiWidgetBase *wt, int roundboxalign, const rcti *re
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->inner_uv[tot][0] = 1.0f;
wt->inner_uv[tot][1] = 1.0f;
-
+
tot++;
}
-
+
/* 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];
-
+
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);
}
-
+
}
else {
-
+
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->inner_uv[tot][0] = 0.0f;
wt->inner_uv[tot][1] = 1.0f;
-
+
tot++;
}
@@ -953,17 +954,17 @@ static void shape_preset_trias_from_rect_checkmark(uiWidgetTrias *tria, const rc
float centx, centy, size;
int a;
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);
-
+
for (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;
}
@@ -1109,11 +1110,11 @@ void UI_widgetbase_draw_cache_end(void)
BLI_assert(g_widget_base_batch.enabled == true);
g_widget_base_batch.enabled = false;
- glEnable(GL_BLEND);
+ GPU_blend(true);
UI_widgetbase_draw_cache_flush();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
static void draw_widgetbase_batch(Gwn_Batch *batch, uiWidgetBase *wtb)
@@ -1169,7 +1170,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, const uiWidgetColors *wcol)
/* For color widget. */
bool alpha_check = (wcol->alpha_check && (wcol->shaded == 0));
- glEnable(GL_BLEND);
+ GPU_blend(true);
/* backdrop non AA */
if (wtb->draw_inner) {
@@ -1213,7 +1214,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, const uiWidgetColors *wcol)
draw_widgetbase_batch(roundbox_batch, wtb);
}
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
/* *********************** text/icon ************************************** */
@@ -1256,17 +1257,17 @@ static void widget_draw_icon_ex(
{
float xs = 0.0f, ys = 0.0f;
float aspect, height;
-
+
if (but->flag & UI_BUT_ICON_PREVIEW) {
- glEnable(GL_BLEND);
+ GPU_blend(true);
widget_draw_preview(icon, alpha, rect);
- glDisable(GL_BLEND);
+ 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_size / aspect;
@@ -1287,12 +1288,12 @@ static void widget_draw_icon_ex(
alpha *= 0.5f;
}
}
-
- glEnable(GL_BLEND);
-
+
+ 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')
@@ -1330,11 +1331,11 @@ static void widget_draw_icon_ex(
if (show_menu_icon) {
xs = rect->xmax - UI_DPI_ICON_SIZE - aspect;
ys = (rect->ymin + rect->ymax - height) / 2.0f;
-
+
UI_icon_draw_aspect(xs, ys, ICON_RIGHTARROW_THIN, aspect, alpha);
}
-
- glDisable(GL_BLEND);
+
+ GPU_blend(false);
}
static void widget_draw_icon(
@@ -1420,8 +1421,8 @@ float UI_text_clip_middle_ex(
strwidth = BLF_width(fstyle->uifont_id, str, max_len);
if ((okwidth > 0.0f) && (strwidth > okwidth)) {
- /* utf8 ellipsis '...', some compilers complain */
- const char sep[] = {0xe2, 0x80, 0xa6, 0x0};
+ /* utf8 ellipsis '..', some compilers complain */
+ 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;
@@ -1500,6 +1501,8 @@ float UI_text_clip_middle_ex(
BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
}
+ BLI_assert(strwidth <= okwidth);
+
return strwidth;
}
@@ -1606,16 +1609,16 @@ static void ui_text_clip_right_label(uiFontStyle *fstyle, uiBut *but, const rcti
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
@@ -1625,10 +1628,10 @@ static void ui_text_clip_right_label(uiFontStyle *fstyle, uiBut *but, const rcti
/* 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);
@@ -1640,12 +1643,12 @@ static void ui_text_clip_right_label(uiFontStyle *fstyle, uiBut *but, const rcti
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);
@@ -1664,7 +1667,7 @@ static void ui_text_clip_right_label(uiFontStyle *fstyle, uiBut *but, const rcti
but->strwidth = strwidth;
but->drawstr[drawstr_len] = 0;
}
-
+
if (fstyle->kerning == 1)
BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
}
@@ -1726,17 +1729,17 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
#endif
UI_fontstyle_set(fstyle);
-
+
if (but->editstr || (but->drawflag & UI_BUT_TEXT_LEFT))
fstyle->align = UI_STYLE_TEXT_LEFT;
else if (but->drawflag & UI_BUT_TEXT_RIGHT)
fstyle->align = UI_STYLE_TEXT_RIGHT;
else
fstyle->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 */
@@ -1780,12 +1783,12 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
/* 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. */
- glEnable(GL_BLEND);
+ GPU_blend(true);
UI_widgetbase_draw_cache_flush();
- glDisable(GL_BLEND);
+ GPU_blend(false);
if (but->selsta >= but->ofs) {
selsta_draw = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->selsta - but->ofs);
@@ -1828,9 +1831,9 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
t = 0;
}
/* We are drawing on top of widget bases. Flush cache. */
- glEnable(GL_BLEND);
+ GPU_blend(true);
UI_widgetbase_draw_cache_flush();
- glDisable(GL_BLEND);
+ GPU_blend(false);
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -1858,7 +1861,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
}
#endif
}
-
+
if (fstyle->kerning == 1)
BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
@@ -1879,9 +1882,11 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
}
}
}
-
+
#ifdef USE_NUMBUTS_LR_ALIGN
- if (!drawstr_right && ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER) &&
+ 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))
{
@@ -1991,9 +1996,9 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
/* draw icon in rect above the space reserved for the label */
rect->ymin += text_size;
- glEnable(GL_BLEND);
+ GPU_blend(true);
widget_draw_preview(icon, alpha, rect);
- glDisable(GL_BLEND);
+ GPU_blend(false);
/* offset rect to draw label in */
rect->ymin -= text_size;
@@ -2006,11 +2011,20 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
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;
+ }
+#endif
+
const BIFIconID icon = (but->flag & UI_HAS_ICON) ? but->icon + but->iconadd : ICON_NONE;
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);
-#ifdef USE_TOOLBAR_HACK
+#ifdef USE_UI_TOOLBAR_HACK
if (is_tool) {
/* pass (even if its a menu toolbar) */
but->drawflag |= UI_BUT_TEXT_LEFT;
@@ -2032,6 +2046,10 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
widget_draw_icon(but, icon, alpha, rect, show_menu_icon);
+#ifdef USE_UI_TOOLBAR_HACK
+ but->block->aspect = aspect_orig;
+#endif
+
rect->xmin += icon_size;
/* without this menu keybindings will overlap the arrow icon [#38083] */
if (show_menu_icon) {
@@ -2099,370 +2117,6 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
/* *********************** widget types ************************************* */
-static struct uiWidgetStateColors wcol_state_colors = {
- {115, 190, 76, 255},
- {90, 166, 51, 255},
- {240, 235, 100, 255},
- {215, 211, 75, 255},
- {180, 0, 255, 255},
- {153, 0, 230, 255},
- {74, 137, 137, 255},
- {49, 112, 112, 255},
- 0.5f, 0.0f
-};
-
-static struct uiWidgetColors wcol_num = {
- {25, 25, 25, 255},
- {180, 180, 180, 255},
- {153, 153, 153, 255},
- {90, 90, 90, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 1,
- -20, 0,
- 0,
- 0.5f,
-};
-
-static struct uiWidgetColors wcol_numslider = {
- {25, 25, 25, 255},
- {180, 180, 180, 255},
- {153, 153, 153, 255},
- {128, 128, 128, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 1,
- -20, 0,
- 0,
- 0.5f,
-};
-
-static struct uiWidgetColors wcol_text = {
- {25, 25, 25, 255},
- {153, 153, 153, 255},
- {153, 153, 153, 255},
- {90, 90, 90, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 1,
- 0, 25,
- 0,
- 0.2f,
-};
-
-static struct uiWidgetColors wcol_option = {
- {0, 0, 0, 255},
- {70, 70, 70, 255},
- {70, 70, 70, 255},
- {255, 255, 255, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 1,
- 15, -15,
- 0,
- 0.3333333f,
-};
-
-/* button that shows popup */
-static struct uiWidgetColors wcol_menu = {
- {0, 0, 0, 255},
- {70, 70, 70, 255},
- {70, 70, 70, 255},
- {255, 255, 255, 255},
-
- {255, 255, 255, 255},
- {204, 204, 204, 255},
-
- 1,
- 15, -15,
- 0,
- 0.2f,
-};
-
-/* button that starts pulldown */
-static struct uiWidgetColors wcol_pulldown = {
- {0, 0, 0, 255},
- {63, 63, 63, 255},
- {86, 128, 194, 255},
- {255, 255, 255, 255},
-
- {0, 0, 0, 255},
- {0, 0, 0, 255},
-
- 0,
- 25, -20,
- 0,
- 0.2f,
-};
-
-/* button inside menu */
-static struct uiWidgetColors wcol_menu_item = {
- {0, 0, 0, 255},
- {0, 0, 0, 0},
- {86, 128, 194, 255},
- {172, 172, 172, 128},
-
- {255, 255, 255, 255},
- {0, 0, 0, 255},
-
- 1,
- 38, 0,
- 0,
- 0.2f,
-};
-
-/* backdrop menu + title text color */
-static struct uiWidgetColors wcol_menu_back = {
- {0, 0, 0, 255},
- {25, 25, 25, 230},
- {45, 45, 45, 230},
- {100, 100, 100, 255},
-
- {160, 160, 160, 255},
- {255, 255, 255, 255},
-
- 0,
- 25, -20,
- 0,
- 0.25f,
-};
-
-/* pie menus */
-static struct uiWidgetColors wcol_pie_menu = {
- {10, 10, 10, 200},
- {25, 25, 25, 230},
- {140, 140, 140, 255},
- {45, 45, 45, 230},
-
- {160, 160, 160, 255},
- {255, 255, 255, 255},
-
- 1,
- 10, -10,
- 0,
- 0.5f,
-};
-
-
-/* tooltip color */
-static struct uiWidgetColors wcol_tooltip = {
- {0, 0, 0, 255},
- {25, 25, 25, 230},
- {45, 45, 45, 230},
- {100, 100, 100, 255},
-
- {255, 255, 255, 255},
- {255, 255, 255, 255},
-
- 0,
- 25, -20,
- 0,
- 0.25f,
-};
-
-static struct uiWidgetColors wcol_radio = {
- {0, 0, 0, 255},
- {70, 70, 70, 255},
- {86, 128, 194, 255},
- {255, 255, 255, 255},
-
- {255, 255, 255, 255},
- {0, 0, 0, 255},
-
- 1,
- 15, -15,
- 0,
- 0.2f,
-};
-
-static struct uiWidgetColors wcol_regular = {
- {25, 25, 25, 255},
- {153, 153, 153, 255},
- {100, 100, 100, 255},
- {25, 25, 25, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 0,
- 0, 0,
- 0,
- 0.25f,
-};
-
-static struct uiWidgetColors wcol_tool = {
- {25, 25, 25, 255},
- {153, 153, 153, 255},
- {100, 100, 100, 255},
- {25, 25, 25, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 1,
- 15, -15,
- 0,
- 0.2f,
-};
-
-static struct uiWidgetColors wcol_toolbar_item = {
- .outline = {0x19, 0x19, 0x19, 0xff},
- .inner = {0x46, 0x46, 0x46, 0xff},
- .inner_sel = {0xcc, 0xcc, 0xcc, 0xff},
- .item = {0x0, 0x0, 0x0, 0xff},
-
- .text = {0xff, 0xff, 0xff, 0xff},
- .text_sel = {0x33, 0x33, 0x33, 0xff},
-
- .shaded = 0,
- .shadetop = 0,
- .shadedown = 0,
- .alpha_check = 0,
- .roundness = 0.3f,
-};
-
-static struct uiWidgetColors wcol_box = {
- {25, 25, 25, 255},
- {128, 128, 128, 255},
- {100, 100, 100, 255},
- {25, 25, 25, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 0,
- 0, 0,
- 0,
- 0.2f,
-};
-
-static struct uiWidgetColors wcol_toggle = {
- {25, 25, 25, 255},
- {153, 153, 153, 255},
- {100, 100, 100, 255},
- {25, 25, 25, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 0,
- 0, 0,
- 0,
- 0.25f,
-};
-
-static struct uiWidgetColors wcol_scroll = {
- {50, 50, 50, 180},
- {80, 80, 80, 180},
- {100, 100, 100, 180},
- {128, 128, 128, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 1,
- 5, -5,
- 0,
- 0.5f,
-};
-
-static struct uiWidgetColors wcol_progress = {
- {0, 0, 0, 255},
- {190, 190, 190, 255},
- {100, 100, 100, 180},
- {128, 128, 128, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 0,
- 0, 0,
- 0,
- 0.25f,
-};
-
-static struct uiWidgetColors wcol_list_item = {
- {0, 0, 0, 255},
- {0, 0, 0, 0},
- {86, 128, 194, 255},
- {90, 90, 90, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 0,
- 0, 0,
- 0,
- 0.2f,
-};
-
-struct uiWidgetColors wcol_tab = {
- {60, 60, 60, 255},
- {83, 83, 83, 255},
- {114, 114, 114, 255},
- {90, 90, 90, 255},
-
- {0, 0, 0, 255},
- {0, 0, 0, 255},
-
- 0,
- 0, 0,
- 0,
- 0.25f,
-};
-
-/* free wcol struct to play with */
-static struct uiWidgetColors wcol_tmp = {
- {0, 0, 0, 255},
- {128, 128, 128, 255},
- {100, 100, 100, 255},
- {25, 25, 25, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 0,
- 0, 0,
- 0,
- 0.25f,
-};
-
-
-/* called for theme init (new theme) and versions */
-void ui_widget_color_init(ThemeUI *tui)
-{
- tui->wcol_regular = wcol_regular;
- tui->wcol_tool = wcol_tool;
- tui->wcol_toolbar_item = wcol_toolbar_item;
- tui->wcol_text = wcol_text;
- tui->wcol_radio = wcol_radio;
- tui->wcol_tab = wcol_tab;
- tui->wcol_option = wcol_option;
- tui->wcol_toggle = wcol_toggle;
- tui->wcol_num = wcol_num;
- tui->wcol_numslider = wcol_numslider;
- tui->wcol_menu = wcol_menu;
- tui->wcol_pulldown = wcol_pulldown;
- tui->wcol_menu_back = wcol_menu_back;
- tui->wcol_pie_menu = wcol_pie_menu;
- tui->wcol_tooltip = wcol_tooltip;
- tui->wcol_menu_item = wcol_menu_item;
- tui->wcol_box = wcol_box;
- tui->wcol_scroll = wcol_scroll;
- tui->wcol_list_item = wcol_list_item;
- tui->wcol_progress = wcol_progress;
-
- tui->wcol_state = wcol_state_colors;
-}
-
/* ************ button callbacks, state ***************** */
static void widget_state_blend(char cp[3], const char cpstate[3], const float fac)
@@ -2528,7 +2182,7 @@ static void widget_state(uiWidgetType *wt, int state)
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);
}
@@ -2573,11 +2227,11 @@ static void widget_state_numslider(uiWidgetType *wt, int state)
/* call this for option button */
widget_state(wt, state);
-
+
/* 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 (state & UI_BUT_ANIMATED_KEY)
widget_state_blend(wt->wcol.item, wcol_state->inner_key_sel, blend);
else if (state & UI_BUT_ANIMATED)
@@ -2606,10 +2260,10 @@ static void widget_state_numslider(uiWidgetType *wt, int state)
static void widget_state_option_menu(uiWidgetType *wt, int state)
{
bTheme *btheme = UI_GetTheme(); /* XXX */
-
+
/* call this for option button */
widget_state(wt, state);
-
+
/* 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);
@@ -2621,18 +2275,12 @@ static void widget_state_option_menu(uiWidgetType *wt, int state)
static void widget_state_nothing(uiWidgetType *wt, int UNUSED(state))
{
wt->wcol = *(wt->wcol_theme);
-}
+}
/* special case, button that calls pulldown */
-static void widget_state_pulldown(uiWidgetType *wt, int state)
+static void widget_state_pulldown(uiWidgetType *wt, int UNUSED(state))
{
wt->wcol = *(wt->wcol_theme);
-
- copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
- copy_v3_v3_char(wt->wcol.outline, wt->wcol.inner);
-
- if (state & UI_ACTIVE)
- copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
}
/* special case, pie menu items */
@@ -2648,18 +2296,22 @@ static void widget_state_pie_menu_item(uiWidgetType *wt, int state)
copy_v4_v4_char(wt->wcol.inner, wt->wcol.item);
wt->wcol.inner[3] = 64;
}
- /* regular disabled */
- else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
- widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f);
- }
- /* regular active */
- else if (state & UI_SELECT) {
- copy_v4_v4_char(wt->wcol.outline, wt->wcol.inner_sel);
- copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
- }
- else if (state & UI_ACTIVE) {
- copy_v4_v4_char(wt->wcol.inner, wt->wcol.item);
- copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
+ 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.outline, wt->wcol.inner_sel);
+ }
+ else if (state & UI_ACTIVE) {
+ copy_v4_v4_char(wt->wcol.inner, wt->wcol.item);
+ }
}
}
@@ -2667,7 +2319,7 @@ static void widget_state_pie_menu_item(uiWidgetType *wt, int state)
static void widget_state_menu_item(uiWidgetType *wt, int state)
{
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);
@@ -2676,14 +2328,19 @@ static void widget_state_menu_item(uiWidgetType *wt, int state)
copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
wt->wcol.inner[3] = 64;
}
- /* regular disabled */
- else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
- widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f);
- }
- /* regular active */
- else if (state & UI_ACTIVE) {
- copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
- copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
+ 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);
+ }
}
}
@@ -2700,17 +2357,17 @@ static void widget_softshadow(const rcti *rect, int roundboxalign, const float r
int step, totvert;
float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2];
const float radout = UI_ThemeMenuShadowWidth();
-
+
/* 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;
-
+
/* inner part */
totvert = round_box_shadow_edges(wtb.inner_v, &rect1, radin, roundboxalign & (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT), 0.0f);
@@ -2723,9 +2380,9 @@ static void widget_softshadow(const rcti *rect, int roundboxalign, const float r
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);
-
+
immUniformColor4f(0.0f, 0.0f, 0.0f, alphastep * (1.0f - expfac));
widget_verts_to_triangle_strip(&wtb, totvert, triangle_strip);
@@ -2740,9 +2397,9 @@ static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int dir
{
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;
@@ -2756,15 +2413,15 @@ static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int dir
roundboxalign = UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT;
rect->ymax += 0.1f * U.widget_unit;
}
-
- glEnable(GL_BLEND);
+
+ 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);
-
- glDisable(GL_BLEND);
+
+ GPU_blend(false);
}
static void ui_hsv_cursor(float x, float y)
@@ -2775,13 +2432,13 @@ static void ui_hsv_cursor(float x, float y)
immUniformColor3f(1.0f, 1.0f, 1.0f);
imm_draw_circle_fill_2d(pos, x, y, 3.0f * U.pixelsize, 8);
-
- glEnable(GL_BLEND);
- glEnable(GL_LINE_SMOOTH);
+
+ 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);
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
+ GPU_blend(false);
+ GPU_line_smooth(false);
immUnbindProgram();
}
@@ -2808,15 +2465,15 @@ void ui_hsvcircle_pos_from_vals(uiBut *but, const rcti *rect, float *hsv, float
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 ((but->flag & UI_BUT_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 = CLAMPIS(radius_t, 0.0f, 1.0f) * radius;
+
+ radius = clamp_f(radius_t, 0.0f, 1.0f) * radius;
*xpos = centx + cosf(-ang) * radius;
*ypos = centy + sinf(-ang) * radius;
}
@@ -2835,7 +2492,7 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *
const float *hsv_ptr = cpicker->color_data;
float rgb[3], hsvo[3], hsv[3], col[3], colcent[3];
bool color_profile = ui_but_is_colorpicker_display_space(but);
-
+
/* color */
ui_but_v3_get(but, rgb);
@@ -2861,7 +2518,7 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *
else
hsv[2] = 0.5f;
}
-
+
ui_color_picker_to_rgb(0.0f, 0.0f, hsv[2], colcent, colcent + 1, colcent + 2);
Gwn_VertFormat *format = immVertexFormat();
@@ -2873,12 +2530,12 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *
immBegin(GWN_PRIM_TRI_FAN, tot + 2);
immAttrib3fv(color, colcent);
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);
-
+
ui_hsvcircle_vals_from_pos(hsv, hsv + 1, rect, centx + co * radius, centy + si * radius);
ui_color_picker_to_rgb_v(hsv, col);
@@ -2895,16 +2552,16 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- glEnable(GL_BLEND);
- glEnable(GL_LINE_SMOOTH);
+ GPU_blend(true);
+ GPU_line_smooth(true);
immUniformColor3ubv((unsigned char *)wcol->outline);
imm_draw_circle_wire_2d(pos, centx, centy, radius, tot);
immUnbindProgram();
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
+ GPU_blend(false);
+ GPU_line_smooth(false);
/* cursor */
float xpos, ypos;
@@ -2927,7 +2584,7 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons
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]);
@@ -2979,7 +2636,7 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
-
+
immBegin(GWN_PRIM_TRIS, steps * 3 * 6);
for (dx = 0.0f; dx < 0.999f; dx += color_step) { /* 0.999 = prevent float inaccuracy for steps */
const float dx_next = dx + color_step;
@@ -2989,7 +2646,7 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons
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:
@@ -3031,17 +2688,17 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons
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) {
immAttrib4f(col, col0[a][0], col0[a][1], col0[a][2], alpha);
immVertex2f(pos, sx1, sy);
-
+
immAttrib4f(col, col1[a][0], col1[a][1], col1[a][2], alpha);
immVertex2f(pos, sx2, sy);
@@ -3053,7 +2710,7 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons
immAttrib4f(col, col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha);
immVertex2f(pos, sx2, sy + dy);
-
+
immAttrib4f(col, col0[a + 1][0], col0[a + 1][1], col0[a + 1][2], alpha);
immVertex2f(pos, sx1, sy + dy);
}
@@ -3117,24 +2774,24 @@ static void ui_draw_but_HSVCUBE(uiBut *but, const rcti *rect)
float *hsv = cpicker->color_data;
float hsv_n[3];
bool use_display_colorspace = ui_but_is_colorpicker_display_space(but);
-
+
copy_v3_v3(hsv_n, hsv);
-
+
ui_but_v3_get(but, rgb);
-
+
if (use_display_colorspace)
ui_block_cm_to_display_space_v3(but->block, rgb);
-
+
rgb_to_hsv_compat_v(rgb, hsv_n);
-
+
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_hsv_cursor(x, y);
-
+
/* outline */
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -3153,7 +2810,7 @@ static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect)
float x, y;
float rgb[3], hsv[3], v;
bool color_profile = but->block->color_profile;
-
+
if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
color_profile = false;
@@ -3167,7 +2824,7 @@ static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect)
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;
@@ -3178,23 +2835,26 @@ static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect)
}
widget_init(&wtb);
-
+
/* fully rounded */
round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
-
+
/* setup temp colors */
- wcol_tmp.outline[0] = wcol_tmp.outline[1] = wcol_tmp.outline[2] = 0;
- wcol_tmp.inner[0] = wcol_tmp.inner[1] = wcol_tmp.inner[2] = 128;
- wcol_tmp.shadetop = 127;
- wcol_tmp.shadedown = -128;
- wcol_tmp.shaded = 1;
-
- widgetbase_draw(&wtb, &wcol_tmp);
+ 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. */
- glEnable(GL_BLEND);
+ GPU_blend(true);
UI_widgetbase_draw_cache_flush();
- glDisable(GL_BLEND);
+ GPU_blend(false);
/* cursor */
x = rect->xmin + 0.5f * BLI_rcti_size_x(rect);
@@ -3204,6 +2864,20 @@ static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect)
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);
+}
+
/* ************ separator, for menus etc ***************** */
static void ui_draw_separator(const rcti *rect, uiWidgetColors *wcol)
@@ -3219,16 +2893,16 @@ static void ui_draw_separator(const rcti *rect, uiWidgetColors *wcol)
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- glEnable(GL_BLEND);
+ GPU_blend(true);
immUniformColor4ubv(col);
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
immBegin(GWN_PRIM_LINES, 2);
immVertex2f(pos, rect->xmin, y);
immVertex2f(pos, rect->xmax, y);
immEnd();
- glDisable(GL_BLEND);
+ GPU_blend(false);
immUnbindProgram();
}
@@ -3242,9 +2916,9 @@ static void widget_numbut_draw(uiWidgetColors *wcol, rcti *rect, int state, int
if (state & UI_SELECT)
SWAP(short, wcol->shadetop, wcol->shadedown);
-
+
widget_init(&wtb);
-
+
if (!emboss) {
round_box_edges(&wtb, roundboxalign, rect, rad);
}
@@ -3324,7 +2998,7 @@ static void widget_numbut_draw(uiWidgetColors *wcol, rcti *rect, int state, int
/* inner and outline */
widgetbase_draw(&wtb, wcol);
}
-
+
if (!(state & UI_STATE_TEXT_INPUT)) {
const float textofs = 0.425f * BLI_rcti_size_y(rect);
@@ -3364,29 +3038,29 @@ void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *s
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;
@@ -3395,20 +3069,20 @@ void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *s
/* 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');
@@ -3419,7 +3093,7 @@ void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *s
}
}
widgetbase_draw(&wtb, wcol);
-
+
if (state & UI_SCROLL_NO_OUTLINE) {
SWAP(bool, outline, wtb.draw_outline);
}
@@ -3438,13 +3112,13 @@ static void widget_scroll(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
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));
@@ -3613,7 +3287,7 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
uiWidgetBase wtb;
float rad, col[4];
bool color_profile = but->block->color_profile;
-
+
col[3] = 1.0f;
if (but->rnaprop) {
@@ -3626,12 +3300,12 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
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)) {
@@ -3643,18 +3317,18 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
rect->xmax -= SWATCH_KEYED_BORDER;
rect->ymin += SWATCH_KEYED_BORDER;
rect->ymax -= SWATCH_KEYED_BORDER;
-
+
round_box_edges(&wtb, roundboxalign, rect, rad);
}
-
+
if (color_profile)
ui_block_cm_to_display_space_v3(but->block, col);
-
+
rgba_float_to_uchar((unsigned char *)wcol->inner, col);
wcol->shaded = 0;
wcol->alpha_check = (wcol->inner[3] < 255);
-
+
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
@@ -3674,9 +3348,9 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
bw += (bw < 0.5f) ? 0.5f : -0.5f;
/* We are drawing on top of widget bases. Flush cache. */
- glEnable(GL_BLEND);
+ GPU_blend(true);
UI_widgetbase_draw_cache_flush();
- glDisable(GL_BLEND);
+ GPU_blend(false);
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -3702,16 +3376,16 @@ static void widget_icon_has_anim(uiBut *but, uiWidgetColors *wcol, rcti *rect, i
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
+ /* Draw number buttons still with left/right
* triangles when field is not embossed */
widget_numbut_embossn(but, wcol, rect, state, roundboxalign);
}
@@ -3722,15 +3396,15 @@ static void widget_textbut(uiWidgetColors *wcol, rcti *rect, int state, int roun
{
uiWidgetBase wtb;
float rad;
-
+
if (state & UI_SELECT)
SWAP(short, wcol->shadetop, wcol->shadedown);
-
+
widget_init(&wtb);
-
+
rad = wcol->roundness * U.widget_unit;
round_box_edges(&wtb, roundboxalign, rect, rad);
-
+
widgetbase_draw(&wtb, wcol);
}
@@ -3739,19 +3413,19 @@ static void widget_menubut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state),
{
uiWidgetBase wtb;
float rad;
-
+
widget_init(&wtb);
-
+
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;
-
+
widgetbase_draw(&wtb, wcol);
-
+
/* text space, arrows are about 0.6 height of button */
rect->xmax -= (6 * BLI_rcti_size_y(rect)) / 10;
}
@@ -3760,12 +3434,12 @@ static void widget_menuiconbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(stat
{
uiWidgetBase wtb;
float rad;
-
+
widget_init(&wtb);
-
+
rad = wcol->roundness * U.widget_unit;
round_box_edges(&wtb, roundboxalign, rect, rad);
-
+
/* decoration */
widgetbase_draw(&wtb, wcol);
}
@@ -3776,9 +3450,9 @@ static void widget_menunodebut(uiWidgetColors *wcol, rcti *rect, int UNUSED(stat
uiWidgetBase wtb;
uiWidgetColors wcol_backup = *wcol;
float rad;
-
+
widget_init(&wtb);
-
+
rad = wcol->roundness * U.widget_unit;
round_box_edges(&wtb, roundboxalign, rect, rad);
@@ -3788,7 +3462,7 @@ static void widget_menunodebut(uiWidgetColors *wcol, rcti *rect, int UNUSED(stat
wcol->outline[0] = min_ii(wcol->outline[0] + 15, 255);
wcol->outline[1] = min_ii(wcol->outline[1] + 15, 255);
wcol->outline[2] = min_ii(wcol->outline[2] + 15, 255);
-
+
/* decoration */
widgetbase_draw(&wtb, wcol);
*wcol = wcol_backup;
@@ -3796,15 +3470,28 @@ static void widget_menunodebut(uiWidgetColors *wcol, rcti *rect, int UNUSED(stat
static void widget_pulldownbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
{
- if (state & UI_ACTIVE) {
+ 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);
}
}
@@ -3812,13 +3499,13 @@ static void widget_pulldownbut(uiWidgetColors *wcol, rcti *rect, int state, int
static void widget_menu_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
{
uiWidgetBase wtb;
-
+
widget_init(&wtb);
-
+
/* not rounded, no outline */
wtb.draw_outline = false;
round_box_edges(&wtb, 0, rect, 0.0f);
-
+
widgetbase_draw(&wtb, wcol);
}
@@ -3849,14 +3536,14 @@ static void widget_list_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(sta
{
uiWidgetBase wtb;
float rad;
-
+
widget_init(&wtb);
-
+
/* 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);
}
@@ -3866,29 +3553,29 @@ static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UN
rcti recttemp = *rect;
float rad;
int delta;
-
+
widget_init(&wtb);
-
+
/* square */
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 */
rect->xmin += BLI_rcti_size_y(rect) * 0.7 + delta;
}
@@ -3917,12 +3604,12 @@ static void widget_radiobut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state),
{
uiWidgetBase wtb;
float rad;
-
+
widget_init(&wtb);
-
+
rad = wcol->roundness * U.widget_unit;
round_box_edges(&wtb, roundboxalign, rect, rad);
-
+
widgetbase_draw(&wtb, wcol);
}
@@ -3931,23 +3618,23 @@ static void widget_box(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(
uiWidgetBase wtb;
float rad;
char old_col[3];
-
+
widget_init(&wtb);
-
+
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];
}
-
+
rad = wcol->roundness * U.widget_unit;
round_box_edges(&wtb, roundboxalign, rect, rad);
-
+
widgetbase_draw(&wtb, wcol);
-
+
copy_v3_v3_char(wcol->inner, old_col);
}
@@ -3955,12 +3642,12 @@ static void widget_but(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int
{
uiWidgetBase wtb;
float rad;
-
+
widget_init(&wtb);
-
+
rad = wcol->roundness * U.widget_unit;
round_box_edges(&wtb, roundboxalign, rect, rad);
-
+
widgetbase_draw(&wtb, wcol);
}
@@ -3969,9 +3656,9 @@ static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state),
{
uiWidgetBase wtb;
const float rad = wcol->roundness * U.widget_unit;
-
+
widget_init(&wtb);
-
+
/* half rounded */
round_box_edges(&wtb, roundboxalign, rect, rad);
@@ -4034,9 +3721,9 @@ static void widget_tab(uiWidgetColors *wcol, rcti *rect, int state, int roundbox
widgetbase_draw(&wtb, wcol);
/* We are drawing on top of widget bases. Flush cache. */
- glEnable(GL_BLEND);
+ GPU_blend(true);
UI_widgetbase_draw_cache_flush();
- glDisable(GL_BLEND);
+ GPU_blend(false);
#ifdef USE_TAB_SHADED_HIGHLIGHT
/* draw outline (3d look) */
@@ -4063,13 +3750,13 @@ static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *
/* state copy! */
wt->wcol = *(wt->wcol_theme);
-
+
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);
-
+
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -4082,7 +3769,7 @@ static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *
immUnbindProgram();
}
-
+
/* outline */
round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
wtb.draw_outline = true;
@@ -4094,7 +3781,7 @@ 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;
@@ -4102,7 +3789,7 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
wt.draw = widget_but;
wt.custom = NULL;
wt.text = widget_draw_text_icon;
-
+
switch (type) {
case UI_WTYPE_REGULAR:
break;
@@ -4111,16 +3798,16 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
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;
@@ -4130,13 +3817,13 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
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;
@@ -4146,7 +3833,7 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
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;
@@ -4156,24 +3843,24 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
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;
@@ -4184,7 +3871,7 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
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;
@@ -4194,20 +3881,20 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
wt.wcol_theme = &btheme->tui.wcol_menu;
wt.draw = widget_menunodebut;
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;
@@ -4223,19 +3910,19 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
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;
@@ -4250,7 +3937,7 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
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;
@@ -4262,7 +3949,7 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
wt.state = widget_state_pie_menu_item;
break;
}
-
+
return &wt;
}
@@ -4273,13 +3960,13 @@ static int widget_roundbox_set(uiBut *but, rcti *rect)
/* 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;
@@ -4336,6 +4023,10 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
uiFontStyle *fstyle = &style->widget;
uiWidgetType *wt = NULL;
+#ifdef USE_UI_POPOVER_ONCE
+ const rcti rect_orig = *rect;
+#endif
+
/* handle menus separately */
if (but->dt == UI_EMBOSS_PULLDOWN) {
switch (but->type) {
@@ -4383,10 +4074,11 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
case UI_BTYPE_SEPR:
case UI_BTYPE_SEPR_LINE:
+ case UI_BTYPE_SEPR_SPACER:
break;
-
+
case UI_BTYPE_BUT:
-#ifdef USE_TOOLBAR_HACK
+#ifdef USE_UI_TOOLBAR_HACK
if (UI_but_is_tool(but)) {
wt = widget_type(UI_WTYPE_TOOLBAR_ITEM);
}
@@ -4401,11 +4093,11 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
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;
@@ -4413,7 +4105,7 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
case UI_BTYPE_LISTROW:
wt = widget_type(UI_WTYPE_LISTITEM);
break;
-
+
case UI_BTYPE_TEXT:
wt = widget_type(UI_WTYPE_NAME);
break;
@@ -4433,7 +4125,7 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
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)) {
@@ -4442,13 +4134,13 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
}
else
wt = widget_type(UI_WTYPE_TOGGLE);
-
+
/* option buttons have strings outside, on menus use different colors */
if (but->block->flag & UI_BLOCK_LOOP)
wt->state = widget_state_option_menu;
-
+
break;
-
+
case UI_BTYPE_MENU:
case UI_BTYPE_BLOCK:
case UI_BTYPE_POPOVER:
@@ -4477,15 +4169,15 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
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);
@@ -4494,7 +4186,7 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
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);
@@ -4503,39 +4195,39 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
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;
@@ -4562,12 +4254,12 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
break;
}
}
-
+
if (wt) {
//rcti disablerect = *rect; /* rect gets clipped smaller for text */
int roundboxalign, state;
bool disabled = false;
-
+
roundboxalign = widget_roundbox_set(but, rect);
/* Mask out flags re-used for local state. */
@@ -4599,7 +4291,7 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE))
if (but->dt != UI_EMBOSS_PULLDOWN)
disabled = true;
-
+
if (disabled)
ui_widget_color_disabled(wt);
@@ -4610,27 +4302,38 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
wt->draw(&wt->wcol, rect, state, roundboxalign);
if (disabled)
- glEnable(GL_BLEND);
+ GPU_blend(true);
+
+#ifdef USE_UI_POPOVER_ONCE
+ if (but->block->flag & UI_BLOCK_POPOVER_ONCE) {
+ if ((state & UI_ACTIVE) && ui_but_is_popover_once_compat(but)) {
+ uiWidgetType wt_back = *wt;
+ uiWidgetType *wt_temp = widget_type(UI_WTYPE_MENU_ITEM);
+ wt_temp->state(wt_temp, state);
+ 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;
+ }
+ }
+#endif
+
wt->text(fstyle, &wt->wcol, but, rect);
if (disabled)
- glDisable(GL_BLEND);
-
+ GPU_blend(false);
+
// if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE))
// if (but->dt != UI_EMBOSS_PULLDOWN)
// widget_disabled(&disablerect);
}
}
-void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
+static void ui_draw_clip_tri(uiBlock *block, rcti *rect, uiWidgetType *wt)
{
- uiWidgetType *wt = widget_type(UI_WTYPE_MENU_BACK);
-
- wt->state(wt, 0);
- if (block)
- wt->draw(&wt->wcol, rect, block->flag, block->direction);
- else
- wt->draw(&wt->wcol, rect, 0, 0);
-
if (block) {
float draw_color[4];
unsigned char *color = (unsigned char *)wt->wcol.text;
@@ -4651,6 +4354,19 @@ void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
}
}
+void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
+{
+ uiWidgetType *wt = widget_type(UI_WTYPE_MENU_BACK);
+
+ wt->state(wt, 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);
+}
+
/**
* 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.
@@ -4665,7 +4381,7 @@ static void ui_draw_popover_back_impl(
rect->ymax -= unit_half;
rect->ymin += unit_half;
- glEnable(GL_BLEND);
+ GPU_blend(true);
/* Extracted from 'widget_menu_back', keep separate to avoid menu changes breaking popovers */
{
@@ -4685,7 +4401,7 @@ static void ui_draw_popover_back_impl(
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4ubv((unsigned char *)wcol->inner);
- glEnable(GL_BLEND);
+ GPU_blend(true);
immBegin(GWN_PRIM_TRIS, 3);
if (direction == UI_DIR_DOWN) {
const float y = rect->ymax;
@@ -4703,22 +4419,24 @@ static void ui_draw_popover_back_impl(
immUnbindProgram();
}
- glDisable(GL_BLEND);
+ 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] = {block->mx, block->my};
ui_window_to_block_fl(ar, block, &mval_origin[0], &mval_origin[1]);
- ui_draw_popover_back_impl(&wcol_menu_back, rect, block->direction, mval_origin);
+ ui_draw_popover_back_impl(wt->wcol_theme, rect, block->direction, mval_origin);
}
else {
- uiWidgetType *wt = widget_type(UI_WTYPE_MENU_BACK);
-
wt->state(wt, 0);
wt->draw(&wt->wcol, rect, 0, 0);
}
+
+ ui_draw_clip_tri(block, rect, wt);
}
static void draw_disk_shaded(
@@ -4795,7 +4513,7 @@ void ui_draw_pie_center(uiBlock *block)
gpuPushMatrix();
gpuTranslate2f(cx, cy);
- glEnable(GL_BLEND);
+ 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);
@@ -4838,7 +4556,7 @@ void ui_draw_pie_center(uiBlock *block)
draw_disk_shaded(angle - range / 2.0f, range, pie_confirm_radius, pie_confirm_external, subd, col, NULL, false);
}
- glDisable(GL_BLEND);
+ GPU_blend(false);
gpuPopMatrix();
}
@@ -4849,30 +4567,41 @@ uiWidgetColors *ui_tooltip_get_theme(void)
return wt->wcol_theme;
}
-void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *UNUSED(block), rcti *rect)
+/**
+ * Generic drawing for background.
+ */
+void ui_draw_widget_back_color(
+ uiWidgetTypeEnum type, bool use_shadow, const rcti *rect,
+ const float color[4])
{
- uiWidgetType *wt = widget_type(UI_WTYPE_TOOLTIP);
+ uiWidgetType *wt = widget_type(type);
+
+ if (use_shadow) {
+ GPU_blend(true);
+ widget_softshadow(rect, UI_CNR_ALL, 0.25f * U.widget_unit);
+ GPU_blend(false);
+ }
+
+ rcti rect_copy = *rect;
wt->state(wt, 0);
- /* wt->draw ends up using same function to draw the tooltip as menu_back */
- wt->draw(&wt->wcol, rect, 0, 0);
+ if (color) {
+ rgba_float_to_uchar((unsigned char *)wt->wcol.inner, color);
+ }
+ wt->draw(&wt->wcol, &rect_copy, 0, UI_CNR_ALL);
}
-
-void ui_draw_search_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
+void ui_draw_widget_back(uiWidgetTypeEnum type, bool use_shadow, const rcti *rect)
{
- uiWidgetType *wt = widget_type(UI_WTYPE_BOX);
-
- glEnable(GL_BLEND);
- widget_softshadow(rect, UI_CNR_ALL, 0.25f * U.widget_unit);
- glDisable(GL_BLEND);
+ ui_draw_widget_back_color(type, 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);
- if (block)
- wt->draw(&wt->wcol, rect, block->flag, UI_CNR_ALL);
- else
- wt->draw(&wt->wcol, rect, 0, UI_CNR_ALL);
+ /* 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(uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state, bool use_sep)
@@ -4883,10 +4612,10 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
wt->state(wt, state);
wt->draw(&wt->wcol, rect, 0, 0);
-
+
UI_fontstyle_set(fstyle);
fstyle->align = UI_STYLE_TEXT_LEFT;
-
+
/* text location offset */
rect->xmin += 0.25f * UI_UNIT_X;
if (iconid) rect->xmin += UI_DPI_ICON_SIZE;
@@ -4935,7 +4664,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
*cpoin = UI_SEP_CHAR;
}
}
-
+
/* restore rect, was messed with */
*rect = _rect;
@@ -4946,10 +4675,10 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
height = ICON_SIZE_FROM_BUTRECT(rect);
aspect = ICON_DEFAULT_HEIGHT / height;
-
- glEnable(GL_BLEND);
+
+ GPU_blend(true);
UI_icon_draw_aspect(xs, ys, iconid, aspect, 1.0f); /* XXX scale weak get from fstyle? */
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
}
@@ -4959,17 +4688,17 @@ void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int
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);
wt->draw(&wt->wcol, rect, 0, 0);
-
+
/* draw icon in rect above the space reserved for the label */
rect->ymin += text_size;
- glEnable(GL_BLEND);
+ GPU_blend(true);
widget_draw_preview(iconid, 1.0f, rect);
- glDisable(GL_BLEND);
-
+ GPU_blend(false);
+
BLF_width_and_height(fstyle->uifont_id, name, BLF_DRAW_STR_DUMMY_MAX, &font_dims[0], &font_dims[1]);
/* text rect */
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 95a7d0a0d06..fb4d6e0ea14 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -48,18 +48,24 @@
#include "BKE_addon.h"
#include "BKE_appdir.h"
#include "BKE_colorband.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
#include "BKE_main.h"
+#include "BKE_mesh_runtime.h"
#include "BIF_gl.h"
#include "BLF_api.h"
+#include "ED_screen.h"
+
#include "UI_interface.h"
#include "UI_interface_icons.h"
#include "interface_intern.h"
+#include "GPU_framebuffer.h"
+
+
+extern const bTheme U_theme_default;
/* global for themes */
typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha);
@@ -96,18 +102,19 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
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:
@@ -115,7 +122,7 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
}
}
else {
-
+
switch (spacetype) {
case SPACE_BUTS:
ts = &btheme->tbuts;
@@ -165,6 +172,9 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
case SPACE_TOPBAR:
ts = &btheme->ttopbar;
break;
+ case SPACE_STATUSBAR:
+ ts = &btheme->tstatusbar;
+ break;
default:
ts = &btheme->tv3d;
break;
@@ -180,6 +190,12 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->header;
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_LOW_GRAD:
cp = ts->gradients.gradient;
@@ -242,6 +258,8 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
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_PANEL_SHOW_HEADER:
cp = &setting;
setting = ts->panelcolors.show_header;
@@ -250,7 +268,7 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = &setting;
setting = ts->panelcolors.show_back;
break;
-
+
case TH_BUTBACK:
cp = ts->button; break;
case TH_BUTBACK_TEXT:
@@ -273,7 +291,7 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->shade2; break;
case TH_HILITE:
cp = ts->hilite; break;
-
+
case TH_GRID:
cp = ts->grid; break;
case TH_VIEW_OVERLAY:
@@ -524,7 +542,7 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
case TH_HANDLE_VERTEX_SIZE:
cp = &ts->handle_vertex_size;
break;
-
+
case TH_GP_VERTEX:
cp = ts->gp_vertex;
break;
@@ -534,7 +552,7 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
case TH_GP_VERTEX_SIZE:
cp = &ts->gp_vertex_size;
break;
-
+
case TH_DOPESHEET_CHANNELOB:
cp = ts->ds_channel;
break;
@@ -622,21 +640,21 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
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_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;
@@ -655,7 +673,7 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
case TH_NLA_SOUND_SEL:
cp = ts->nla_sound_sel;
break;
-
+
case TH_WIDGET_EMBOSS:
cp = btheme->tui.widget_emboss; break;
@@ -716,147 +734,8 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
}
}
}
-
- return (const unsigned char *)cp;
-}
-/* use this call to init new bone color sets in Theme */
-static void ui_theme_init_boneColorSets(bTheme *btheme)
-{
- int i;
-
- /* define default color sets - currently we only define 15 of these, though that should be ample */
- /* set 1 */
- rgba_char_args_set(btheme->tarm[0].solid, 0x9a, 0x00, 0x00, 255);
- rgba_char_args_set(btheme->tarm[0].select, 0xbd, 0x11, 0x11, 255);
- rgba_char_args_set(btheme->tarm[0].active, 0xf7, 0x0a, 0x0a, 255);
- /* set 2 */
- rgba_char_args_set(btheme->tarm[1].solid, 0xf7, 0x40, 0x18, 255);
- rgba_char_args_set(btheme->tarm[1].select, 0xf6, 0x69, 0x13, 255);
- rgba_char_args_set(btheme->tarm[1].active, 0xfa, 0x99, 0x00, 255);
- /* set 3 */
- rgba_char_args_set(btheme->tarm[2].solid, 0x1e, 0x91, 0x09, 255);
- rgba_char_args_set(btheme->tarm[2].select, 0x59, 0xb7, 0x0b, 255);
- rgba_char_args_set(btheme->tarm[2].active, 0x83, 0xef, 0x1d, 255);
- /* set 4 */
- rgba_char_args_set(btheme->tarm[3].solid, 0x0a, 0x36, 0x94, 255);
- rgba_char_args_set(btheme->tarm[3].select, 0x36, 0x67, 0xdf, 255);
- rgba_char_args_set(btheme->tarm[3].active, 0x5e, 0xc1, 0xef, 255);
- /* set 5 */
- rgba_char_args_set(btheme->tarm[4].solid, 0xa9, 0x29, 0x4e, 255);
- rgba_char_args_set(btheme->tarm[4].select, 0xc1, 0x41, 0x6a, 255);
- rgba_char_args_set(btheme->tarm[4].active, 0xf0, 0x5d, 0x91, 255);
- /* set 6 */
- rgba_char_args_set(btheme->tarm[5].solid, 0x43, 0x0c, 0x78, 255);
- rgba_char_args_set(btheme->tarm[5].select, 0x54, 0x3a, 0xa3, 255);
- rgba_char_args_set(btheme->tarm[5].active, 0x87, 0x64, 0xd5, 255);
- /* set 7 */
- rgba_char_args_set(btheme->tarm[6].solid, 0x24, 0x78, 0x5a, 255);
- rgba_char_args_set(btheme->tarm[6].select, 0x3c, 0x95, 0x79, 255);
- rgba_char_args_set(btheme->tarm[6].active, 0x6f, 0xb6, 0xab, 255);
- /* set 8 */
- rgba_char_args_set(btheme->tarm[7].solid, 0x4b, 0x70, 0x7c, 255);
- rgba_char_args_set(btheme->tarm[7].select, 0x6a, 0x86, 0x91, 255);
- rgba_char_args_set(btheme->tarm[7].active, 0x9b, 0xc2, 0xcd, 255);
- /* set 9 */
- rgba_char_args_set(btheme->tarm[8].solid, 0xf4, 0xc9, 0x0c, 255);
- rgba_char_args_set(btheme->tarm[8].select, 0xee, 0xc2, 0x36, 255);
- rgba_char_args_set(btheme->tarm[8].active, 0xf3, 0xff, 0x00, 255);
- /* set 10 */
- rgba_char_args_set(btheme->tarm[9].solid, 0x1e, 0x20, 0x24, 255);
- rgba_char_args_set(btheme->tarm[9].select, 0x48, 0x4c, 0x56, 255);
- rgba_char_args_set(btheme->tarm[9].active, 0xff, 0xff, 0xff, 255);
- /* set 11 */
- rgba_char_args_set(btheme->tarm[10].solid, 0x6f, 0x2f, 0x6a, 255);
- rgba_char_args_set(btheme->tarm[10].select, 0x98, 0x45, 0xbe, 255);
- rgba_char_args_set(btheme->tarm[10].active, 0xd3, 0x30, 0xd6, 255);
- /* set 12 */
- rgba_char_args_set(btheme->tarm[11].solid, 0x6c, 0x8e, 0x22, 255);
- rgba_char_args_set(btheme->tarm[11].select, 0x7f, 0xb0, 0x22, 255);
- rgba_char_args_set(btheme->tarm[11].active, 0xbb, 0xef, 0x5b, 255);
- /* set 13 */
- rgba_char_args_set(btheme->tarm[12].solid, 0x8d, 0x8d, 0x8d, 255);
- rgba_char_args_set(btheme->tarm[12].select, 0xb0, 0xb0, 0xb0, 255);
- rgba_char_args_set(btheme->tarm[12].active, 0xde, 0xde, 0xde, 255);
- /* set 14 */
- rgba_char_args_set(btheme->tarm[13].solid, 0x83, 0x43, 0x26, 255);
- rgba_char_args_set(btheme->tarm[13].select, 0x8b, 0x58, 0x11, 255);
- rgba_char_args_set(btheme->tarm[13].active, 0xbd, 0x6a, 0x11, 255);
- /* set 15 */
- rgba_char_args_set(btheme->tarm[14].solid, 0x08, 0x31, 0x0e, 255);
- rgba_char_args_set(btheme->tarm[14].select, 0x1c, 0x43, 0x0b, 255);
- rgba_char_args_set(btheme->tarm[14].active, 0x34, 0x62, 0x2b, 255);
-
- /* reset flags too */
- for (i = 0; i < 20; i++)
- btheme->tarm[i].flag = 0;
-}
-
-/* use this call to init new variables in themespace, if they're same for all */
-static void ui_theme_init_new_do(ThemeSpace *ts)
-{
- rgba_char_args_set(ts->header_text, 0, 0, 0, 255);
- rgba_char_args_set(ts->header_title, 0, 0, 0, 255);
- rgba_char_args_set(ts->header_text_hi, 255, 255, 255, 255);
-
-#if 0
- rgba_char_args_set(ts->panel_text, 0, 0, 0, 255);
- rgba_char_args_set(ts->panel_title, 0, 0, 0, 255);
- rgba_char_args_set(ts->panel_text_hi, 255, 255, 255, 255);
-#endif
-
- ts->panelcolors.show_back = false;
- ts->panelcolors.show_header = false;
- rgba_char_args_set(ts->panelcolors.back, 114, 114, 114, 128);
- rgba_char_args_set(ts->panelcolors.header, 0, 0, 0, 25);
-
- rgba_char_args_set(ts->button, 145, 145, 145, 245);
- rgba_char_args_set(ts->button_title, 0, 0, 0, 255);
- rgba_char_args_set(ts->button_text, 0, 0, 0, 255);
- rgba_char_args_set(ts->button_text_hi, 255, 255, 255, 255);
-
- rgba_char_args_set(ts->list, 165, 165, 165, 255);
- rgba_char_args_set(ts->list_title, 0, 0, 0, 255);
- rgba_char_args_set(ts->list_text, 0, 0, 0, 255);
- rgba_char_args_set(ts->list_text_hi, 255, 255, 255, 255);
-
- rgba_char_args_set(ts->tab_active, 114, 114, 114, 255);
- rgba_char_args_set(ts->tab_inactive, 83, 83, 83, 255);
- rgba_char_args_set(ts->tab_back, 64, 64, 64, 255);
- rgba_char_args_set(ts->tab_outline, 60, 60, 60, 255);
-}
-
-static void ui_theme_init_new(bTheme *btheme)
-{
- ThemeSpace *ts;
-
- for (ts = UI_THEMESPACE_START(btheme); ts != UI_THEMESPACE_END(btheme); ts++) {
- ui_theme_init_new_do(ts);
- }
-}
-
-static void ui_theme_space_init_handles_color(ThemeSpace *theme_space)
-{
- rgba_char_args_set(theme_space->handle_free, 0, 0, 0, 255);
- rgba_char_args_set(theme_space->handle_auto, 0x90, 0x90, 0x00, 255);
- rgba_char_args_set(theme_space->handle_vect, 0x40, 0x90, 0x30, 255);
- rgba_char_args_set(theme_space->handle_align, 0x80, 0x30, 0x60, 255);
- rgba_char_args_set(theme_space->handle_sel_free, 0, 0, 0, 255);
- rgba_char_args_set(theme_space->handle_sel_auto, 0xf0, 0xff, 0x40, 255);
- rgba_char_args_set(theme_space->handle_sel_vect, 0x40, 0xc0, 0x30, 255);
- rgba_char_args_set(theme_space->handle_sel_align, 0xf0, 0x90, 0xa0, 255);
- rgba_char_args_set(theme_space->handle_vertex, 0x00, 0x00, 0x00, 0xff);
- rgba_char_args_set(theme_space->handle_vertex_select, 0xff, 0xff, 0, 0xff);
- rgba_char_args_set(theme_space->act_spline, 0xdb, 0x25, 0x12, 255);
-}
-
-static void ui_theme_space_init_manipulator_colors(bTheme *btheme)
-{
- rgba_char_args_set(btheme->tui.manipulator_hi, 255, 255, 255, 255);
- rgba_char_args_set(btheme->tui.manipulator_primary, 222, 255, 13, 255);
- rgba_char_args_set(btheme->tui.manipulator_secondary, 0, 255, 255, 255);
- rgba_char_args_set(btheme->tui.manipulator_a, 23, 127, 23, 255);
- rgba_char_args_set(btheme->tui.manipulator_b, 127, 23, 23, 255);
+ return (const unsigned char *)cp;
}
/**
@@ -866,378 +745,17 @@ static void ui_theme_space_init_manipulator_colors(bTheme *btheme)
*/
void ui_theme_init_default(void)
{
- bTheme *btheme;
-
+
/* we search for the theme with name Default */
- btheme = BLI_findstring(&U.themes, "Default", offsetof(bTheme, name));
-
+ bTheme *btheme = BLI_findstring(&U.themes, "Default", offsetof(bTheme, name));
if (btheme == NULL) {
- btheme = MEM_callocN(sizeof(bTheme), "theme");
+ btheme = MEM_callocN(sizeof(bTheme), __func__);
BLI_addtail(&U.themes, btheme);
- strcpy(btheme->name, "Default");
}
-
+
UI_SetTheme(0, 0); /* make sure the global used in this file is set */
- /* UI buttons */
- ui_widget_color_init(&btheme->tui);
-
- btheme->tui.iconfile[0] = 0;
- rgba_char_args_set(btheme->tui.wcol_tooltip.text, 255, 255, 255, 255);
- rgba_char_args_set_fl(btheme->tui.widget_emboss, 1.0f, 1.0f, 1.0f, 0.02f);
- rgba_char_args_set_fl(btheme->tui.editor_outline, 0.25f, 0.25f, 0.25f, 1.0f);
-
- rgba_char_args_set(btheme->tui.xaxis, 220, 0, 0, 255);
- rgba_char_args_set(btheme->tui.yaxis, 0, 220, 0, 255);
- rgba_char_args_set(btheme->tui.zaxis, 0, 0, 220, 255);
-
- btheme->tui.menu_shadow_fac = 0.5f;
- btheme->tui.menu_shadow_width = 12;
-
- /* Bone Color Sets */
- ui_theme_init_boneColorSets(btheme);
-
- /* common (new) variables */
- ui_theme_init_new(btheme);
-
- /* Manipulator. */
- ui_theme_space_init_manipulator_colors(btheme);
-
- /* space view3d */
- rgba_char_args_set_fl(btheme->tv3d.back, 0.225, 0.225, 0.225, 1.0);
- rgba_char_args_set(btheme->tv3d.text, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.text_hi, 255, 255, 255, 255);
-
- rgba_char_args_set_fl(btheme->tv3d.header, 0.45, 0.45, 0.45, 1.0);
- rgba_char_args_set_fl(btheme->tv3d.button, 0.45, 0.45, 0.45, 0.5);
-// rgba_char_args_set(btheme->tv3d.panel, 165, 165, 165, 127);
-
- rgba_char_args_set(btheme->tv3d.shade1, 160, 160, 160, 100);
- rgba_char_args_set(btheme->tv3d.shade2, 0x7f, 0x70, 0x70, 100);
-
- rgba_char_args_set_fl(btheme->tv3d.grid, 0.251, 0.251, 0.251, 1.0);
- rgba_char_args_set(btheme->tv3d.view_overlay, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.wire, 0x0, 0x0, 0x0, 255);
- rgba_char_args_set(btheme->tv3d.wire_edit, 0x0, 0x0, 0x0, 255);
- rgba_char_args_set(btheme->tv3d.lamp, 0, 0, 0, 40);
- rgba_char_args_set(btheme->tv3d.speaker, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.camera, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.empty, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.select, 241, 88, 0, 255);
- rgba_char_args_set(btheme->tv3d.active, 255, 170, 64, 255);
- rgba_char_args_set(btheme->tv3d.group, 8, 48, 8, 255);
- rgba_char_args_set(btheme->tv3d.group_active, 85, 187, 85, 255);
- rgba_char_args_set(btheme->tv3d.transform, 0xff, 0xff, 0xff, 255);
- rgba_char_args_set(btheme->tv3d.vertex, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.vertex_select, 255, 133, 0, 255);
- rgba_char_args_set(btheme->tv3d.vertex_bevel, 0, 165, 255, 255);
- rgba_char_args_set(btheme->tv3d.vertex_unreferenced, 0, 0, 0, 255);
- btheme->tv3d.vertex_size = 3;
- btheme->tv3d.outline_width = 1;
- rgba_char_args_set(btheme->tv3d.edge, 0x0, 0x0, 0x0, 255);
- rgba_char_args_set(btheme->tv3d.edge_select, 255, 160, 0, 255);
- rgba_char_args_set(btheme->tv3d.edge_seam, 219, 37, 18, 255);
- rgba_char_args_set(btheme->tv3d.edge_bevel, 0, 165, 255, 255);
- rgba_char_args_set(btheme->tv3d.edge_facesel, 75, 75, 75, 255);
- rgba_char_args_set(btheme->tv3d.face, 0, 0, 0, 18);
- rgba_char_args_set(btheme->tv3d.face_select, 255, 133, 0, 60);
- rgba_char_args_set(btheme->tv3d.normal, 0x22, 0xDD, 0xDD, 255);
- rgba_char_args_set(btheme->tv3d.vertex_normal, 0x23, 0x61, 0xDD, 255);
- rgba_char_args_set(btheme->tv3d.loop_normal, 0xDD, 0x23, 0xDD, 255);
- rgba_char_args_set(btheme->tv3d.face_dot, 255, 133, 0, 255);
- rgba_char_args_set(btheme->tv3d.editmesh_active, 255, 255, 255, 128);
- rgba_char_args_set_fl(btheme->tv3d.edge_crease, 0.8, 0, 0.6, 1.0);
- rgba_char_args_set(btheme->tv3d.edge_sharp, 0, 255, 255, 255);
- rgba_char_args_set(btheme->tv3d.header_text, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.header_text_hi, 255, 255, 255, 255);
- rgba_char_args_set(btheme->tv3d.button_text, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.button_text_hi, 255, 255, 255, 255);
- rgba_char_args_set(btheme->tv3d.button_title, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.title, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.freestyle_edge_mark, 0x7f, 0xff, 0x7f, 255);
- rgba_char_args_set(btheme->tv3d.freestyle_face_mark, 0x7f, 0xff, 0x7f, 51);
- rgba_char_args_set_fl(btheme->tv3d.paint_curve_handle, 0.5f, 1.0f, 0.5f, 0.5f);
- rgba_char_args_set_fl(btheme->tv3d.paint_curve_pivot, 1.0f, 0.5f, 0.5f, 0.5f);
- rgba_char_args_set(btheme->tv3d.gp_vertex, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.gp_vertex_select, 255, 133, 0, 255);
- btheme->tv3d.gp_vertex_size = 3;
-
- btheme->tv3d.facedot_size = 4;
-
- rgba_char_args_set(btheme->tv3d.extra_edge_len, 32, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.extra_edge_angle, 32, 32, 0, 255);
- rgba_char_args_set(btheme->tv3d.extra_face_area, 0, 32, 0, 255);
- rgba_char_args_set(btheme->tv3d.extra_face_angle, 0, 0, 128, 255);
-
- rgba_char_args_set(btheme->tv3d.cframe, 0x60, 0xc0, 0x40, 255);
-
- rgba_char_args_set(btheme->tv3d.nurb_uline, 0x90, 0x90, 0x00, 255);
- rgba_char_args_set(btheme->tv3d.nurb_vline, 0x80, 0x30, 0x60, 255);
- rgba_char_args_set(btheme->tv3d.nurb_sel_uline, 0xf0, 0xff, 0x40, 255);
- rgba_char_args_set(btheme->tv3d.nurb_sel_vline, 0xf0, 0x90, 0xa0, 255);
-
- ui_theme_space_init_handles_color(&btheme->tv3d);
-
- rgba_char_args_set(btheme->tv3d.act_spline, 0xdb, 0x25, 0x12, 255);
- rgba_char_args_set(btheme->tv3d.lastsel_point, 0xff, 0xff, 0xff, 255);
-
- rgba_char_args_set(btheme->tv3d.bone_solid, 200, 200, 200, 255);
- /* alpha 80 is not meant editable, used for wire+action draw */
- rgba_char_args_set(btheme->tv3d.bone_pose, 80, 200, 255, 80);
- rgba_char_args_set(btheme->tv3d.bone_pose_active, 140, 255, 255, 80);
-
- rgba_char_args_set(btheme->tv3d.bundle_solid, 200, 200, 200, 255);
- rgba_char_args_set(btheme->tv3d.camera_path, 0x00, 0x00, 0x00, 255);
-
- rgba_char_args_set(btheme->tv3d.skin_root, 180, 77, 77, 255);
- rgba_char_args_set(btheme->tv3d.gradients.gradient, 0, 0, 0, 0);
- rgba_char_args_set(btheme->tv3d.gradients.high_gradient, 58, 58, 58, 255);
- btheme->tv3d.gradients.show_grad = false;
-
- rgba_char_args_set(btheme->tv3d.clipping_border_3d, 50, 50, 50, 255);
-
- rgba_char_args_set(btheme->tv3d.time_keyframe, 0xDD, 0xD7, 0x00, 0xFF);
- rgba_char_args_set(btheme->tv3d.time_gp_keyframe, 0xB5, 0xE6, 0x1D, 0xFF);
-
- /* space buttons */
- /* to have something initialized */
- btheme->tbuts = btheme->tv3d;
-
- rgba_char_args_set_fl(btheme->tbuts.back, 0.45, 0.45, 0.45, 1.0);
-// rgba_char_args_set(btheme->tbuts.panel, 0x82, 0x82, 0x82, 255);
-
- /* graph editor */
- btheme->tipo = btheme->tv3d;
- rgba_char_args_set_fl(btheme->tipo.back, 0.42, 0.42, 0.42, 1.0);
- rgba_char_args_set_fl(btheme->tipo.list, 0.4, 0.4, 0.4, 1.0);
- rgba_char_args_set(btheme->tipo.grid, 94, 94, 94, 255);
-// rgba_char_args_set(btheme->tipo.panel, 255, 255, 255, 150);
- rgba_char_args_set(btheme->tipo.shade1, 150, 150, 150, 100); /* scrollbars */
- rgba_char_args_set(btheme->tipo.shade2, 0x70, 0x70, 0x70, 100);
- rgba_char_args_set(btheme->tipo.vertex, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tipo.vertex_select, 255, 133, 0, 255);
- rgba_char_args_set(btheme->tipo.hilite, 0x60, 0xc0, 0x40, 255);
- btheme->tipo.vertex_size = 6;
-
- rgba_char_args_set(btheme->tipo.handle_vertex, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tipo.handle_vertex_select, 255, 133, 0, 255);
- rgba_char_args_set(btheme->tipo.handle_auto_clamped, 0x99, 0x40, 0x30, 255);
- rgba_char_args_set(btheme->tipo.handle_sel_auto_clamped, 0xf0, 0xaf, 0x90, 255);
- btheme->tipo.handle_vertex_size = 5;
-
- rgba_char_args_set(btheme->tipo.ds_channel, 82, 96, 110, 255);
- rgba_char_args_set(btheme->tipo.ds_subchannel, 124, 137, 150, 255);
- rgba_char_args_set(btheme->tipo.group, 79, 101, 73, 255);
- rgba_char_args_set(btheme->tipo.group_active, 135, 177, 125, 255);
-
- /* dopesheet */
- btheme->tact = btheme->tipo;
- rgba_char_args_set(btheme->tact.strip, 12, 10, 10, 128);
- rgba_char_args_set(btheme->tact.strip_select, 255, 140, 0, 255);
-
- rgba_char_args_set(btheme->tact.anim_active, 204, 112, 26, 102);
-
- rgba_char_args_set(btheme->tact.keytype_keyframe, 232, 232, 232, 255);
- rgba_char_args_set(btheme->tact.keytype_keyframe_select, 255, 190, 50, 255);
- rgba_char_args_set(btheme->tact.keytype_extreme, 232, 179, 204, 255);
- rgba_char_args_set(btheme->tact.keytype_extreme_select, 242, 128, 128, 255);
- rgba_char_args_set(btheme->tact.keytype_breakdown, 179, 219, 232, 255);
- rgba_char_args_set(btheme->tact.keytype_breakdown_select, 84, 191, 237, 255);
- rgba_char_args_set(btheme->tact.keytype_jitter, 148, 229, 117, 255);
- rgba_char_args_set(btheme->tact.keytype_jitter_select, 97, 192, 66, 255);
-
- rgba_char_args_set(btheme->tact.keyborder, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tact.keyborder_select, 0, 0, 0, 255);
-
- btheme->tact.keyframe_scale_fac = 1.0f;
-
- /* space nla */
- btheme->tnla = btheme->tact;
-
- rgba_char_args_set(btheme->tnla.anim_active, 204, 112, 26, 102); /* same as for dopesheet; duplicate here for easier reference */
- rgba_char_args_set(btheme->tnla.anim_non_active, 153, 135, 97, 77);
-
- rgba_char_args_set(btheme->tnla.nla_tweaking, 77, 243, 26, 77);
- rgba_char_args_set(btheme->tnla.nla_tweakdupli, 217, 0, 0, 255);
-
- rgba_char_args_set(btheme->tnla.nla_transition, 28, 38, 48, 255);
- rgba_char_args_set(btheme->tnla.nla_transition_sel, 46, 117, 219, 255);
- rgba_char_args_set(btheme->tnla.nla_meta, 51, 38, 66, 255);
- rgba_char_args_set(btheme->tnla.nla_meta_sel, 105, 33, 150, 255);
- rgba_char_args_set(btheme->tnla.nla_sound, 43, 61, 61, 255);
- rgba_char_args_set(btheme->tnla.nla_sound_sel, 31, 122, 122, 255);
-
- rgba_char_args_set(btheme->tnla.keyborder, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tnla.keyborder_select, 0, 0, 0, 255);
-
- /* space file */
- /* to have something initialized */
- btheme->tfile = btheme->tv3d;
- rgba_char_args_set_fl(btheme->tfile.back, 0.3, 0.3, 0.3, 1);
-// rgba_char_args_set_fl(btheme->tfile.panel, 0.3, 0.3, 0.3, 1);
- rgba_char_args_set_fl(btheme->tfile.list, 0.4, 0.4, 0.4, 1);
- rgba_char_args_set(btheme->tfile.text, 250, 250, 250, 255);
- rgba_char_args_set(btheme->tfile.text_hi, 15, 15, 15, 255);
-// rgba_char_args_set(btheme->tfile.panel, 145, 145, 145, 255); /* bookmark/ui regions */
- rgba_char_args_set(btheme->tfile.hilite, 255, 140, 25, 255); /* selected files */
-
- rgba_char_args_set(btheme->tfile.image, 250, 250, 250, 255);
- rgba_char_args_set(btheme->tfile.movie, 250, 250, 250, 255);
- rgba_char_args_set(btheme->tfile.scene, 250, 250, 250, 255);
-
-
- /* space seq */
- btheme->tseq = btheme->tv3d;
- rgba_char_args_set(btheme->tseq.back, 116, 116, 116, 255);
- rgba_char_args_set(btheme->tseq.movie, 81, 105, 135, 255);
- rgba_char_args_set(btheme->tseq.movieclip, 32, 32, 143, 255);
- rgba_char_args_set(btheme->tseq.mask, 152, 78, 62, 255);
- rgba_char_args_set(btheme->tseq.image, 109, 88, 129, 255);
- rgba_char_args_set(btheme->tseq.scene, 78, 152, 62, 255);
- rgba_char_args_set(btheme->tseq.audio, 46, 143, 143, 255);
- rgba_char_args_set(btheme->tseq.effect, 169, 84, 124, 255);
- rgba_char_args_set(btheme->tseq.transition, 162, 95, 111, 255);
- rgba_char_args_set(btheme->tseq.meta, 109, 145, 131, 255);
- rgba_char_args_set(btheme->tseq.text_strip, 162, 151, 0, 255);
- rgba_char_args_set(btheme->tseq.preview_back, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tseq.grid, 64, 64, 64, 255);
-
- /* space image */
- btheme->tima = btheme->tv3d;
- rgba_char_args_set(btheme->tima.back, 53, 53, 53, 255);
- rgba_char_args_set(btheme->tima.vertex, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tima.vertex_select, 255, 133, 0, 255);
- rgba_char_args_set(btheme->tima.wire_edit, 192, 192, 192, 255);
- rgba_char_args_set(btheme->tima.edge_select, 255, 133, 0, 255);
- btheme->tima.vertex_size = 3;
- btheme->tima.facedot_size = 3;
- rgba_char_args_set(btheme->tima.face, 255, 255, 255, 10);
- rgba_char_args_set(btheme->tima.face_select, 255, 133, 0, 60);
- rgba_char_args_set(btheme->tima.editmesh_active, 255, 255, 255, 128);
- rgba_char_args_set_fl(btheme->tima.preview_back, 0.0, 0.0, 0.0, 0.3);
- rgba_char_args_set_fl(btheme->tima.preview_stitch_face, 0.5, 0.5, 0.0, 0.2);
- rgba_char_args_set_fl(btheme->tima.preview_stitch_edge, 1.0, 0.0, 1.0, 0.2);
- rgba_char_args_set_fl(btheme->tima.preview_stitch_vert, 0.0, 0.0, 1.0, 0.2);
- rgba_char_args_set_fl(btheme->tima.preview_stitch_stitchable, 0.0, 1.0, 0.0, 1.0);
- rgba_char_args_set_fl(btheme->tima.preview_stitch_unstitchable, 1.0, 0.0, 0.0, 1.0);
- rgba_char_args_set_fl(btheme->tima.preview_stitch_active, 0.886, 0.824, 0.765, 0.140);
-
- rgba_char_args_test_set(btheme->tima.uv_others, 96, 96, 96, 255);
- rgba_char_args_test_set(btheme->tima.uv_shadow, 112, 112, 112, 255);
-
- ui_theme_space_init_handles_color(&btheme->tima);
- btheme->tima.handle_vertex_size = 5;
-
- /* space text */
- btheme->text = btheme->tv3d;
- rgba_char_args_set(btheme->text.back, 153, 153, 153, 255);
- rgba_char_args_set(btheme->text.shade1, 143, 143, 143, 255);
- rgba_char_args_set(btheme->text.shade2, 0xc6, 0x77, 0x77, 255);
- rgba_char_args_set(btheme->text.hilite, 255, 0, 0, 255);
-
- /* syntax highlighting */
- rgba_char_args_set(btheme->text.syntaxn, 0, 0, 200, 255); /* Numbers Blue*/
- rgba_char_args_set(btheme->text.syntaxl, 100, 0, 0, 255); /* Strings Red */
- rgba_char_args_set(btheme->text.syntaxc, 0, 100, 50, 255); /* Comments Greenish */
- rgba_char_args_set(btheme->text.syntaxv, 95, 95, 0, 255); /* Special Yellow*/
- rgba_char_args_set(btheme->text.syntaxd, 50, 0, 140, 255); /* Decorator/Preprocessor Dir. Blue-purple */
- rgba_char_args_set(btheme->text.syntaxr, 140, 60, 0, 255); /* Reserved Orange*/
- rgba_char_args_set(btheme->text.syntaxb, 128, 0, 80, 255); /* Builtin Red-purple */
- rgba_char_args_set(btheme->text.syntaxs, 76, 76, 76, 255); /* Gray (mix between fg/bg) */
-
- /* space oops */
- btheme->toops = btheme->tv3d;
- rgba_char_args_set_fl(btheme->toops.back, 0.45, 0.45, 0.45, 1.0);
-
- rgba_char_args_set_fl(btheme->toops.match, 0.2, 0.5, 0.2, 0.3); /* highlighting search match - soft green*/
- rgba_char_args_set_fl(btheme->toops.selected_highlight, 0.51, 0.53, 0.55, 0.3);
-
- /* space info */
- btheme->tinfo = btheme->tv3d;
- rgba_char_args_set_fl(btheme->tinfo.back, 0.45, 0.45, 0.45, 1.0);
- rgba_char_args_set(btheme->tinfo.info_selected, 96, 128, 255, 255);
- rgba_char_args_set(btheme->tinfo.info_selected_text, 255, 255, 255, 255);
- rgba_char_args_set(btheme->tinfo.info_error, 220, 0, 0, 255);
- rgba_char_args_set(btheme->tinfo.info_error_text, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tinfo.info_warning, 220, 128, 96, 255);
- rgba_char_args_set(btheme->tinfo.info_warning_text, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tinfo.info_info, 0, 170, 0, 255);
- rgba_char_args_set(btheme->tinfo.info_info_text, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tinfo.info_debug, 196, 196, 196, 255);
- rgba_char_args_set(btheme->tinfo.info_debug_text, 0, 0, 0, 255);
-
- /* space user preferences */
- btheme->tuserpref = btheme->tv3d;
- rgba_char_args_set_fl(btheme->tuserpref.back, 0.45, 0.45, 0.45, 1.0);
-
- /* space console */
- btheme->tconsole = btheme->tv3d;
- rgba_char_args_set(btheme->tconsole.back, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tconsole.console_output, 96, 128, 255, 255);
- rgba_char_args_set(btheme->tconsole.console_input, 255, 255, 255, 255);
- rgba_char_args_set(btheme->tconsole.console_info, 0, 170, 0, 255);
- rgba_char_args_set(btheme->tconsole.console_error, 220, 96, 96, 255);
- rgba_char_args_set(btheme->tconsole.console_cursor, 220, 96, 96, 255);
- rgba_char_args_set(btheme->tconsole.console_select, 255, 255, 255, 48);
-
- /* space time */
- btheme->ttime = btheme->tv3d;
- rgba_char_args_set_fl(btheme->ttime.back, 0.45, 0.45, 0.45, 1.0);
- rgba_char_args_set_fl(btheme->ttime.grid, 0.36, 0.36, 0.36, 1.0);
- rgba_char_args_set(btheme->ttime.shade1, 173, 173, 173, 255); /* sliders */
-
- rgba_char_args_set(btheme->ttime.time_keyframe, 0xDD, 0xD7, 0x00, 0xFF);
- rgba_char_args_set(btheme->ttime.time_gp_keyframe, 0xB5, 0xE6, 0x1D, 0xFF);
-
- /* space node, re-uses syntax and console color storage */
- btheme->tnode = btheme->tv3d;
- rgba_char_args_set(btheme->tnode.syntaxr, 115, 115, 115, 255); /* wire inner color */
- rgba_char_args_set(btheme->tnode.edge_select, 255, 255, 255, 255); /* wire selected */
- rgba_char_args_set(btheme->tnode.syntaxl, 155, 155, 155, 160); /* TH_NODE, backdrop */
- rgba_char_args_set(btheme->tnode.syntaxn, 100, 100, 100, 255); /* in */
- rgba_char_args_set(btheme->tnode.nodeclass_output, 100, 100, 100, 255); /* output */
- rgba_char_args_set(btheme->tnode.syntaxb, 108, 105, 111, 255); /* operator */
- rgba_char_args_set(btheme->tnode.syntaxv, 104, 106, 117, 255); /* generator */
- rgba_char_args_set(btheme->tnode.syntaxc, 105, 117, 110, 255); /* group */
- rgba_char_args_set(btheme->tnode.nodeclass_texture, 108, 105, 111, 255); /* operator */
- rgba_char_args_set(btheme->tnode.nodeclass_shader, 108, 105, 111, 255); /* operator */
- rgba_char_args_set(btheme->tnode.nodeclass_filter, 108, 105, 111, 255); /* operator */
- rgba_char_args_set(btheme->tnode.nodeclass_script, 108, 105, 111, 255); /* operator */
- rgba_char_args_set(btheme->tnode.nodeclass_pattern, 108, 105, 111, 255); /* operator */
- rgba_char_args_set(btheme->tnode.nodeclass_vector, 108, 105, 111, 255); /* operator */
- rgba_char_args_set(btheme->tnode.nodeclass_layout, 108, 105, 111, 255); /* operator */
- rgba_char_args_set(btheme->tnode.movie, 155, 155, 155, 160); /* frame */
- rgba_char_args_set(btheme->tnode.syntaxs, 151, 116, 116, 255); /* matte nodes */
- rgba_char_args_set(btheme->tnode.syntaxd, 116, 151, 151, 255); /* distort nodes */
- rgba_char_args_set(btheme->tnode.console_output, 223, 202, 53, 255); /* interface nodes */
- btheme->tnode.noodle_curving = 5;
-
- /* space clip */
- btheme->tclip = btheme->tv3d;
-
- rgba_char_args_set(btheme->tclip.marker_outline, 0x00, 0x00, 0x00, 255);
- rgba_char_args_set(btheme->tclip.marker, 0x7f, 0x7f, 0x00, 255);
- rgba_char_args_set(btheme->tclip.act_marker, 0xff, 0xff, 0xff, 255);
- rgba_char_args_set(btheme->tclip.sel_marker, 0xff, 0xff, 0x00, 255);
- rgba_char_args_set(btheme->tclip.dis_marker, 0x7f, 0x00, 0x00, 255);
- rgba_char_args_set(btheme->tclip.lock_marker, 0x7f, 0x7f, 0x7f, 255);
- rgba_char_args_set(btheme->tclip.path_before, 0xff, 0x00, 0x00, 255);
- rgba_char_args_set(btheme->tclip.path_after, 0x00, 0x00, 0xff, 255);
- rgba_char_args_set(btheme->tclip.grid, 0x5e, 0x5e, 0x5e, 255);
- rgba_char_args_set(btheme->tclip.cframe, 0x60, 0xc0, 0x40, 255);
- rgba_char_args_set(btheme->tclip.list, 0x66, 0x66, 0x66, 0xff);
- rgba_char_args_set(btheme->tclip.strip, 0x0c, 0x0a, 0x0a, 0x80);
- rgba_char_args_set(btheme->tclip.strip_select, 0xff, 0x8c, 0x00, 0xff);
- btheme->tclip.handle_vertex_size = 5;
- ui_theme_space_init_handles_color(&btheme->tclip);
-
- /* space topbar */
- char tmp[4];
- btheme->ttopbar = btheme->tv3d;
- /* swap colors */
- copy_v4_v4_char(tmp, btheme->ttopbar.header);
- copy_v4_v4_char(btheme->ttopbar.header, btheme->ttopbar.tab_inactive);
- copy_v4_v4_char(btheme->ttopbar.back, tmp);
+ memcpy(btheme, &U_theme_default, sizeof(*btheme));
}
void ui_style_init_default(void)
@@ -1291,7 +809,7 @@ void UI_Theme_Restore(struct bThemeState *theme_state)
void UI_ThemeColor(int colorid)
{
const unsigned char *cp;
-
+
cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
glColor3ubv(cp);
@@ -1301,7 +819,7 @@ void UI_ThemeColor(int colorid)
void UI_ThemeColor4(int colorid)
{
const unsigned char *cp;
-
+
cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
glColor4ubv(cp);
}
@@ -1318,7 +836,7 @@ void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset)
{
int r, g, b, a;
const unsigned char *cp;
-
+
cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
r = coloffset + (int) cp[0];
CLAMP(r, 0, 255);
@@ -1336,7 +854,7 @@ void UI_GetThemeColorShadeAlpha4ubv(int colorid, int coloffset, int alphaoffset,
{
int r, g, b, a;
const unsigned char *cp;
-
+
cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
r = coloffset + (int) cp[0];
CLAMP(r, 0, 255);
@@ -1392,7 +910,7 @@ void UI_ThemeColorBlendShade(int colorid1, int colorid2, float fac, int offset)
{
int r, g, b;
const unsigned char *cp1, *cp2;
-
+
cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
@@ -1400,11 +918,11 @@ void UI_ThemeColorBlendShade(int colorid1, int colorid2, float fac, int offset)
r = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]);
g = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]);
b = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]);
-
+
CLAMP(r, 0, 255);
CLAMP(g, 0, 255);
CLAMP(b, 0, 255);
-
+
glColor3ub(r, g, b);
}
@@ -1413,7 +931,7 @@ void UI_ThemeColorBlendShadeAlpha(int colorid1, int colorid2, float fac, int off
{
int r, g, b, a;
const unsigned char *cp1, *cp2;
-
+
cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
@@ -1422,7 +940,7 @@ void UI_ThemeColorBlendShadeAlpha(int colorid1, int colorid2, float fac, int off
g = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]);
b = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]);
a = alphaoffset + floorf((1.0f - fac) * cp1[3] + fac * cp2[3]);
-
+
CLAMP(r, 0, 255);
CLAMP(g, 0, 255);
CLAMP(b, 0, 255);
@@ -1442,7 +960,7 @@ void UI_FontThemeColor(int fontid, int colorid)
float UI_GetThemeValuef(int colorid)
{
const unsigned char *cp;
-
+
cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
return ((float)cp[0]);
}
@@ -1451,7 +969,7 @@ float UI_GetThemeValuef(int colorid)
int UI_GetThemeValue(int colorid)
{
const unsigned char *cp;
-
+
cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
return ((int) cp[0]);
}
@@ -1478,7 +996,7 @@ int UI_GetThemeValueType(int colorid, int spacetype)
void UI_GetThemeColor3fv(int colorid, float col[3])
{
const unsigned char *cp;
-
+
cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
col[0] = ((float)cp[0]) / 255.0f;
col[1] = ((float)cp[1]) / 255.0f;
@@ -1488,7 +1006,7 @@ void UI_GetThemeColor3fv(int colorid, float col[3])
void UI_GetThemeColor4fv(int colorid, float col[4])
{
const unsigned char *cp;
-
+
cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
col[0] = ((float)cp[0]) / 255.0f;
col[1] = ((float)cp[1]) / 255.0f;
@@ -1501,16 +1019,16 @@ void UI_GetThemeColorShade3fv(int colorid, int offset, float col[3])
{
int r, g, b;
const unsigned char *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] = ((float)r) / 255.0f;
col[1] = ((float)g) / 255.0f;
col[2] = ((float)b) / 255.0f;
@@ -1644,7 +1162,7 @@ void UI_GetThemeColorBlendShade4fv(int colorid1, int colorid2, float fac, int of
void UI_GetThemeColor3ubv(int colorid, unsigned char col[3])
{
const unsigned char *cp;
-
+
cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
col[0] = cp[0];
col[1] = cp[1];
@@ -1656,19 +1174,19 @@ void UI_GetThemeColorShade4fv(int colorid, int offset, float col[4])
{
int r, g, b, a;
const unsigned char *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);
-
+
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;
@@ -1679,7 +1197,7 @@ void UI_GetThemeColorShade4fv(int colorid, int offset, float col[4])
void UI_GetThemeColor4ubv(int colorid, unsigned char col[4])
{
const unsigned char *cp;
-
+
cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
col[0] = cp[0];
col[1] = cp[1];
@@ -1690,7 +1208,7 @@ void UI_GetThemeColor4ubv(int colorid, unsigned char col[4])
void UI_GetThemeColorType4ubv(int colorid, int spacetype, char col[4])
{
const unsigned char *cp;
-
+
cp = UI_ThemeGetColorPtr(theme_active, spacetype, colorid);
col[0] = cp[0];
col[1] = cp[1];
@@ -1710,7 +1228,7 @@ void UI_ColorPtrBlendShade3ubv(const unsigned char cp1[3], const unsigned char c
r = r < 0 ? 0 : (r > 255 ? 255 : r);
g = g < 0 ? 0 : (g > 255 ? 255 : g);
b = b < 0 ? 0 : (b > 255 ? 255 : b);
-
+
glColor3ub(r, g, b);
}
@@ -1755,16 +1273,16 @@ void UI_GetColorPtrBlendShade3ubv(
void UI_ThemeClearColor(int colorid)
{
float col[3];
-
+
UI_GetThemeColor3fv(colorid, col);
- glClearColor(col[0], col[1], col[2], 0.0f);
+ 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);
- glClearColor(col[0], col[1], col[2], alpha);
+ GPU_clear_color(col[0], col[1], col[2], alpha);
}
@@ -1777,7 +1295,7 @@ int UI_ThemeMenuShadowWidth(void)
void UI_make_axis_color(const unsigned char src_col[3], unsigned char dst_col[3], const char axis)
{
unsigned char col[3];
-
+
switch (axis) {
case 'X':
UI_GetThemeColor3ubv(TH_AXIS_X, col);
@@ -1800,10 +1318,8 @@ void UI_make_axis_color(const unsigned char src_col[3], unsigned char dst_col[3]
/* ************************************************************* */
/* patching UserDef struct and Themes */
-void init_userdef_do_versions(void)
+void init_userdef_do_versions(Main *bmain)
{
- Main *bmain = G.main;
-
#define USER_VERSION_ATLEAST(ver, subver) MAIN_VERSION_ATLEAST(bmain, ver, subver)
/* the UserDef struct is not corrected with do_versions() .... ugh! */
@@ -1834,287 +1350,68 @@ void init_userdef_do_versions(void)
}
if (U.pad_rot_angle == 0.0f)
U.pad_rot_angle = 15.0f;
-
+
/* graph editor - unselected F-Curve visibility */
if (U.fcu_inactive_alpha == 0) {
U.fcu_inactive_alpha = 0.25f;
}
-
- /* signal for derivedmesh to use colorband */
+
+ /* signal for evaluated mesh to use colorband */
/* run in case this was on and is now off in the user prefs [#28096] */
- vDM_ColorBand_store((U.flag & USER_CUSTOM_RANGE) ? (&U.coba_weight) : NULL, UI_GetTheme()->tv3d.vertex_unreferenced);
+ BKE_mesh_runtime_color_band_store((U.flag & USER_CUSTOM_RANGE) ? (&U.coba_weight) : NULL, UI_GetTheme()->tv3d.vertex_unreferenced);
if (!USER_VERSION_ATLEAST(192, 0)) {
strcpy(U.sounddir, "/");
}
-
+
/* patch to set Dupli Armature */
if (!USER_VERSION_ATLEAST(220, 0)) {
U.dupflag |= USER_DUP_ARM;
}
-
+
/* added seam, normal color, undo */
if (!USER_VERSION_ATLEAST(235, 0)) {
- bTheme *btheme;
-
U.uiflag |= USER_GLOBALUNDO;
if (U.undosteps == 0) U.undosteps = 32;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* check for (alpha == 0) is safe, then color was never set */
- if (btheme->tv3d.edge_seam[3] == 0) {
- rgba_char_args_set(btheme->tv3d.edge_seam, 230, 150, 50, 255);
- }
- if (btheme->tv3d.normal[3] == 0) {
- rgba_char_args_set(btheme->tv3d.normal, 0x22, 0xDD, 0xDD, 255);
- }
- if (btheme->tv3d.vertex_normal[3] == 0) {
- rgba_char_args_set(btheme->tv3d.vertex_normal, 0x23, 0x61, 0xDD, 255);
- }
- if (btheme->tv3d.face_dot[3] == 0) {
- rgba_char_args_set(btheme->tv3d.face_dot, 255, 138, 48, 255);
- btheme->tv3d.facedot_size = 4;
- }
- }
}
if (!USER_VERSION_ATLEAST(236, 0)) {
/* illegal combo... */
- if (U.flag & USER_LMOUSESELECT)
+ if (U.flag & USER_LMOUSESELECT)
U.flag &= ~USER_TWOBUTTONMOUSE;
}
- if (!USER_VERSION_ATLEAST(237, 0)) {
- bTheme *btheme;
- /* new space type */
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* check for (alpha == 0) is safe, then color was never set */
- if (btheme->ttime.back[3] == 0) {
- /* copied from ui_theme_init_default */
- btheme->ttime = btheme->tv3d;
- rgba_char_args_set_fl(btheme->ttime.back, 0.45, 0.45, 0.45, 1.0);
- rgba_char_args_set_fl(btheme->ttime.grid, 0.36, 0.36, 0.36, 1.0);
- rgba_char_args_set(btheme->ttime.shade1, 173, 173, 173, 255); /* sliders */
- }
- if (btheme->text.syntaxn[3] == 0) {
- rgba_char_args_set(btheme->text.syntaxn, 0, 0, 200, 255); /* Numbers Blue*/
- rgba_char_args_set(btheme->text.syntaxl, 100, 0, 0, 255); /* Strings red */
- rgba_char_args_set(btheme->text.syntaxc, 0, 100, 50, 255); /* Comments greenish */
- rgba_char_args_set(btheme->text.syntaxv, 95, 95, 0, 255); /* Special */
- rgba_char_args_set(btheme->text.syntaxb, 128, 0, 80, 255); /* Builtin, red-purple */
- }
- }
- }
- if (!USER_VERSION_ATLEAST(238, 0)) {
- bTheme *btheme;
- /* bone colors */
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* check for alpha==0 is safe, then color was never set */
- if (btheme->tv3d.bone_solid[3] == 0) {
- rgba_char_args_set(btheme->tv3d.bone_solid, 200, 200, 200, 255);
- rgba_char_args_set(btheme->tv3d.bone_pose, 80, 200, 255, 80);
- }
- }
- }
- if (!USER_VERSION_ATLEAST(239, 0)) {
- bTheme *btheme;
- /* bone colors */
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* check for alpha==0 is safe, then color was never set */
- if (btheme->tnla.strip[3] == 0) {
- rgba_char_args_set(btheme->tnla.strip_select, 0xff, 0xff, 0xaa, 255);
- rgba_char_args_set(btheme->tnla.strip, 0xe4, 0x9c, 0xc6, 255);
- }
- }
- }
if (!USER_VERSION_ATLEAST(240, 0)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* Lamp theme, check for alpha==0 is safe, then color was never set */
- if (btheme->tv3d.lamp[3] == 0) {
- rgba_char_args_set(btheme->tv3d.lamp, 0, 0, 0, 40);
-/* TEMPORAL, remove me! (ton) */
- U.uiflag |= USER_PLAINMENUS;
- }
-
- }
+ U.uiflag |= USER_PLAINMENUS;
if (U.obcenter_dia == 0) U.obcenter_dia = 6;
}
if (!USER_VERSION_ATLEAST(242, 0)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* Node editor theme, check for alpha==0 is safe, then color was never set */
- if (btheme->tnode.syntaxn[3] == 0) {
- /* re-uses syntax color storage */
- btheme->tnode = btheme->tv3d;
- rgba_char_args_set(btheme->tnode.edge_select, 255, 255, 255, 255);
- rgba_char_args_set(btheme->tnode.syntaxl, 150, 150, 150, 255); /* TH_NODE, backdrop */
- rgba_char_args_set(btheme->tnode.syntaxn, 129, 131, 144, 255); /* in/output */
- rgba_char_args_set(btheme->tnode.syntaxb, 127, 127, 127, 255); /* operator */
- rgba_char_args_set(btheme->tnode.syntaxv, 142, 138, 145, 255); /* generator */
- rgba_char_args_set(btheme->tnode.syntaxc, 120, 145, 120, 255); /* group */
- }
- /* Group theme colors */
- if (btheme->tv3d.group[3] == 0) {
- rgba_char_args_set(btheme->tv3d.group, 0x0C, 0x30, 0x0C, 255);
- rgba_char_args_set(btheme->tv3d.group_active, 0x66, 0xFF, 0x66, 255);
- }
- /* Sequence editor theme*/
- if (btheme->tseq.movie[3] == 0) {
- rgba_char_args_set(btheme->tseq.movie, 81, 105, 135, 255);
- rgba_char_args_set(btheme->tseq.image, 109, 88, 129, 255);
- rgba_char_args_set(btheme->tseq.scene, 78, 152, 62, 255);
- rgba_char_args_set(btheme->tseq.audio, 46, 143, 143, 255);
- rgba_char_args_set(btheme->tseq.effect, 169, 84, 124, 255);
- rgba_char_args_set(btheme->tseq.transition, 162, 95, 111, 255);
- rgba_char_args_set(btheme->tseq.meta, 109, 145, 131, 255);
- }
- }
-
- /* set defaults for 3D View rotating axis indicator */
+ /* set defaults for 3D View rotating axis indicator */
/* since size can't be set to 0, this indicates it's not saved in startup.blend */
if (U.rvisize == 0) {
U.rvisize = 15;
U.rvibright = 8;
U.uiflag |= USER_SHOW_ROTVIEWICON;
}
-
- }
- if (!USER_VERSION_ATLEAST(243, 0)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* long keyframe color */
- /* check for alpha==0 is safe, then color was never set */
- if (btheme->tact.strip[3] == 0) {
- rgba_char_args_set(btheme->tv3d.edge_sharp, 255, 32, 32, 255);
- rgba_char_args_set(btheme->tact.strip_select, 0xff, 0xff, 0xaa, 204);
- rgba_char_args_set(btheme->tact.strip, 0xe4, 0x9c, 0xc6, 204);
- }
-
- /* IPO-Editor - Vertex Size*/
- if (btheme->tipo.vertex_size == 0) {
- btheme->tipo.vertex_size = 3;
- }
- }
+
}
if (!USER_VERSION_ATLEAST(244, 0)) {
/* set default number of recently-used files (if not set) */
if (U.recent_files == 0) U.recent_files = 10;
}
if (!USER_VERSION_ATLEAST(245, 3)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->tv3d.editmesh_active, 255, 255, 255, 128);
- }
if (U.coba_weight.tot == 0)
BKE_colorband_init(&U.coba_weight, true);
}
if (!USER_VERSION_ATLEAST(245, 3)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* these should all use the same color */
- rgba_char_args_set(btheme->tv3d.cframe, 0x60, 0xc0, 0x40, 255);
- rgba_char_args_set(btheme->tipo.cframe, 0x60, 0xc0, 0x40, 255);
- rgba_char_args_set(btheme->tact.cframe, 0x60, 0xc0, 0x40, 255);
- rgba_char_args_set(btheme->tnla.cframe, 0x60, 0xc0, 0x40, 255);
- rgba_char_args_set(btheme->tseq.cframe, 0x60, 0xc0, 0x40, 255);
- //rgba_char_args_set(btheme->tsnd.cframe, 0x60, 0xc0, 0x40, 255); Not needed anymore
- rgba_char_args_set(btheme->ttime.cframe, 0x60, 0xc0, 0x40, 255);
- }
- }
- if (!USER_VERSION_ATLEAST(245, 3)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* action channel groups (recolor anyway) */
- rgba_char_args_set(btheme->tact.group, 0x39, 0x7d, 0x1b, 255);
- rgba_char_args_set(btheme->tact.group_active, 0x7d, 0xe9, 0x60, 255);
-
- /* bone custom-color sets */
- if (btheme->tarm[0].solid[3] == 0)
- ui_theme_init_boneColorSets(btheme);
- }
- }
- if (!USER_VERSION_ATLEAST(245, 3)) {
U.flag |= USER_ADD_VIEWALIGNED | USER_ADD_EDITMODE;
}
- if (!USER_VERSION_ATLEAST(245, 3)) {
- bTheme *btheme;
-
- /* adjust themes */
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- const char *col;
-
- /* IPO Editor: Handles/Vertices */
- col = btheme->tipo.vertex;
- rgba_char_args_set(btheme->tipo.handle_vertex, col[0], col[1], col[2], 255);
- col = btheme->tipo.vertex_select;
- rgba_char_args_set(btheme->tipo.handle_vertex_select, col[0], col[1], col[2], 255);
- btheme->tipo.handle_vertex_size = btheme->tipo.vertex_size;
-
- /* Sequence/Image Editor: colors for GPencil text */
- col = btheme->tv3d.bone_pose;
- rgba_char_args_set(btheme->tseq.bone_pose, col[0], col[1], col[2], 255);
- rgba_char_args_set(btheme->tima.bone_pose, col[0], col[1], col[2], 255);
- col = btheme->tv3d.vertex_select;
- rgba_char_args_set(btheme->tseq.vertex_select, col[0], col[1], col[2], 255);
- }
- }
if (!USER_VERSION_ATLEAST(250, 0)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* this was not properly initialized in 2.45 */
- if (btheme->tima.face_dot[3] == 0) {
- rgba_char_args_set(btheme->tima.editmesh_active, 255, 255, 255, 128);
- rgba_char_args_set(btheme->tima.face_dot, 255, 133, 0, 255);
- btheme->tima.facedot_size = 2;
- }
-
- /* DopeSheet - (Object) Channel color */
- rgba_char_args_set(btheme->tact.ds_channel, 82, 96, 110, 255);
- rgba_char_args_set(btheme->tact.ds_subchannel, 124, 137, 150, 255);
- /* DopeSheet - Group Channel color (saner version) */
- rgba_char_args_set(btheme->tact.group, 79, 101, 73, 255);
- rgba_char_args_set(btheme->tact.group_active, 135, 177, 125, 255);
-
- /* Graph Editor - (Object) Channel color */
- rgba_char_args_set(btheme->tipo.ds_channel, 82, 96, 110, 255);
- rgba_char_args_set(btheme->tipo.ds_subchannel, 124, 137, 150, 255);
- /* Graph Editor - Group Channel color */
- rgba_char_args_set(btheme->tipo.group, 79, 101, 73, 255);
- rgba_char_args_set(btheme->tipo.group_active, 135, 177, 125, 255);
-
- /* Nla Editor - (Object) Channel color */
- rgba_char_args_set(btheme->tnla.ds_channel, 82, 96, 110, 255);
- rgba_char_args_set(btheme->tnla.ds_subchannel, 124, 137, 150, 255);
- /* NLA Editor - New Strip colors */
- rgba_char_args_set(btheme->tnla.strip, 12, 10, 10, 128);
- rgba_char_args_set(btheme->tnla.strip_select, 255, 140, 0, 255);
- }
-
/* adjust grease-pencil distances */
U.gp_manhattendist = 1;
U.gp_euclideandist = 2;
-
+
/* adjust default interpolation for new IPO-curves */
U.ipo_new = BEZT_IPO_BEZ;
}
-
- if (!USER_VERSION_ATLEAST(250, 1)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
-
- /* common (new) variables, it checks for alpha==0 */
- ui_theme_init_new(btheme);
-
- if (btheme->tui.wcol_num.outline[3] == 0)
- ui_widget_color_init(&btheme->tui);
-
- rgba_char_args_set_fl(btheme->tinfo.back, 0.45, 0.45, 0.45, 1.0);
- rgba_char_args_set_fl(btheme->tuserpref.back, 0.45, 0.45, 0.45, 1.0);
- }
- }
if (!USER_VERSION_ATLEAST(250, 3)) {
/* new audio system */
@@ -2133,10 +1430,10 @@ void init_userdef_do_versions(void)
if (U.audiorate == 0)
U.audiorate = 48000;
}
-
+
if (!USER_VERSION_ATLEAST(250, 8)) {
wmKeyMap *km;
-
+
for (km = U.user_keymaps.first; km; km = km->next) {
if (STREQ(km->idname, "Armature_Sketch"))
strcpy(km->idname, "Armature Sketch");
@@ -2172,72 +1469,14 @@ void init_userdef_do_versions(void)
strcpy(km->idname, "Property Editor");
}
}
-
+
if (!USER_VERSION_ATLEAST(252, 3)) {
- if (U.flag & USER_LMOUSESELECT)
+ if (U.flag & USER_LMOUSESELECT)
U.flag &= ~USER_TWOBUTTONMOUSE;
}
if (!USER_VERSION_ATLEAST(252, 4)) {
- bTheme *btheme;
-
/* default new handle type is auto handles */
U.keyhandles_new = HD_AUTO;
-
- /* init new curve colors */
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- ui_theme_space_init_handles_color(&btheme->tv3d);
- ui_theme_space_init_handles_color(&btheme->tipo);
-
- /* edge crease */
- rgba_char_args_set_fl(btheme->tv3d.edge_crease, 0.8, 0, 0.6, 1.0);
- }
- }
- if (!USER_VERSION_ATLEAST(253, 0)) {
- bTheme *btheme;
-
- /* init new curve colors */
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if (btheme->tv3d.lastsel_point[3] == 0)
- rgba_char_args_set(btheme->tv3d.lastsel_point, 0xff, 0xff, 0xff, 255);
- }
- }
- if (!USER_VERSION_ATLEAST(252, 5)) {
- bTheme *btheme;
-
- /* interface_widgets.c */
- struct uiWidgetColors wcol_progress = {
- {0, 0, 0, 255},
- {190, 190, 190, 255},
- {100, 100, 100, 180},
- {128, 128, 128, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 0,
- 5, -5
- };
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* init progress bar theme */
- btheme->tui.wcol_progress = wcol_progress;
- }
- }
-
- if (!USER_VERSION_ATLEAST(255, 2)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->tv3d.extra_edge_len, 32, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.extra_face_angle, 0, 32, 0, 255);
- rgba_char_args_set(btheme->tv3d.extra_face_area, 0, 0, 128, 255);
- }
- }
-
- if (!USER_VERSION_ATLEAST(256, 4)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if ((btheme->tv3d.outline_width) == 0) btheme->tv3d.outline_width = 1;
- }
}
if (!USER_VERSION_ATLEAST(257, 0)) {
@@ -2246,226 +1485,22 @@ void init_userdef_do_versions(void)
U.autokey_flag &= ~AUTOKEY_FLAG_ONLYKEYINGSET;
}
- if (!USER_VERSION_ATLEAST(258, 2)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- btheme->tnode.noodle_curving = 5;
- }
- }
-
- if (!USER_VERSION_ATLEAST(259, 1)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- btheme->tv3d.speaker[3] = 255;
- }
- }
-
if (!USER_VERSION_ATLEAST(260, 3)) {
- bTheme *btheme;
-
- /* if new keyframes handle default is stuff "auto", make it "auto-clamped" instead
+ /* if new keyframes handle default is stuff "auto", make it "auto-clamped" instead
* was changed in 260 as part of GSoC11, but version patch was wrong
*/
- if (U.keyhandles_new == HD_AUTO)
+ if (U.keyhandles_new == HD_AUTO)
U.keyhandles_new = HD_AUTO_ANIM;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if (btheme->tv3d.bundle_solid[3] == 0)
- rgba_char_args_set(btheme->tv3d.bundle_solid, 200, 200, 200, 255);
-
- if (btheme->tv3d.camera_path[3] == 0)
- rgba_char_args_set(btheme->tv3d.camera_path, 0x00, 0x00, 0x00, 255);
-
- if ((btheme->tclip.back[3]) == 0) {
- btheme->tclip = btheme->tv3d;
-
- rgba_char_args_set(btheme->tclip.marker_outline, 0x00, 0x00, 0x00, 255);
- rgba_char_args_set(btheme->tclip.marker, 0x7f, 0x7f, 0x00, 255);
- rgba_char_args_set(btheme->tclip.act_marker, 0xff, 0xff, 0xff, 255);
- rgba_char_args_set(btheme->tclip.sel_marker, 0xff, 0xff, 0x00, 255);
- rgba_char_args_set(btheme->tclip.dis_marker, 0x7f, 0x00, 0x00, 255);
- rgba_char_args_set(btheme->tclip.lock_marker, 0x7f, 0x7f, 0x7f, 255);
- rgba_char_args_set(btheme->tclip.path_before, 0xff, 0x00, 0x00, 255);
- rgba_char_args_set(btheme->tclip.path_after, 0x00, 0x00, 0xff, 255);
- rgba_char_args_set(btheme->tclip.grid, 0x5e, 0x5e, 0x5e, 255);
- rgba_char_args_set(btheme->tclip.cframe, 0x60, 0xc0, 0x40, 255);
- rgba_char_args_set(btheme->tclip.handle_vertex, 0x00, 0x00, 0x00, 0xff);
- rgba_char_args_set(btheme->tclip.handle_vertex_select, 0xff, 0xff, 0, 0xff);
- btheme->tclip.handle_vertex_size = 5;
- }
-
- /* auto-clamped handles -> based on auto */
- if (btheme->tipo.handle_auto_clamped[3] == 0)
- rgba_char_args_set(btheme->tipo.handle_auto_clamped, 0x99, 0x40, 0x30, 255);
- if (btheme->tipo.handle_sel_auto_clamped[3] == 0)
- rgba_char_args_set(btheme->tipo.handle_sel_auto_clamped, 0xf0, 0xaf, 0x90, 255);
- }
/* enable (Cycles) addon by default */
BKE_addon_ensure(&U.addons, "cycles");
}
-
- if (!USER_VERSION_ATLEAST(260, 5)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->tui.panel.header, 0, 0, 0, 25);
- btheme->tui.icon_alpha = 1.0;
- }
- }
-
+
if (!USER_VERSION_ATLEAST(261, 4)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set_fl(btheme->tima.preview_stitch_face, 0.071, 0.259, 0.694, 0.150);
- rgba_char_args_set_fl(btheme->tima.preview_stitch_edge, 1.0, 0.522, 0.0, 0.7);
- rgba_char_args_set_fl(btheme->tima.preview_stitch_vert, 1.0, 0.522, 0.0, 0.5);
- rgba_char_args_set_fl(btheme->tima.preview_stitch_stitchable, 0.0, 1.0, 0.0, 1.0);
- rgba_char_args_set_fl(btheme->tima.preview_stitch_unstitchable, 1.0, 0.0, 0.0, 1.0);
- rgba_char_args_set_fl(btheme->tima.preview_stitch_active, 0.886, 0.824, 0.765, 0.140);
-
- rgba_char_args_set_fl(btheme->toops.match, 0.2, 0.5, 0.2, 0.3);
- rgba_char_args_set_fl(btheme->toops.selected_highlight, 0.51, 0.53, 0.55, 0.3);
- }
-
U.use_16bit_textures = true;
}
- if (!USER_VERSION_ATLEAST(262, 2)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if (btheme->tui.wcol_menu_item.item[3] == 255)
- rgba_char_args_set(btheme->tui.wcol_menu_item.item, 172, 172, 172, 128);
- }
- }
-
- if (!USER_VERSION_ATLEAST(262, 3)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if (btheme->tui.wcol_tooltip.inner[3] == 0) {
- btheme->tui.wcol_tooltip = btheme->tui.wcol_menu_back;
- }
- if (btheme->tui.wcol_tooltip.text[0] == 160) { /* hrmf */
- rgba_char_args_set(btheme->tui.wcol_tooltip.text, 255, 255, 255, 255);
- }
- }
- }
-
- if (!USER_VERSION_ATLEAST(262, 4)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if (btheme->tseq.movieclip[3] == 0) {
- rgba_char_args_set(btheme->tseq.movieclip, 32, 32, 143, 255);
- }
- }
- }
-
- if (!USER_VERSION_ATLEAST(263, 2)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if (btheme->tclip.strip[0] == 0) {
- rgba_char_args_set(btheme->tclip.list, 0x66, 0x66, 0x66, 0xff);
- rgba_char_args_set(btheme->tclip.strip, 0x0c, 0x0a, 0x0a, 0x80);
- rgba_char_args_set(btheme->tclip.strip_select, 0xff, 0x8c, 0x00, 0xff);
- }
- }
- }
-
- if (!USER_VERSION_ATLEAST(263, 6)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next)
- rgba_char_args_set(btheme->tv3d.skin_root, 180, 77, 77, 255);
- }
-
- if (!USER_VERSION_ATLEAST(263, 7)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* DopeSheet Summary */
- rgba_char_args_set(btheme->tact.anim_active, 204, 112, 26, 102);
-
- /* NLA Colors */
- rgba_char_args_set(btheme->tnla.anim_active, 204, 112, 26, 102); /* same as dopesheet above */
- rgba_char_args_set(btheme->tnla.anim_non_active, 153, 135, 97, 77);
-
- rgba_char_args_set(btheme->tnla.nla_tweaking, 77, 243, 26, 77);
- rgba_char_args_set(btheme->tnla.nla_tweakdupli, 217, 0, 0, 255);
-
- rgba_char_args_set(btheme->tnla.nla_transition, 28, 38, 48, 255);
- rgba_char_args_set(btheme->tnla.nla_transition_sel, 46, 117, 219, 255);
- rgba_char_args_set(btheme->tnla.nla_meta, 51, 38, 66, 255);
- rgba_char_args_set(btheme->tnla.nla_meta_sel, 105, 33, 150, 255);
- rgba_char_args_set(btheme->tnla.nla_sound, 43, 61, 61, 255);
- rgba_char_args_set(btheme->tnla.nla_sound_sel, 31, 122, 122, 255);
- }
- }
-
- if (!USER_VERSION_ATLEAST(263, 11)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if (btheme->tseq.mask[3] == 0) {
- rgba_char_args_set(btheme->tseq.mask, 152, 78, 62, 255);
- }
- }
- }
-
- if (!USER_VERSION_ATLEAST(263, 15)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->tv3d.bone_pose_active, 140, 255, 255, 80);
- }
- }
-
- if (!USER_VERSION_ATLEAST(263, 16)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if (btheme->tact.anim_active[3] == 0)
- rgba_char_args_set(btheme->tact.anim_active, 204, 112, 26, 102);
-
- if (btheme->tnla.anim_active[3] == 0)
- rgba_char_args_set(btheme->tnla.anim_active, 204, 112, 26, 102);
- }
- }
-
- if (!USER_VERSION_ATLEAST(263, 22)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if (btheme->tipo.lastsel_point[3] == 0)
- rgba_char_args_set(btheme->tipo.lastsel_point, 0xff, 0xff, 0xff, 255);
-
- if (btheme->tv3d.skin_root[3] == 0)
- rgba_char_args_set(btheme->tv3d.skin_root, 180, 77, 77, 255);
- }
- }
-
- if (!USER_VERSION_ATLEAST(264, 9)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->tui.xaxis, 220, 0, 0, 255);
- rgba_char_args_set(btheme->tui.yaxis, 0, 220, 0, 255);
- rgba_char_args_set(btheme->tui.zaxis, 0, 0, 220, 255);
- }
- }
-
if (!USER_VERSION_ATLEAST(267, 0)) {
- /* Freestyle color settings */
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* check for alpha == 0 is safe, then color was never set */
- if (btheme->tv3d.freestyle_edge_mark[3] == 0) {
- rgba_char_args_set(btheme->tv3d.freestyle_edge_mark, 0x7f, 0xff, 0x7f, 255);
- rgba_char_args_set(btheme->tv3d.freestyle_face_mark, 0x7f, 0xff, 0x7f, 51);
- }
-
- if (btheme->tv3d.wire_edit[3] == 0) {
- rgba_char_args_set(btheme->tv3d.wire_edit, 0x0, 0x0, 0x0, 255);
- }
- }
/* GL Texture Garbage Collection */
if (U.textimeout == 0) {
@@ -2478,10 +1513,6 @@ void init_userdef_do_versions(void)
if (U.dbl_click_time == 0) {
U.dbl_click_time = 350;
}
- if (U.scrcastfps == 0) {
- U.scrcastfps = 10;
- U.scrcastwait = 50;
- }
if (U.v2d_min_gridsize == 0) {
U.v2d_min_gridsize = 35;
}
@@ -2496,7 +1527,7 @@ void init_userdef_do_versions(void)
U.ndof_sensitivity = 1.0f;
U.ndof_flag = (NDOF_LOCK_HORIZON | NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM | NDOF_SHOULD_ROTATE);
}
-
+
if (U.ndof_orbit_sensitivity == 0.0f) {
U.ndof_orbit_sensitivity = U.ndof_sensitivity;
@@ -2507,175 +1538,12 @@ void init_userdef_do_versions(void)
U.tweak_threshold = 10;
}
- if (!USER_VERSION_ATLEAST(265, 1)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* note: the toggle operator for transparent backdrops limits to these spacetypes */
- if (btheme->tnode.button[3] == 255) {
- btheme->tv3d.button[3] = 128;
- btheme->tnode.button[3] = 128;
- btheme->tima.button[3] = 128;
- btheme->tseq.button[3] = 128;
- btheme->tclip.button[3] = 128;
- }
- }
- }
-
- /* panel header/backdrop supported locally per editor now */
- if (!USER_VERSION_ATLEAST(265, 2)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- ThemeSpace *ts;
-
- /* new color, panel backdrop. Not used anywhere yet, until you enable it */
- copy_v3_v3_char(btheme->tui.panel.back, btheme->tbuts.button);
- btheme->tui.panel.back[3] = 128;
-
- for (ts = UI_THEMESPACE_START(btheme); ts != UI_THEMESPACE_END(btheme); ts++) {
- ts->panelcolors = btheme->tui.panel;
- }
- }
- }
-
/* NOTE!! from now on use U.versionfile and U.subversionfile */
#undef USER_VERSION_ATLEAST
#define USER_VERSION_ATLEAST(ver, subver) MAIN_VERSION_ATLEAST((&(U)), ver, subver)
- if (!USER_VERSION_ATLEAST(266, 0)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* rna definition limits fac to 0.01 */
- if (btheme->tui.menu_shadow_fac == 0.0f) {
- btheme->tui.menu_shadow_fac = 0.5f;
- btheme->tui.menu_shadow_width = 12;
- }
- }
- }
-
- if (!USER_VERSION_ATLEAST(265, 4)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->text.syntaxd, 50, 0, 140, 255); /* Decorator/Preprocessor Dir. Blue-purple */
- rgba_char_args_set(btheme->text.syntaxr, 140, 60, 0, 255); /* Reserved Orange */
- rgba_char_args_set(btheme->text.syntaxs, 76, 76, 76, 255); /* Gray (mix between fg/bg) */
- }
- }
-
- if (!USER_VERSION_ATLEAST(265, 6)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- copy_v4_v4_char(btheme->tv3d.gradients.high_gradient, btheme->tv3d.back);
- }
- }
-
- if (!USER_VERSION_ATLEAST(265, 9)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_test_set(btheme->tnode.syntaxs, 151, 116, 116, 255); /* matte nodes */
- rgba_char_args_test_set(btheme->tnode.syntaxd, 116, 151, 151, 255); /* distort nodes */
- }
- }
-
- if (!USER_VERSION_ATLEAST(265, 11)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_test_set(btheme->tconsole.console_select, 255, 255, 255, 48);
- }
- }
-
- if (!USER_VERSION_ATLEAST(266, 2)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_test_set(btheme->tnode.console_output, 223, 202, 53, 255); /* interface nodes */
- }
- }
-
- if (!USER_VERSION_ATLEAST(268, 3)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_test_set(btheme->tima.uv_others, 96, 96, 96, 255);
- rgba_char_args_test_set(btheme->tima.uv_shadow, 112, 112, 112, 255);
- }
- }
-
- if (!USER_VERSION_ATLEAST(269, 5)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->tima.wire_edit, 192, 192, 192, 255);
- rgba_char_args_set(btheme->tima.edge_select, 255, 133, 0, 255);
- }
- }
- if (!USER_VERSION_ATLEAST(269, 6)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- char r, g, b;
- r = btheme->tnode.syntaxn[0];
- g = btheme->tnode.syntaxn[1];
- b = btheme->tnode.syntaxn[2];
- rgba_char_args_test_set(btheme->tnode.nodeclass_output, r, g, b, 255);
- r = btheme->tnode.syntaxb[0];
- g = btheme->tnode.syntaxb[1];
- b = btheme->tnode.syntaxb[2];
- rgba_char_args_test_set(btheme->tnode.nodeclass_filter, r, g, b, 255);
- rgba_char_args_test_set(btheme->tnode.nodeclass_vector, r, g, b, 255);
- rgba_char_args_test_set(btheme->tnode.nodeclass_texture, r, g, b, 255);
- rgba_char_args_test_set(btheme->tnode.nodeclass_shader, r, g, b, 255);
- rgba_char_args_test_set(btheme->tnode.nodeclass_script, r, g, b, 255);
- rgba_char_args_test_set(btheme->tnode.nodeclass_pattern, r, g, b, 255);
- rgba_char_args_test_set(btheme->tnode.nodeclass_layout, r, g, b, 255);
- }
- }
-
- if (!USER_VERSION_ATLEAST(269, 8)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_test_set(btheme->tinfo.info_selected, 96, 128, 255, 255);
- rgba_char_args_test_set(btheme->tinfo.info_selected_text, 255, 255, 255, 255);
- rgba_char_args_test_set(btheme->tinfo.info_error, 220, 0, 0, 255);
- rgba_char_args_test_set(btheme->tinfo.info_error_text, 0, 0, 0, 255);
- rgba_char_args_test_set(btheme->tinfo.info_warning, 220, 128, 96, 255);
- rgba_char_args_test_set(btheme->tinfo.info_warning_text, 0, 0, 0, 255);
- rgba_char_args_test_set(btheme->tinfo.info_info, 0, 170, 0, 255);
- rgba_char_args_test_set(btheme->tinfo.info_info_text, 0, 0, 0, 255);
- rgba_char_args_test_set(btheme->tinfo.info_debug, 196, 196, 196, 255);
- rgba_char_args_test_set(btheme->tinfo.info_debug_text, 0, 0, 0, 255);
- }
- }
-
if (!USER_VERSION_ATLEAST(269, 9)) {
- bTheme *btheme;
- /* Action Editor (and NLA Editor) - Keyframe Colors */
- /* Graph Editor - larger vertex size defaults */
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* Action Editor ................. */
- /* key types */
- rgba_char_args_set(btheme->tact.keytype_keyframe, 232, 232, 232, 255);
- rgba_char_args_set(btheme->tact.keytype_keyframe_select, 255, 190, 50, 255);
- rgba_char_args_set(btheme->tact.keytype_extreme, 232, 179, 204, 255);
- rgba_char_args_set(btheme->tact.keytype_extreme_select, 242, 128, 128, 255);
- rgba_char_args_set(btheme->tact.keytype_breakdown, 179, 219, 232, 255);
- rgba_char_args_set(btheme->tact.keytype_breakdown_select, 84, 191, 237, 255);
- rgba_char_args_set(btheme->tact.keytype_jitter, 148, 229, 117, 255);
- rgba_char_args_set(btheme->tact.keytype_jitter_select, 97, 192, 66, 255);
-
- /* key border */
- rgba_char_args_set(btheme->tact.keyborder, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tact.keyborder_select, 0, 0, 0, 255);
-
- /* NLA ............................ */
- /* key border */
- rgba_char_args_set(btheme->tnla.keyborder, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tnla.keyborder_select, 0, 0, 0, 255);
-
- /* Graph Editor ................... */
- btheme->tipo.vertex_size = 6;
- btheme->tipo.handle_vertex_size = 5;
- }
-
/* grease pencil - new layer color */
if (U.gpencil_new_layer_col[3] < 0.1f) {
/* defaults to black, but must at least be visible! */
@@ -2683,139 +1551,10 @@ void init_userdef_do_versions(void)
}
}
- if (!USER_VERSION_ATLEAST(269, 10)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- ThemeSpace *ts;
-
- for (ts = UI_THEMESPACE_START(btheme); ts != UI_THEMESPACE_END(btheme); ts++) {
- rgba_char_args_set(ts->tab_active, 114, 114, 114, 255);
- rgba_char_args_set(ts->tab_inactive, 83, 83, 83, 255);
- rgba_char_args_set(ts->tab_back, 64, 64, 64, 255);
- rgba_char_args_set(ts->tab_outline, 60, 60, 60, 255);
- }
- }
- }
-
- if (!USER_VERSION_ATLEAST(271, 0)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->tui.wcol_tooltip.text, 255, 255, 255, 255);
- }
- }
-
- if (!USER_VERSION_ATLEAST(272, 2)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set_fl(btheme->tv3d.paint_curve_handle, 0.5f, 1.0f, 0.5f, 0.5f);
- rgba_char_args_set_fl(btheme->tv3d.paint_curve_pivot, 1.0f, 0.5f, 0.5f, 0.5f);
- rgba_char_args_set_fl(btheme->tima.paint_curve_handle, 0.5f, 1.0f, 0.5f, 0.5f);
- rgba_char_args_set_fl(btheme->tima.paint_curve_pivot, 1.0f, 0.5f, 0.5f, 0.5f);
- rgba_char_args_set(btheme->tnode.syntaxr, 115, 115, 115, 255);
- }
- }
-
if (!USER_VERSION_ATLEAST(271, 5)) {
- bTheme *btheme;
-
- struct uiWidgetColors wcol_pie_menu = {
- {10, 10, 10, 200},
- {25, 25, 25, 230},
- {140, 140, 140, 255},
- {45, 45, 45, 230},
-
- {160, 160, 160, 255},
- {255, 255, 255, 255},
-
- 1,
- 10, -10
- };
-
U.pie_menu_radius = 100;
U.pie_menu_threshold = 12;
U.pie_animation_timeout = 6;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- btheme->tui.wcol_pie_menu = wcol_pie_menu;
-
- ui_theme_space_init_handles_color(&btheme->tclip);
- ui_theme_space_init_handles_color(&btheme->tima);
- btheme->tima.handle_vertex_size = 5;
- btheme->tclip.handle_vertex_size = 5;
- }
- }
-
- if (!USER_VERSION_ATLEAST(271, 6)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* check for (alpha == 0) is safe, then color was never set */
- if (btheme->tv3d.loop_normal[3] == 0) {
- rgba_char_args_set(btheme->tv3d.loop_normal, 0xDD, 0x23, 0xDD, 255);
- }
- }
- }
-
- if (!USER_VERSION_ATLEAST(272, 3)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set_fl(btheme->tui.widget_emboss, 1.0f, 1.0f, 1.0f, 0.02f);
- }
- }
-
- if (!USER_VERSION_ATLEAST(273, 1)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* Grease Pencil vertex settings */
- rgba_char_args_set(btheme->tv3d.gp_vertex, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.gp_vertex_select, 255, 133, 0, 255);
- btheme->tv3d.gp_vertex_size = 3;
-
- rgba_char_args_set(btheme->tseq.gp_vertex, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tseq.gp_vertex_select, 255, 133, 0, 255);
- btheme->tseq.gp_vertex_size = 3;
-
- rgba_char_args_set(btheme->tima.gp_vertex, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tima.gp_vertex_select, 255, 133, 0, 255);
- btheme->tima.gp_vertex_size = 3;
-
- rgba_char_args_set(btheme->tnode.gp_vertex, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tnode.gp_vertex_select, 255, 133, 0, 255);
- btheme->tnode.gp_vertex_size = 3;
- }
- }
-
- if (!USER_VERSION_ATLEAST(273, 5)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- unsigned char *cp = (unsigned char *)btheme->tv3d.clipping_border_3d;
- int c;
- copy_v4_v4_char((char *)cp, btheme->tv3d.back);
- c = cp[0] - 8;
- CLAMP(c, 0, 255);
- cp[0] = c;
- c = cp[1] - 8;
- CLAMP(c, 0, 255);
- cp[1] = c;
- c = cp[2] - 8;
- CLAMP(c, 0, 255);
- cp[2] = c;
- cp[3] = 255;
- }
- }
-
- if (!USER_VERSION_ATLEAST(274, 5)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- copy_v4_v4_char(btheme->tima.metadatatext, btheme->tima.text_hi);
- copy_v4_v4_char(btheme->tseq.metadatatext, btheme->tseq.text_hi);
- }
- }
-
- if (!USER_VERSION_ATLEAST(275, 1)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- copy_v4_v4_char(btheme->tclip.metadatatext, btheme->tseq.text_hi);
- }
}
if (!USER_VERSION_ATLEAST(275, 2)) {
@@ -2826,85 +1565,12 @@ void init_userdef_do_versions(void)
U.node_margin = 80;
}
- if (!USER_VERSION_ATLEAST(276, 1)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set_fl(btheme->tima.preview_back, 0.0f, 0.0f, 0.0f, 0.3f);
- }
- }
-
- if (!USER_VERSION_ATLEAST(276, 2)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->tclip.gp_vertex, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tclip.gp_vertex_select, 255, 133, 0, 255);
- btheme->tclip.gp_vertex_size = 3;
- }
- }
-
- if (!USER_VERSION_ATLEAST(276, 3)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->tseq.text_strip, 162, 151, 0, 255);
- }
- }
-
- if (!USER_VERSION_ATLEAST(276, 8)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->tui.wcol_progress.item, 128, 128, 128, 255);
- }
- }
-
- if (!USER_VERSION_ATLEAST(276, 10)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* 3dView Keyframe Indicators */
- rgba_char_args_set(btheme->tv3d.time_keyframe, 0xDD, 0xD7, 0x00, 0xFF);
- rgba_char_args_set(btheme->tv3d.time_gp_keyframe, 0xB5, 0xE6, 0x1D, 0xFF);
- }
- }
-
- if (!USER_VERSION_ATLEAST(277, 0)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if (memcmp(btheme->tui.wcol_list_item.item, btheme->tui.wcol_list_item.text_sel, sizeof(char) * 3) == 0) {
- copy_v4_v4_char(btheme->tui.wcol_list_item.item, btheme->tui.wcol_text.item);
- copy_v4_v4_char(btheme->tui.wcol_list_item.text_sel, btheme->tui.wcol_text.text_sel);
- }
- }
- }
-
- if (!USER_VERSION_ATLEAST(277, 2)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if (btheme->tact.keyframe_scale_fac < 0.1f)
- btheme->tact.keyframe_scale_fac = 1.0f;
- }
- }
-
- if (!USER_VERSION_ATLEAST(278, 2)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->tv3d.vertex_bevel, 0, 165, 255, 255);
- rgba_char_args_set(btheme->tv3d.edge_bevel, 0, 165, 255, 255);
- }
- }
-
- if (!USER_VERSION_ATLEAST(278, 3)) {
- for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* Keyframe Indicators (were using wrong alpha) */
- btheme->tv3d.time_keyframe[3] = btheme->tv3d.time_gp_keyframe[3] = 255;
- btheme->ttime.time_keyframe[3] = btheme->ttime.time_gp_keyframe[3] = 255;
- }
- }
-
if (!USER_VERSION_ATLEAST(278, 6)) {
/* Clear preference flags for re-use. */
U.flag &= ~(
USER_FLAG_DEPRECATED_1 | USER_FLAG_DEPRECATED_2 | USER_FLAG_DEPRECATED_3 |
USER_FLAG_DEPRECATED_6 | USER_FLAG_DEPRECATED_7 |
- USER_FLAG_DEPRECATED_9 | USER_FLAG_DEPRECATED_10);
+ USER_FLAG_DEPRECATED_9 | USER_DEVELOPER_UI);
U.uiflag &= ~(
USER_UIFLAG_DEPRECATED_7);
U.transopts &= ~(
@@ -2914,90 +1580,13 @@ void init_userdef_do_versions(void)
U.uiflag |= USER_LOCK_CURSOR_ADJUST;
}
- if (!USER_VERSION_ATLEAST(280, 9)) {
- /* interface_widgets.c */
- struct uiWidgetColors wcol_tab = {
- {60, 60, 60, 255},
- {83, 83, 83, 255},
- {114, 114, 114, 255},
- {90, 90, 90, 255},
-
- {0, 0, 0, 255},
- {0, 0, 0, 255},
- 0,
- 0, 0
- };
+ if (!USER_VERSION_ATLEAST(280, 20)) {
+ U.gpu_viewport_quality = 0.6f;
+ /* Reset theme, old themes will not be compatible with minor version updates from now on. */
for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) {
- char tmp[4];
-
- btheme->tui.wcol_tab = wcol_tab;
- btheme->ttopbar = btheme->tv3d;
- /* swap colors */
- copy_v4_v4_char(tmp, btheme->ttopbar.header);
- copy_v4_v4_char(btheme->ttopbar.header, btheme->ttopbar.tab_inactive);
- copy_v4_v4_char(btheme->ttopbar.back, tmp);
- }
- }
-
- if (!USER_VERSION_ATLEAST(280, 9)) {
- /* Timeline removal */
- for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) {
- if (btheme->tipo.anim_active[3] == 0) {
- rgba_char_args_set(btheme->tipo.anim_active, 204, 112, 26, 102);
- }
- if (btheme->tseq.anim_active[3] == 0) {
- rgba_char_args_set(btheme->tseq.anim_active, 204, 112, 26, 102);
- }
- }
- }
-
- if (!USER_VERSION_ATLEAST(280, 10)) {
- /* Roundness */
- for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) {
- btheme->tui.wcol_regular.roundness = 0.25f;
- btheme->tui.wcol_tool.roundness = 0.2f;
- btheme->tui.wcol_text.roundness = 0.2f;
- btheme->tui.wcol_radio.roundness = 0.2f;
- btheme->tui.wcol_option.roundness = 0.333333f;
- btheme->tui.wcol_toggle.roundness = 0.25f;
- btheme->tui.wcol_num.roundness = 0.5f;
- btheme->tui.wcol_numslider.roundness = 0.5f;
- btheme->tui.wcol_tab.roundness = 0.25f;
- btheme->tui.wcol_menu.roundness = 0.2f;
- btheme->tui.wcol_pulldown.roundness = 0.2f;
- btheme->tui.wcol_menu_back.roundness = 0.25f;
- btheme->tui.wcol_menu_item.roundness = 0.25f;
- btheme->tui.wcol_tooltip.roundness = 0.25f;
- btheme->tui.wcol_box.roundness = 0.2f;
- btheme->tui.wcol_scroll.roundness = 0.5f;
- btheme->tui.wcol_progress.roundness = 0.25f;
- btheme->tui.wcol_list_item.roundness = 0.2f;
- btheme->tui.wcol_pie_menu.roundness = 0.5f;
- rgba_char_args_set_fl(btheme->tui.editor_outline, 0.25f, 0.25f, 0.25f, 1.0f);
- }
- }
-
- if (((bTheme *)U.themes.first)->tui.wcol_toolbar_item.text[3] == 0) {
- struct uiWidgetColors wcol_toolbar_item = {
- .outline = {0x0, 0x0, 0x0, 0xff},
- .inner = {0x46, 0x46, 0x46, 0xff},
- .inner_sel = {0xcc, 0xcc, 0xcc, 0xff},
- .item = {0x0, 0x0, 0x0, 0xff},
-
- .text = {0xff, 0xff, 0xff, 0xff},
- .text_sel = {0x33, 0x33, 0x33, 0xff},
-
- .shaded = 0,
- .shadetop = 0,
- .shadedown = 0,
- .alpha_check = 0,
- .roundness = 0.3f,
- };
- for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) {
- btheme->tui.wcol_toolbar_item = wcol_toolbar_item;
- btheme->tui.icon_saturation = 1.0f;
+ memcpy(btheme, &U_theme_default, sizeof(*btheme));
}
}
@@ -3008,18 +1597,12 @@ void init_userdef_do_versions(void)
/* (keep this block even if it becomes empty). */
}
- if (((bTheme *)U.themes.first)->tui.manipulator_hi[3] == 0) {
- for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) {
- ui_theme_space_init_manipulator_colors(btheme);
- }
- }
-
if (U.pixelsize == 0.0f)
U.pixelsize = 1.0f;
-
+
if (U.image_draw_method == 0)
U.image_draw_method = IMAGE_DRAW_METHOD_2DTEXTURE;
-
+
// we default to the first audio device
U.audiodevice = 0;
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index c1791998ec7..4e9d1fad6e0 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -17,7 +17,7 @@
*
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
- *
+ *
* Contributor(s): Blender Foundation, Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
@@ -51,6 +51,7 @@
#include "GPU_immediate.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "WM_api.h"
@@ -119,7 +120,7 @@ static int view2d_scroll_mapped(int scroll)
static void view2d_masks(View2D *v2d, bool check_scrollers)
{
int scroll;
-
+
/* mask - view frame */
v2d->mask.xmin = v2d->mask.ymin = 0;
v2d->mask.xmax = v2d->winx - 1; /* -1 yes! masks are pixels */
@@ -144,9 +145,9 @@ static void view2d_masks(View2D *v2d, bool check_scrollers)
}
}
}
-
+
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)
@@ -170,7 +171,7 @@ static void view2d_masks(View2D *v2d, bool check_scrollers)
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 */
@@ -182,7 +183,7 @@ static void view2d_masks(View2D *v2d, bool check_scrollers)
v2d->hor = v2d->mask;
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)) {
@@ -225,20 +226,20 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
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
+
+ /* 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? */
@@ -251,28 +252,28 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
/* 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.
+ /* '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;
}
@@ -282,14 +283,14 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
/* 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);
}
@@ -297,10 +298,10 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
v2d->keeptot = V2D_KEEPTOT_STRICT;
tot_changed = do_init;
-
+
/* panning in y-axis is prohibited */
v2d->keepofs = V2D_LOCKOFS_Y;
-
+
/* absolutely no scrollers allowed */
v2d->scroll = 0;
break;
@@ -308,15 +309,15 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
/* 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);
@@ -327,16 +328,16 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
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;
}
@@ -347,29 +348,29 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
/* 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);
-
+
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);
-
+
}
/**
@@ -382,16 +383,16 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
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
@@ -399,7 +400,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
* - 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
@@ -409,14 +410,14 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
/* 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
+
+ /* 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
*/
@@ -424,7 +425,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
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;
@@ -445,11 +446,11 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
height *= zoom / oldzoom;
}
}
- /* keepzoom (V2D_LIMITZOOM set), indicates that zoom level on each axis must not exceed limits
+ /* 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;
@@ -460,7 +461,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
width = winx / v2d->maxzoom;
}
}
-
+
/* check if excessive zoom on y-axis */
if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) {
const float zoom = winy / height;
@@ -477,21 +478,21 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
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. thats why it stores 'old'
+ * find which is the best new 'cur' rect. thats 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) {
@@ -508,7 +509,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
}
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):
@@ -518,12 +519,12 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
*/
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!
+
+ /* width does not get modified, as keepaspect here is just set to make
+ * sure visible area adjusts to changing view shape!
*/
}
}
@@ -540,7 +541,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
if (winy < v2d->oldwiny) {
float temp = v2d->oldwiny - winy;
-
+
if (v2d->align & V2D_ALIGN_NO_NEG_Y) {
cur->ymin -= temp;
cur->ymax -= temp;
@@ -557,16 +558,16 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
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) {
@@ -581,7 +582,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
else {
temp = BLI_rctf_cent_x(cur);
dh = width * 0.5f;
-
+
cur->xmin = temp - dh;
cur->xmax = temp + dh;
}
@@ -599,21 +600,21 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
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 */
@@ -621,28 +622,28 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
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)
+ /* 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
+ /* - 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;
}
@@ -656,7 +657,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
/* 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!)
@@ -665,28 +666,28 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
/* 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
+ /* - 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;
}
@@ -696,7 +697,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
}
}
}
-
+
/* height */
if ((curheight > totheight) && !(v2d->keepzoom & (V2D_KEEPZOOM | V2D_LOCKZOOM_Y | V2D_LIMITZOOM))) {
/* if zoom doesn't have to be maintained, just clamp edges */
@@ -707,7 +708,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
/* 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
*/
@@ -715,37 +716,37 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
/* 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
+ * 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
+ * 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 */
@@ -761,7 +762,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
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 */
@@ -778,7 +779,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
}
}
}
-
+
/* set masks */
view2d_masks(v2d, mask_scrollers);
}
@@ -795,11 +796,11 @@ 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) {
@@ -817,14 +818,14 @@ void UI_view2d_sync(bScreen *screen, ScrArea *area, View2D *v2dcur, int flag)
v2dcur->cur.ymin = ar->v2d.cur.ymin;
v2dcur->cur.ymax = ar->v2d.cur.ymax;
}
-
+
/* region possibly changed, so refresh */
- ED_region_tag_redraw(ar);
+ 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) {
@@ -843,9 +844,9 @@ void UI_view2d_sync(bScreen *screen, ScrArea *area, View2D *v2dcur, int flag)
v2dcur->cur.xmin = ar->v2d.cur.xmin;
v2dcur->cur.xmax = ar->v2d.cur.xmax;
}
-
+
/* region possibly changed, so refresh */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw_no_rebuild(ar);
}
}
}
@@ -861,11 +862,11 @@ void UI_view2d_sync(bScreen *screen, ScrArea *area, View2D *v2dcur, int flag)
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 */
@@ -880,11 +881,11 @@ void UI_view2d_curRect_reset(View2D *v2d)
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 */
@@ -899,7 +900,7 @@ void UI_view2d_curRect_reset(View2D *v2d)
else {
/* height is centered around (y == 0) */
const float dy = height / 2.0f;
-
+
v2d->cur.ymin = -dy;
v2d->cur.ymax = dy;
}
@@ -911,11 +912,11 @@ void UI_view2d_curRect_reset(View2D *v2d)
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 */
@@ -923,13 +924,13 @@ void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, bool resiz
// 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 */
@@ -944,11 +945,11 @@ void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, bool resiz
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 */
@@ -963,14 +964,14 @@ void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, bool resiz
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)
@@ -978,12 +979,12 @@ void UI_view2d_totRect_set(View2D *v2d, int width, int height)
int scroll = view2d_scroll_mapped(v2d->scroll);
UI_view2d_totRect_set_resize(v2d, width, height, 0);
-
+
/* solve bad recursion... if scroller state changed, mask is different, so you get different rects */
if (scroll != view2d_scroll_mapped(v2d->scroll)) {
UI_view2d_totRect_set_resize(v2d, width, height, 0);
}
-
+
}
bool UI_view2d_tab_set(View2D *v2d, int tab)
@@ -1054,21 +1055,21 @@ void UI_view2d_zoom_cache_reset(void)
static void view2d_map_cur_using_mask(View2D *v2d, rctf *curmasked)
{
*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)
curmasked->xmin -= dx * (float)v2d->mask.xmin;
if (v2d->mask.xmax + 1 != v2d->winx)
curmasked->xmax += dx * (float)(v2d->winx - v2d->mask.xmax - 1);
-
+
if (v2d->mask.ymin != 0)
curmasked->ymin -= dy * (float)v2d->mask.ymin;
if (v2d->mask.ymax + 1 != v2d->winy)
@@ -1085,7 +1086,7 @@ void UI_view2d_view_ortho(View2D *v2d)
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
*/
@@ -1095,12 +1096,12 @@ void UI_view2d_view_ortho(View2D *v2d)
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);
@@ -1110,7 +1111,7 @@ void UI_view2d_view_ortho(View2D *v2d)
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);
}
@@ -1124,23 +1125,23 @@ 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);
-}
+}
/* Restore view matrices after drawing */
@@ -1149,10 +1150,10 @@ 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;
-
+
wmOrtho2(0.0f, (float)width, 0.0f, (float)height);
gpuLoadIdentity();
-
+
// ED_region_pixelspace(CTX_wm_region(C));
}
@@ -1173,25 +1174,25 @@ static void step_to_grid(float *step, int *power, int unit)
{
const float loga = (float)log10(*step);
float rem;
-
+
*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;
*step = 2.0f; /* use 2 since there are grid lines drawn in between, this way to get 1 line per frane */
}
-
+
/* prevents printing 1.0 2.0 3.0 etc */
if (rem == 1.0f) (*power)++;
}
@@ -1199,9 +1200,9 @@ static void step_to_grid(float *step, int *power, int unit)
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)++;
@@ -1229,14 +1230,14 @@ View2DGrid *UI_view2d_grid_calc(
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);
@@ -1244,7 +1245,7 @@ View2DGrid *UI_view2d_grid_calc(
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);
@@ -1257,14 +1258,14 @@ View2DGrid *UI_view2d_grid_calc(
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);
@@ -1281,7 +1282,7 @@ View2DGrid *UI_view2d_grid_calc(
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));
@@ -1289,14 +1290,14 @@ View2DGrid *UI_view2d_grid_calc(
}
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;
}
@@ -1308,7 +1309,7 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
int vertical_minor_step = (BLI_rcti_size_x(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC),
horizontal_major_step = (BLI_rcti_size_y(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC);
unsigned char grid_line_color[3];
-
+
/* check for grid first, as it may not exist */
if (grid == NULL)
return;
@@ -1351,47 +1352,47 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
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++) {
immSkipAttrib(color);
immVertex2fv(pos, vec1);
immAttrib3ubv(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++) {
immSkipAttrib(color);
immVertex2fv(pos, vec1);
immAttrib3ubv(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++) {
@@ -1399,14 +1400,14 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
immVertex2fv(pos, vec1);
immAttrib3ubv(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++) {
@@ -1414,33 +1415,33 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
immVertex2fv(pos, vec1);
immAttrib3ubv(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;
-
+
immSkipAttrib(color);
immVertex2fv(pos, vec1);
immAttrib3ubv(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;
-
+
immSkipAttrib(color);
immVertex2fv(pos, vec1);
immAttrib3ubv(color, grid_line_color);
@@ -1456,7 +1457,7 @@ 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);
@@ -1478,7 +1479,7 @@ void UI_view2d_constant_grid_draw(View2D *v2d, float step)
count_y = 0;
else
count_y = (v2d->cur.ymax - start_y) / step + 1;
-
+
if (count_x > 0 || count_y > 0) {
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -1486,10 +1487,10 @@ void UI_view2d_constant_grid_draw(View2D *v2d, float step)
float theme_color[3];
UI_GetThemeColorShade3fv(TH_BACK, -10, theme_color);
-
+
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
immBegin(GWN_PRIM_LINES, count_x * 2 + count_y * 2 + 4);
-
+
immAttrib3fv(color, theme_color);
for (int i = 0; i < count_x ; start_x += step, i++) {
immVertex2f(pos, start_x, v2d->cur.ymin);
@@ -1500,16 +1501,16 @@ void UI_view2d_constant_grid_draw(View2D *v2d, float step)
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);
-
+
immAttrib3fv(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();
}
@@ -1535,19 +1536,19 @@ void UI_view2d_multi_grid_draw(View2D *v2d, int colorid, float step, int level_s
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
immBeginAtMost(GWN_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;
@@ -1557,12 +1558,12 @@ void UI_view2d_multi_grid_draw(View2D *v2d, int colorid, float step, int level_s
immAttrib3ubv(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;
@@ -1572,7 +1573,7 @@ void UI_view2d_multi_grid_draw(View2D *v2d, int colorid, float step, int level_s
immAttrib3ubv(color, grid_line_color);
immVertex2f(pos, v2d->cur.xmax, start);
}
-
+
lstep *= level_size;
offset -= 6;
}
@@ -1623,10 +1624,10 @@ struct View2DScrollers {
/* 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 */
-
+
/* scales */
View2DGrid *grid; /* grid for coordinate drawing */
short xunits, xclamp; /* units and clamping options for x-axis */
@@ -1643,16 +1644,16 @@ View2DScrollers *UI_view2d_scrollers_calc(
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);
-
+
vert = v2d->vert;
hor = v2d->hor;
-
+
/* slider rects need to be smaller than region */
smaller = (int)(0.1f * U.widget_unit);
hor.xmin += smaller;
@@ -1661,26 +1662,26 @@ View2DScrollers *UI_view2d_scrollers_calc(
hor.ymin += smaller;
else
hor.ymax -= smaller;
-
+
if (scroll & V2D_SCROLL_LEFT)
vert.xmin += smaller;
else
vert.xmax -= smaller;
vert.ymin += smaller;
vert.ymax -= 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 */
@@ -1693,15 +1694,15 @@ View2DScrollers *UI_view2d_scrollers_calc(
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)
+ 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) {
@@ -1710,9 +1711,9 @@ View2DScrollers *UI_view2d_scrollers_calc(
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 */
@@ -1725,27 +1726,27 @@ View2DScrollers *UI_view2d_scrollers_calc(
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)
+ 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 */
@@ -1753,12 +1754,12 @@ View2DScrollers *UI_view2d_scrollers_calc(
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;
}
@@ -1768,11 +1769,11 @@ static void scroll_printstr(Scene *scene, float x, float y, float val, int power
{
int len;
char timecode_str[32];
-
+
/* adjust the scale unit to work ok */
if (dir == 'v') {
- /* here we bump up the power by factor of 10, as
- * rotation values (hence 'degrees') are divided by 10 to
+ /* here we bump up the power by factor of 10, as
+ * rotation values (hence 'degrees') are divided by 10 to
* be able to show the curves at the same time
*/
if (ELEM(unit, V2D_UNIT_DEGREES, V2D_UNIT_TIME)) {
@@ -1780,7 +1781,7 @@ static void scroll_printstr(Scene *scene, float x, float y, float val, int power
val *= 10;
}
}
-
+
/* get string to print */
if (unit == V2D_UNIT_SECONDS) {
/* not neces*/
@@ -1789,7 +1790,7 @@ static void scroll_printstr(Scene *scene, float x, float y, float val, int power
else {
BLI_timecode_string_from_time_seconds(timecode_str, sizeof(timecode_str), power, val);
}
-
+
/* get length of string, and adjust printing location to fit it into the horizontal scrollbar */
len = strlen(timecode_str);
if (dir == 'h') {
@@ -1799,13 +1800,13 @@ static void scroll_printstr(Scene *scene, float x, float y, float val, int power
else
x -= 4 * len;
}
-
+
/* Add degree sympbol to end of string for vertical scrollbar? */
if ((dir == 'v') && (unit == V2D_UNIT_DEGREES)) {
timecode_str[len] = 186;
timecode_str[len + 1] = 0;
}
-
+
/* draw it */
BLF_draw_default_ascii(x, y, 0.0f, timecode_str, sizeof(timecode_str));
}
@@ -1822,35 +1823,35 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
/* 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,
+ * - 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 &&
@@ -1861,27 +1862,27 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
}
UI_draw_widget_scroll(&wcol, &hor, &slider, state);
-
+
/* scale indicators */
if ((scroll & V2D_SCROLL_SCALE_HORIZONTAL) && (vs->grid)) {
const int font_id = BLF_default();
View2DGrid *grid = vs->grid;
float fac, dfac, fac2, val;
-
- /* the numbers: convert grid->startx and -dx to scroll coordinates
+
+ /* the numbers: convert grid->startx and -dx to scroll coordinates
* - fac is x-coordinate to draw to
* - dfac is gap between scale markings
*/
fac = (grid->startx - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
fac = (float)hor.xmin + fac * BLI_rcti_size_x(&hor);
-
+
dfac = grid->dx / BLI_rctf_size_x(&v2d->cur);
dfac = dfac * BLI_rcti_size_x(&hor);
-
+
/* set starting value, and text color */
UI_FontThemeColor(font_id, TH_TEXT);
val = grid->startx;
-
+
/* if we're clamping to whole numbers only, make sure entries won't be repeated */
if (vs->xclamp == V2D_GRID_CLAMP) {
while (grid->dx < 0.9999f) {
@@ -1899,25 +1900,25 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
BLF_batch_draw_begin();
for (; fac < hor.xmax - 0.5f * U.widget_unit; fac += dfac, val += grid->dx) {
-
+
/* make prints look nicer for scrollers */
if (fac < hor.xmin + 0.5f * U.widget_unit)
continue;
-
+
switch (vs->xunits) {
case V2D_UNIT_FRAMES: /* frames (as whole numbers)*/
scroll_printstr(scene, fac, h, val, grid->powerx, V2D_UNIT_FRAMES, 'h');
break;
-
+
case V2D_UNIT_FRAMESCALE: /* frames (not always as whole numbers) */
scroll_printstr(scene, fac, h, val, grid->powerx, V2D_UNIT_FRAMESCALE, 'h');
break;
-
+
case V2D_UNIT_SECONDS: /* seconds */
fac2 = val / (float)FPS;
scroll_printstr(scene, fac, h, fac2, grid->powerx, V2D_UNIT_SECONDS, 'h');
break;
-
+
case V2D_UNIT_DEGREES: /* Graph Editor for rotation Drivers */
/* HACK: although we're drawing horizontal, we make this draw as 'vertical', just to get degree signs */
scroll_printstr(scene, fac, h, val, grid->powerx, V2D_UNIT_DEGREES, 'v');
@@ -1929,31 +1930,31 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
}
}
}
-
+
/* 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,
+ * - 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 &&
@@ -1962,16 +1963,16 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
{
state |= UI_SCROLL_ARROWS;
}
-
+
UI_draw_widget_scroll(&wcol, &vert, &slider, state);
-
-
+
+
/* scale indiators */
if ((scroll & V2D_SCROLL_SCALE_VERTICAL) && (vs->grid)) {
View2DGrid *grid = vs->grid;
float fac, dfac, val;
-
- /* the numbers: convert grid->starty and dy to scroll coordinates
+
+ /* the numbers: convert grid->starty and dy to scroll coordinates
* - fac is y-coordinate to draw to
* - dfac is gap between scale markings
* - these involve a correction for horizontal scrollbar
@@ -1979,38 +1980,38 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
*/
fac = (grid->starty - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
fac = vert.ymin + fac * BLI_rcti_size_y(&vert);
-
+
dfac = grid->dy / BLI_rctf_size_y(&v2d->cur);
dfac = dfac * BLI_rcti_size_y(&vert);
-
+
/* set starting value, and text color */
const int font_id = BLF_default();
UI_FontThemeColor(font_id, TH_TEXT);
val = grid->starty;
-
+
/* if vertical clamping (to whole numbers) is used (i.e. in Sequencer), apply correction */
if (vs->yclamp == V2D_GRID_CLAMP)
fac += 0.5f * dfac;
-
+
/* draw vertical steps */
if (dfac > 0.0f) {
BLF_rotation(font_id, M_PI_2);
BLF_enable(font_id, BLF_ROTATION);
for (; fac < vert.ymax - 10; fac += dfac, val += grid->dy) {
-
+
/* make prints look nicer for scrollers */
if (fac < vert.ymin + 10)
continue;
-
+
scroll_printstr(scene, (float)(vert.xmax) - 2.0f, fac, val, grid->powery, vs->yunits, 'v');
}
-
+
BLF_disable(font_id, BLF_ROTATION);
}
}
}
-
+
/* Was changed above, so reset. */
btheme->tui.widget_emboss[3] = emboss_alpha;
}
@@ -2055,21 +2056,21 @@ void UI_view2d_listview_cell_to_view(
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;
@@ -2095,21 +2096,21 @@ void UI_view2d_listview_view_to_cell(
/* 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 (column) *column = 0;
if (row) *row = 0;
-
+
return;
}
-
+
/* get column */
if ((column) && (columnwidth > 0))
*column = x / columnwidth;
else if (column)
*column = 0;
-
+
/* get row */
if ((row) && (rowheight > 0))
*row = y / rowheight;
@@ -2131,11 +2132,11 @@ void UI_view2d_listview_visible_cells(
/* 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,
+ 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,
+ UI_view2d_listview_view_to_cell(v2d, columnwidth, rowheight, startx, starty,
v2d->cur.xmax, v2d->cur.ymax, column_max, row_max);
}
}
@@ -2196,7 +2197,7 @@ bool UI_view2d_view_to_region_clip(View2D *v2d, float x, float y, int *r_region_
/* 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)));
@@ -2348,7 +2349,7 @@ View2D *UI_view2d_fromcontext_rwin(const bContext *C)
*
* \param x, y: scale on each axis
*/
-void UI_view2d_scale_get(View2D *v2d, float *x, float *y)
+void UI_view2d_scale_get(View2D *v2d, float *x, float *y)
{
if (x) *x = BLI_rcti_size_x(&v2d->mask) / BLI_rctf_size_x(&v2d->cur);
if (y) *y = BLI_rcti_size_y(&v2d->mask) / BLI_rctf_size_y(&v2d->cur);
@@ -2423,11 +2424,11 @@ short UI_view2d_mouse_in_scrollers(const ARegion *ar, View2D *v2d, int x, int y)
{
int co[2];
int scroll = view2d_scroll_mapped(v2d->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';
@@ -2435,7 +2436,7 @@ short UI_view2d_mouse_in_scrollers(const ARegion *ar, View2D *v2d, int x, int y)
if (scroll & V2D_SCROLL_VERTICAL) {
if (IN_2D_VERT_SCROLL(v2d, co)) return 'v';
}
-
+
/* not found */
return 0;
}
@@ -2464,7 +2465,7 @@ void UI_view2d_text_cache_add(
const char *str, size_t str_len, const char col[4])
{
int mval[2];
-
+
BLI_assert(str_len == strlen(str));
if (UI_view2d_view_to_region_clip(v2d, x, y, &mval[0], &mval[1])) {
@@ -2566,5 +2567,3 @@ void UI_view2d_text_cache_draw(ARegion *ar)
/* ******************************************************** */
-
-
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index 90ef47aa712..defb7391bdf 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -17,7 +17,7 @@
*
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
- *
+ *
* Contributor(s): Blender Foundation, Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
@@ -33,6 +33,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -73,7 +74,7 @@ static int view2d_poll(bContext *C)
*/
/* ------------------ Shared 'core' stuff ---------------------- */
-
+
/* temp customdata for operator */
typedef struct v2dViewPanData {
bScreen *sc; /* screen where view pan was initiated */
@@ -87,10 +88,10 @@ typedef struct v2dViewPanData {
int startx, starty; /* mouse x/y values in window when operator was initiated */
int lastx, lasty; /* previous x/y values of mouse in window */
int invoke_event; /* event starting pan, for modal exit */
-
+
short in_scroller; /* for MMB in scrollers (old feature in past, but now not that useful) */
} v2dViewPanData;
-
+
/* initialize panning customdata */
static int view_pan_init(bContext *C, wmOperator *op)
{
@@ -98,32 +99,32 @@ static int view_pan_init(bContext *C, wmOperator *op)
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;
}
@@ -151,11 +152,11 @@ static int view_pan_poll(bContext *C)
static void view_pan_apply_ex(bContext *C, v2dViewPanData *vpd, float dx, float dy)
{
View2D *v2d = vpd->v2d;
-
+
/* 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;
@@ -165,22 +166,17 @@ static void view_pan_apply_ex(bContext *C, v2dViewPanData *vpd, float dx, float
v2d->cur.ymin += dy;
v2d->cur.ymax += dy;
}
-
+
/* 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);
+
/* request updates to be done... */
- ED_region_tag_redraw(vpd->ar);
WM_event_add_mousemove(C);
-
+
UI_view2d_sync(vpd->sc, vpd->sa, v2d, V2D_LOCK_COPY);
-
- /* exceptions */
- if (vpd->sa->spacetype == SPACE_OUTLINER) {
- /* don't rebuild full tree, since we're just changing our view */
- SpaceOops *soops = vpd->sa->spacedata.first;
- soops->storeflag |= SO_TREESTORE_REDRAW;
- }
}
static void view_pan_apply(bContext *C, wmOperator *op)
@@ -200,8 +196,8 @@ static void view_pan_exit(wmOperator *op)
MEM_freeN(op->customdata);
op->customdata = NULL;
}
-}
-
+}
+
/* ------------------ Modal Drag Version (1) ---------------------- */
/* for 'redo' only, with no user input */
@@ -209,7 +205,7 @@ static int view_pan_exec(bContext *C, wmOperator *op)
{
if (!view_pan_init(C, op))
return OPERATOR_CANCELLED;
-
+
view_pan_apply(C, op);
view_pan_exit(op);
return OPERATOR_FINISHED;
@@ -221,38 +217,38 @@ 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);
@@ -263,7 +259,7 @@ static int view_pan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
v2dViewPanData *vpd = op->customdata;
-
+
/* execute the events */
switch (event->type) {
case MOUSEMOVE:
@@ -271,10 +267,10 @@ static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* 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;
}
@@ -286,7 +282,7 @@ static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* 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);
@@ -299,10 +295,10 @@ static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* 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;
}
}
@@ -323,16 +319,16 @@ static void VIEW2D_OT_pan(wmOperatorType *ot)
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);
@@ -344,26 +340,26 @@ static void VIEW2D_OT_pan(wmOperatorType *ot)
static int view_scrollright_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 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", 20);
RNA_int_set(op->ptr, "deltay", 0);
-
+
/* apply movement, then we're done */
view_pan_apply(C, op);
view_pan_exit(op);
-
+
return OPERATOR_FINISHED;
}
@@ -373,10 +369,10 @@ static void VIEW2D_OT_scroll_right(wmOperatorType *ot)
ot->name = "Scroll Right";
ot->description = "Scroll the view right";
ot->idname = "VIEW2D_OT_scroll_right";
-
+
/* 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);
@@ -388,26 +384,26 @@ static void VIEW2D_OT_scroll_right(wmOperatorType *ot)
static int view_scrollleft_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 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", -20);
RNA_int_set(op->ptr, "deltay", 0);
-
+
/* apply movement, then we're done */
view_pan_apply(C, op);
view_pan_exit(op);
-
+
return OPERATOR_FINISHED;
}
@@ -417,10 +413,10 @@ static void VIEW2D_OT_scroll_left(wmOperatorType *ot)
ot->name = "Scroll Left";
ot->description = "Scroll the view left";
ot->idname = "VIEW2D_OT_scroll_left";
-
+
/* 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);
@@ -431,32 +427,32 @@ static void VIEW2D_OT_scroll_left(wmOperatorType *ot)
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;
}
@@ -466,10 +462,10 @@ static void VIEW2D_OT_scroll_down(wmOperatorType *ot)
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);
@@ -482,32 +478,32 @@ static void VIEW2D_OT_scroll_down(wmOperatorType *ot)
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;
}
@@ -517,10 +513,10 @@ static void VIEW2D_OT_scroll_up(wmOperatorType *ot)
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);
@@ -587,24 +583,24 @@ 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;
}
@@ -613,7 +609,7 @@ static int view_zoom_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 false;
@@ -623,15 +619,15 @@ static int view_zoom_poll(bContext *C)
return false;
v2d = &ar->v2d;
-
+
/* check that 2d-view is zoomable */
if ((v2d->keepzoom & V2D_LOCKZOOM_X) && (v2d->keepzoom & V2D_LOCKZOOM_Y))
return false;
-
+
/* 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,
@@ -644,7 +640,7 @@ static void view_zoomstep_apply_ex(
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
+ * old zoom level is restored after zooming back the same amount
*/
if (facx >= 0.0f) {
dx = BLI_rctf_size_x(&v2d->cur) * facx;
@@ -733,7 +729,7 @@ static void view_zoomstep_apply_ex(
}
/* request updates to be done... */
- ED_region_tag_redraw(vzd->ar);
+ ED_region_tag_redraw_no_rebuild(vzd->ar);
UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
}
@@ -766,40 +762,40 @@ static int view_zoomin_exec(bContext *C, wmOperator *op)
/* 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);
/* 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);
-
+
view_zoomstep_exit(op);
-
+
return OPERATOR_FINISHED;
}
static int view_zoomin_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
v2dViewZoomData *vzd;
-
+
if (!view_zoomdrag_init(C, op))
return OPERATOR_PASS_THROUGH;
-
+
vzd = op->customdata;
-
+
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);
}
-
+
return view_zoomin_exec(C, op);
}
@@ -811,12 +807,12 @@ static void VIEW2D_OT_zoom_in(wmOperatorType *ot)
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);
@@ -832,39 +828,39 @@ static int view_zoomout_exec(bContext *C, wmOperator *op)
/* 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);
/* 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);
view_zoomstep_exit(op);
-
+
return OPERATOR_FINISHED;
}
static int view_zoomout_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
v2dViewZoomData *vzd;
-
+
if (!view_zoomdrag_init(C, op))
return OPERATOR_PASS_THROUGH;
vzd = op->customdata;
-
+
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,
+ 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);
}
@@ -876,12 +872,12 @@ static void VIEW2D_OT_zoom_out(wmOperatorType *ot)
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);
@@ -915,7 +911,7 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op)
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();
@@ -923,7 +919,7 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op)
dx *= time_step * 0.5f;
dy *= time_step * 0.5f;
-
+
vzd->timer_lastdraw = time;
}
@@ -937,7 +933,7 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op)
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;
}
@@ -956,7 +952,7 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op)
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;
}
@@ -966,7 +962,7 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op)
}
}
}
-
+
/* validate that view is in valid configuration after this operation */
UI_view2d_curRect_validate(v2d);
@@ -977,7 +973,7 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op)
}
/* request updates to be done... */
- ED_region_tag_redraw(vzd->ar);
+ ED_region_tag_redraw_no_rebuild(vzd->ar);
UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
}
@@ -988,14 +984,14 @@ static void view_zoomdrag_exit(bContext *C, wmOperator *op)
if (op->customdata) {
v2dViewZoomData *vzd = op->customdata;
-
+
if (vzd->timer)
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), vzd->timer);
-
+
MEM_freeN(op->customdata);
op->customdata = NULL;
}
-}
+}
static void view_zoomdrag_cancel(bContext *C, wmOperator *op)
{
@@ -1007,7 +1003,7 @@ static int view_zoomdrag_exec(bContext *C, wmOperator *op)
{
if (!view_zoomdrag_init(C, op))
return OPERATOR_PASS_THROUGH;
-
+
view_zoomdrag_apply(C, op);
view_zoomdrag_exit(C, op);
return OPERATOR_FINISHED;
@@ -1019,22 +1015,22 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *even
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
+ * 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;
@@ -1051,26 +1047,26 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *even
}
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,
+ UI_view2d_region_to_view(&ar->v2d,
event->mval[0], event->mval[1],
&vzd->mx_2d, &vzd->my_2d);
}
@@ -1081,7 +1077,7 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *even
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);
@@ -1099,24 +1095,24 @@ 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);
@@ -1125,21 +1121,21 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, const wmEvent *event
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 = CLAMPIS(0.001f * v2d->maxzoom, 0.001f, 0.01f);
-
+ 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))
@@ -1147,14 +1143,14 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, const wmEvent *event
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
*/
@@ -1162,28 +1158,28 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, const wmEvent *event
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;
}
}
@@ -1198,18 +1194,18 @@ static void VIEW2D_OT_zoom(wmOperatorType *ot)
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);
@@ -1230,7 +1226,7 @@ static void VIEW2D_OT_zoom(wmOperatorType *ot)
* Currently, these key mappings are hardcoded, but it shouldn't be too important to
* have custom keymappings for this...
*/
-
+
static int view_borderzoom_exec(bContext *C, wmOperator *op)
{
ARegion *ar = CTX_wm_region(C);
@@ -1238,17 +1234,17 @@ static int view_borderzoom_exec(bContext *C, wmOperator *op)
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
+ /* 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
*/
@@ -1268,13 +1264,13 @@ static int view_borderzoom_exec(bContext *C, wmOperator *op)
* - 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);
}
@@ -1282,16 +1278,16 @@ static int view_borderzoom_exec(bContext *C, wmOperator *op)
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)
{
@@ -1299,15 +1295,15 @@ static void VIEW2D_OT_zoom_border(wmOperatorType *ot)
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_border_invoke;
ot->exec = view_borderzoom_exec;
ot->modal = WM_gesture_border_modal;
ot->cancel = WM_gesture_border_cancel;
-
+
ot->poll = view_zoom_poll;
-
+
/* rna */
WM_operator_properties_gesture_border_zoom(ot);
}
@@ -1492,7 +1488,7 @@ void UI_view2d_smooth_view(
v2d->cur = sms.new_cur;
UI_view2d_curRect_validate(v2d);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw_no_rebuild(ar);
UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
}
}
@@ -1536,7 +1532,7 @@ static int view2d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const w
UI_view2d_curRect_validate(v2d);
UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw_no_rebuild(ar);
if (v2d->sms == NULL) {
UI_view2d_zoom_cache_reset();
@@ -1580,17 +1576,17 @@ static void VIEW2D_OT_smoothview(wmOperatorType *ot)
typedef struct v2dScrollerMove {
View2D *v2d; /* View2D data that this operation affects */
ARegion *ar; /* region that the scroller is in */
-
+
short scroller; /* scroller that mouse is in ('h' or 'v') */
short zone; /* -1 is min zoomer, 0 is bar, 1 is max zoomer */ // XXX find some way to provide visual feedback of this (active color?)
-
+
float fac; /* view adjustment factor, based on size of region */
float fac_round; /* for pixel rounding (avoid visible UI jitter) */
float delta; /* amount moved by mouse on axis of interest */
-
+
float scrollbarwidth; /* width of the scrollbar itself, used for page up/down clicks */
int scrollbar_orig; /* initial location of scrollbar x/y, mouse relative */
-
+
int lastx, lasty; /* previous mouse coordinates (in screen coordinates) for determining movement */
} v2dScrollerMove;
@@ -1602,7 +1598,7 @@ typedef struct v2dScrollerMove {
* \warning: The start of this struct must not change, so that it stays in sync with the 'real' version
* For now, we don't need to have a separate (internal) header for structs like this...
*/
-struct View2DScrollers {
+struct View2DScrollers {
/* focus bubbles */
int vert_min, vert_max; /* vertical scrollbar */
int hor_min, hor_max; /* horizontal scrollbar */
@@ -1629,10 +1625,10 @@ 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
+
+ /* 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) {
@@ -1643,12 +1639,12 @@ static short mouse_in_scroller_handle(int mouse, int sc_min, int sc_max, int sh_
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)));
@@ -1656,7 +1652,7 @@ static short mouse_in_scroller_handle(int mouse, int sc_min, int sc_max, int sh_
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)
@@ -1667,10 +1663,25 @@ static short mouse_in_scroller_handle(int mouse, int sc_min, int sc_max, int sh_
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 int scroller_activate_poll(bContext *C)
+{
+ 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;
+
+ /* 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, short in_scroller)
@@ -1681,11 +1692,11 @@ static void scroller_activate_init(bContext *C, wmOperator *op, const wmEvent *e
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;
@@ -1694,7 +1705,7 @@ static void scroller_activate_init(bContext *C, wmOperator *op, const wmEvent *e
/* 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
+ /* '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, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
@@ -1716,7 +1727,7 @@ static void scroller_activate_init(bContext *C, wmOperator *op, const wmEvent *e
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;
@@ -1729,7 +1740,7 @@ static void scroller_activate_init(bContext *C, wmOperator *op, const wmEvent *e
/* 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);
@@ -1737,18 +1748,18 @@ static void scroller_activate_init(bContext *C, wmOperator *op, const wmEvent *e
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(ar);
+ ED_region_tag_redraw_no_rebuild(ar);
}
/* cleanup temp customdata */
@@ -1758,11 +1769,11 @@ static void scroller_activate_exit(bContext *C, wmOperator *op)
v2dScrollerMove *vsm = op->customdata;
vsm->v2d->scroll_ui &= ~(V2D_SCROLL_H_ACTIVE | V2D_SCROLL_V_ACTIVE);
-
+
MEM_freeN(op->customdata);
op->customdata = NULL;
-
- ED_region_tag_redraw(CTX_wm_region(C));
+
+ ED_region_tag_redraw_no_rebuild(CTX_wm_region(C));
}
}
@@ -1777,13 +1788,13 @@ 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:
@@ -1793,16 +1804,16 @@ static void scroller_activate_apply(bContext *C, wmOperator *op)
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:
@@ -1817,14 +1828,14 @@ static void scroller_activate_apply(bContext *C, wmOperator *op)
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(vsm->ar);
+ ED_region_tag_redraw_no_rebuild(vsm->ar);
UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
}
@@ -1835,7 +1846,7 @@ 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:
@@ -1863,11 +1874,11 @@ static int scroller_activate_modal(bContext *C, wmOperator *op, const wmEvent *e
break;
}
}
-
+
/* store previous coordinates */
vsm->lastx = event->x;
vsm->lasty = event->y;
-
+
scroller_activate_apply(C, op);
break;
}
@@ -1880,12 +1891,12 @@ static int scroller_activate_modal(bContext *C, wmOperator *op, const wmEvent *e
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);
@@ -1906,18 +1917,18 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, const wmEvent *
ARegion *ar = CTX_wm_region(C);
View2D *v2d = &ar->v2d;
short in_scroller = 0;
-
+
/* check if mouse in scrollbars, if they're enabled */
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) {
@@ -1944,7 +1955,7 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, const wmEvent *
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)) ||
@@ -1952,30 +1963,30 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, const wmEvent *
{
/* 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;
@@ -1996,13 +2007,13 @@ static void VIEW2D_OT_scroller_activate(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_BLOCKING;
-
+
/* api callbacks */
ot->invoke = scroller_activate_invoke;
ot->modal = scroller_activate_modal;
ot->cancel = scroller_activate_cancel;
- ot->poll = view2d_poll;
+ ot->poll = scroller_activate_poll;
}
/* ********************************************************* */
@@ -2022,7 +2033,7 @@ static int reset_exec(bContext *C, wmOperator *UNUSED(op))
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 */
@@ -2058,7 +2069,7 @@ static int reset_exec(bContext *C, wmOperator *UNUSED(op))
/* 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;
@@ -2070,27 +2081,27 @@ static void VIEW2D_OT_reset(wmOperatorType *ot)
ot->name = "Reset View";
ot->description = "Reset the view";
ot->idname = "VIEW2D_OT_reset";
-
+
/* api callbacks */
ot->exec = reset_exec;
ot->poll = view2d_poll;
}
-
+
/* ********************************************************* */
/* Registration */
void ED_operatortypes_view2d(void)
{
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_zoom_in);
WM_operatortype_append(VIEW2D_OT_zoom_out);
-
+
WM_operatortype_append(VIEW2D_OT_zoom);
WM_operatortype_append(VIEW2D_OT_zoom_border);
@@ -2099,7 +2110,7 @@ void ED_operatortypes_view2d(void)
#endif
WM_operatortype_append(VIEW2D_OT_smoothview);
-
+
WM_operatortype_append(VIEW2D_OT_scroller_activate);
WM_operatortype_append(VIEW2D_OT_reset);
@@ -2117,15 +2128,15 @@ void ED_keymap_view2d(wmKeyConfig *keyconf)
/* pan/scroll */
WM_keymap_add_item(keymap, "VIEW2D_OT_pan", MIDDLEMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_pan", MIDDLEMOUSE, KM_PRESS, KM_SHIFT, 0);
-
+
WM_keymap_add_item(keymap, "VIEW2D_OT_pan", MOUSEPAN, 0, 0, 0);
-
+
WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_right", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_left", WHEELUPMOUSE, KM_PRESS, KM_CTRL, 0);
-
+
WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_down", WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_up", WHEELUPMOUSE, KM_PRESS, KM_SHIFT, 0);
-
+
#ifdef WITH_INPUT_NDOF
WM_keymap_add_item(keymap, "VIEW2D_OT_ndof", NDOF_MOTION, 0, 0, 0);
#endif
@@ -2136,7 +2147,7 @@ void ED_keymap_view2d(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_out", PADMINUS, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_in", PADPLUSKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MOUSEPAN, 0, KM_CTRL, 0);
-
+
WM_keymap_verify_item(keymap, "VIEW2D_OT_smoothview", TIMER1, KM_ANY, KM_ANY, 0);
/* scroll up/down - no modifiers, only when zoom fails */
@@ -2146,7 +2157,7 @@ void ED_keymap_view2d(wmKeyConfig *keyconf)
/* these may be necessary if vertical scroll is disallowed */
WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_right", WHEELDOWNMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_left", WHEELUPMOUSE, KM_PRESS, 0, 0);
-
+
/* alternatives for page up/down to scroll */
#if 0 // XXX disabled, since this causes conflicts with hotkeys in animation editors
/* scroll up/down may fall through to left/right */
@@ -2158,11 +2169,11 @@ void ED_keymap_view2d(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_right", PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_left", PAGEUPKEY, KM_PRESS, KM_SHIFT, 0);
#endif
-
+
/* zoom - drag */
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MOUSEZOOM, 0, 0, 0);
-
+
/* borderzoom - drag */
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_border", BKEY, KM_PRESS, KM_SHIFT, 0);
@@ -2176,12 +2187,12 @@ void ED_keymap_view2d(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "VIEW2D_OT_pan", MOUSEPAN, 0, 0, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_down", WHEELDOWNMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_up", WHEELUPMOUSE, KM_PRESS, 0, 0);
-
+
kmi = WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_down", PAGEDOWNKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "page", true);
kmi = WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_up", PAGEUPKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "page", true);
-
+
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MOUSEZOOM, 0, 0, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MOUSEPAN, 0, KM_CTRL, 0);
@@ -2189,4 +2200,3 @@ void ED_keymap_view2d(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_in", PADPLUSKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_reset", HOMEKEY, KM_PRESS, 0, 0);
}
-
diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c
index b584782e183..91fc1e9fe6a 100644
--- a/source/blender/editors/io/io_alembic.c
+++ b/source/blender/editors/io/io_alembic.c
@@ -79,14 +79,14 @@ static int wm_alembic_export_invoke(bContext *C, wmOperator *op, const wmEvent *
Main *bmain = CTX_data_main(C);
char filepath[FILE_MAX];
- if (bmain->name[0] == '\0') {
+ if (BKE_main_blendfile_path(bmain)[0] == '\0') {
BLI_strncpy(filepath, "untitled", sizeof(filepath));
}
else {
- BLI_strncpy(filepath, bmain->name, sizeof(filepath));
+ BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath));
}
- BLI_replace_extension(filepath, sizeof(filepath), ".abc");
+ BLI_path_extension_replace(filepath, sizeof(filepath), ".abc");
RNA_string_set(op->ptr, "filepath", filepath);
}
@@ -284,8 +284,8 @@ static bool wm_alembic_export_check(bContext *UNUSED(C), wmOperator *op)
char filepath[FILE_MAX];
RNA_string_get(op->ptr, "filepath", filepath);
- if (!BLI_testextensie(filepath, ".abc")) {
- BLI_ensure_extension(filepath, FILE_MAX, ".abc");
+ if (!BLI_path_extension_check(filepath, ".abc")) {
+ BLI_path_extension_ensure(filepath, FILE_MAX, ".abc");
RNA_string_set(op->ptr, "filepath", filepath);
return true;
}
@@ -422,12 +422,12 @@ static int get_sequence_len(char *filename, int *ofs)
}
char path[FILE_MAX];
- BLI_path_abs(filename, G.main->name);
+ 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(G.main->name, path, FILE_MAX);
+ BLI_split_dir_part(BKE_main_blendfile_path_from_global(), path, FILE_MAX);
}
DIR *dir = opendir(path);
diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c
index eb79d0bec13..221142a6cf8 100644
--- a/source/blender/editors/io/io_cache.c
+++ b/source/blender/editors/io/io_cache.c
@@ -60,8 +60,8 @@ static int cachefile_open_invoke(bContext *C, wmOperator *op, const wmEvent *eve
char filepath[FILE_MAX];
Main *bmain = CTX_data_main(C);
- BLI_strncpy(filepath, bmain->name, sizeof(filepath));
- BLI_replace_extension(filepath, sizeof(filepath), ".abc");
+ 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);
}
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index a3cbdb57fed..8f05495bb7f 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -60,16 +60,19 @@
#include "io_collada.h"
static int wm_collada_export_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];
+ const char *blendfile_path = BKE_main_blendfile_path(bmain);
- if (G.main->name[0] == 0)
+ if (blendfile_path[0] == '\0')
BLI_strncpy(filepath, "untitled", sizeof(filepath));
else
- BLI_strncpy(filepath, G.main->name, sizeof(filepath));
+ BLI_strncpy(filepath, blendfile_path, sizeof(filepath));
- BLI_replace_extension(filepath, sizeof(filepath), ".dae");
+ BLI_path_extension_replace(filepath, sizeof(filepath), ".dae");
RNA_string_set(op->ptr, "filepath", filepath);
}
@@ -116,7 +119,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
}
RNA_string_get(op->ptr, "filepath", filepath);
- BLI_ensure_extension(filepath, sizeof(filepath), ".dae");
+ BLI_path_extension_ensure(filepath, sizeof(filepath), ".dae");
/* Avoid File write exceptions in Collada */
@@ -164,8 +167,10 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
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(CTX_data_edit_object(C));
+ ED_object_editmode_load(bmain, CTX_data_edit_object(C));
Scene *scene = CTX_data_scene(C);
@@ -200,9 +205,11 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
if (export_settings.include_armatures) includeFilter |= OB_REL_MOD_ARMATURE;
if (export_settings.include_children) includeFilter |= OB_REL_CHILDREN_RECURSIVE;
- export_count = collada_export(CTX_data_depsgraph(C),
- scene,
- &export_settings
+ export_count = collada_export(
+ C,
+ CTX_data_depsgraph(C),
+ scene,
+ &export_settings
);
if (export_count == 0) {
@@ -330,8 +337,8 @@ static bool wm_collada_export_check(bContext *UNUSED(C), wmOperator *op)
char filepath[FILE_MAX];
RNA_string_get(op->ptr, "filepath", filepath);
- if (!BLI_testextensie(filepath, ".dae")) {
- BLI_ensure_extension(filepath, FILE_MAX, ".dae");
+ if (!BLI_path_extension_check(filepath, ".dae")) {
+ BLI_path_extension_ensure(filepath, FILE_MAX, ".dae");
RNA_string_set(op->ptr, "filepath", filepath);
return true;
}
@@ -584,8 +591,8 @@ void WM_OT_collada_import(wmOperatorType *ot)
0,
INT_MAX);
- RNA_def_boolean(ot->srna,
- "keep_bind_info", 0, "Keep Bind Info",
+ 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");
}
diff --git a/source/blender/editors/io/io_collada.h b/source/blender/editors/io/io_collada.h
index 4bb1475a3b2..ba122630aec 100644
--- a/source/blender/editors/io/io_collada.h
+++ b/source/blender/editors/io/io_collada.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2007 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
diff --git a/source/blender/editors/io/io_ops.c b/source/blender/editors/io/io_ops.c
index d1e933517a9..26414661f52 100644
--- a/source/blender/editors/io/io_ops.c
+++ b/source/blender/editors/io/io_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -42,7 +42,7 @@
#include "io_cache.h"
-void ED_operatortypes_io(void)
+void ED_operatortypes_io(void)
{
#ifdef WITH_COLLADA
/* Collada operators: */
diff --git a/source/blender/editors/io/io_ops.h b/source/blender/editors/io/io_ops.h
index 4fffca4607c..677ce40cc38 100644
--- a/source/blender/editors/io/io_ops.h
+++ b/source/blender/editors/io/io_ops.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2007 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
diff --git a/source/blender/editors/lattice/editlattice_select.c b/source/blender/editors/lattice/editlattice_select.c
index ccf90452b0f..6f1c864130d 100644
--- a/source/blender/editors/lattice/editlattice_select.c
+++ b/source/blender/editors/lattice/editlattice_select.c
@@ -59,6 +59,8 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "DEG_depsgraph.h"
+
#include "lattice_intern.h"
/* -------------------------------------------------------------------- */
@@ -118,6 +120,7 @@ static int lattice_select_random_exec(bContext *C, wmOperator *op)
BLI_rng_free(rng);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
@@ -209,6 +212,7 @@ static int lattice_select_mirror_exec(bContext *C, wmOperator *op)
}
/* TODO, only notify changes */
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
MEM_freeN(objects);
@@ -295,6 +299,7 @@ static int lattice_select_more_less(bContext *C, const bool select)
MEM_freeN(selpoints);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
}
@@ -366,51 +371,56 @@ void ED_lattice_flags_set(Object *obedit, int flag)
static int lattice_select_all_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- Lattice *lt = obedit->data;
- BPoint *bp;
- int a;
+ 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, &objects_len);
+
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
-
- bp = lt->editlatt->latt->def;
- a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
-
- while (a--) {
- if (bp->hide == 0) {
- if (bp->f1 & SELECT) {
- action = SEL_DESELECT;
- break;
- }
+ 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;
}
- bp++;
}
}
- switch (action) {
- case SEL_SELECT:
- ED_lattice_flags_set(obedit, 1);
- break;
- case SEL_DESELECT:
- ED_lattice_flags_set(obedit, 0);
- break;
- case SEL_INVERT:
- 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;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ Lattice *lt;
+ BPoint *bp;
+ int a;
+
+ switch (action) {
+ case SEL_SELECT:
+ ED_lattice_flags_set(obedit, 1);
+ break;
+ case SEL_DESELECT:
+ 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;
+ }
+ bp++;
}
- bp++;
- }
- break;
+ break;
+ }
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
+ MEM_freeN(objects);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
}
@@ -466,6 +476,7 @@ static int lattice_select_ungrouped_exec(bContext *C, wmOperator *op)
}
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -564,6 +575,7 @@ bool ED_lattice_select_pick(bContext *C, const int mval[2], bool extend, bool de
lt->actbp = LT_ACTBP_NONE;
}
+ DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
return true;
diff --git a/source/blender/editors/lattice/lattice_ops.c b/source/blender/editors/lattice/lattice_ops.c
index d3d57a0b510..4f2e87c11c1 100644
--- a/source/blender/editors/lattice/lattice_ops.c
+++ b/source/blender/editors/lattice/lattice_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
diff --git a/source/blender/editors/manipulator_library/manipulator_draw_utils.c b/source/blender/editors/manipulator_library/manipulator_draw_utils.c
index 430841311aa..a0b226b7502 100644
--- a/source/blender/editors/manipulator_library/manipulator_draw_utils.c
+++ b/source/blender/editors/manipulator_library/manipulator_draw_utils.c
@@ -41,6 +41,7 @@
#include "GPU_batch.h"
#include "GPU_glew.h"
#include "GPU_immediate.h"
+#include "GPU_state.h"
#include "MEM_guardedalloc.h"
@@ -104,13 +105,13 @@ void wm_manipulator_geometryinfo_draw(const ManipulatorGeomInfo *info, const boo
* since it causes issues leaving the GL state modified. */
#if 0
glEnable(GL_CULL_FACE);
- glEnable(GL_DEPTH_TEST);
+ GPU_depth_test(true);
#endif
GWN_batch_draw(batch);
#if 0
- glDisable(GL_DEPTH_TEST);
+ GPU_depth_test(false);
glDisable(GL_CULL_FACE);
#endif
diff --git a/source/blender/editors/manipulator_library/manipulator_library_intern.h b/source/blender/editors/manipulator_library/manipulator_library_intern.h
index 01ca217fc0a..55db99236e0 100644
--- a/source/blender/editors/manipulator_library/manipulator_library_intern.h
+++ b/source/blender/editors/manipulator_library/manipulator_library_intern.h
@@ -109,4 +109,3 @@ void wm_manipulator_vec_draw(
#endif /* __MANIPULATOR_LIBRARY_INTERN_H__ */
-
diff --git a/source/blender/editors/manipulator_library/manipulator_library_presets.c b/source/blender/editors/manipulator_library/manipulator_library_presets.c
index cccf484f29d..12f07611722 100644
--- a/source/blender/editors/manipulator_library/manipulator_library_presets.c
+++ b/source/blender/editors/manipulator_library/manipulator_library_presets.c
@@ -148,4 +148,3 @@ void ED_manipulator_draw_preset_facemap(
GPU_select_load_id(-1);
}
}
-
diff --git a/source/blender/editors/manipulator_library/manipulator_types/arrow2d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/arrow2d_manipulator.c
index 749e92e25fb..5acf1ab2d64 100644
--- a/source/blender/editors/manipulator_library/manipulator_types/arrow2d_manipulator.c
+++ b/source/blender/editors/manipulator_library/manipulator_types/arrow2d_manipulator.c
@@ -44,6 +44,7 @@
#include "GPU_draw.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "MEM_guardedalloc.h"
@@ -103,20 +104,20 @@ static void manipulator_arrow2d_draw(const bContext *UNUSED(C), wmManipulator *m
manipulator_color_get(mpr, mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT, color);
- glLineWidth(mpr->line_width);
+ GPU_line_width(mpr->line_width);
WM_manipulator_calc_matrix_final(mpr, matrix_final);
- glEnable(GL_BLEND);
+ GPU_blend(true);
arrow2d_draw_geom(mpr, matrix_final, color);
- glDisable(GL_BLEND);
+ GPU_blend(false);
if (mpr->interaction_data) {
ManipulatorInteraction *inter = mpr->interaction_data;
- glEnable(GL_BLEND);
+ GPU_blend(true);
arrow2d_draw_geom(mpr, inter->init_matrix_final, (const float[4]){0.5f, 0.5f, 0.5f, 0.5f});
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
}
diff --git a/source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c
index 409a2c3ca83..a5bcef7ed5e 100644
--- a/source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c
+++ b/source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c
@@ -51,6 +51,7 @@
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
#include "GPU_select.h"
+#include "GPU_state.h"
#include "MEM_guardedalloc.h"
@@ -92,6 +93,7 @@ static void arrow_draw_geom(const ArrowManipulator3D *arrow, const bool select,
uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
bool unbind_shader = true;
const int draw_style = RNA_enum_get(arrow->manipulator.ptr, "draw_style");
+ const int draw_options = RNA_enum_get(arrow->manipulator.ptr, "draw_options");
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
@@ -117,7 +119,7 @@ static void arrow_draw_geom(const ArrowManipulator3D *arrow, const bool select,
{-unitx, unity, 0},
};
- glLineWidth(arrow->manipulator.line_width);
+ GPU_line_width(arrow->manipulator.line_width);
wm_manipulator_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GWN_PRIM_LINE_LOOP);
}
else {
@@ -131,9 +133,13 @@ static void arrow_draw_geom(const ArrowManipulator3D *arrow, const bool select,
{0.0f, 0.0f, arrow_length},
};
- glLineWidth(arrow->manipulator.line_width);
- wm_manipulator_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GWN_PRIM_LINE_STRIP);
-
+ if (draw_options & ED_MANIPULATOR_ARROW_DRAW_FLAG_STEM) {
+ GPU_line_width(arrow->manipulator.line_width);
+ wm_manipulator_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GWN_PRIM_LINE_STRIP);
+ }
+ else {
+ immUniformColor4fv(color);
+ }
/* *** draw arrow head *** */
@@ -192,9 +198,9 @@ static void arrow_draw_intern(ArrowManipulator3D *arrow, const bool select, cons
gpuPushMatrix();
gpuMultMatrix(matrix_final);
- glEnable(GL_BLEND);
+ GPU_blend(true);
arrow_draw_geom(arrow, select, color);
- glDisable(GL_BLEND);
+ GPU_blend(false);
gpuPopMatrix();
@@ -205,9 +211,9 @@ static void arrow_draw_intern(ArrowManipulator3D *arrow, const bool select, cons
gpuMultMatrix(inter->init_matrix_final);
- glEnable(GL_BLEND);
+ GPU_blend(true);
arrow_draw_geom(arrow, select, (const float[4]){0.5f, 0.5f, 0.5f, 0.5f});
- glDisable(GL_BLEND);
+ GPU_blend(false);
gpuPopMatrix();
}
@@ -303,9 +309,9 @@ static int manipulator_arrow_modal(
/* set the property for the operator and call its modal function */
if (WM_manipulator_target_property_is_valid(mpr_prop)) {
- const int draw_options = RNA_enum_get(arrow->manipulator.ptr, "draw_options");
- const bool constrained = (draw_options & ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED) != 0;
- const bool inverted = (draw_options & ED_MANIPULATOR_ARROW_STYLE_INVERTED) != 0;
+ const int transform_flag = RNA_enum_get(arrow->manipulator.ptr, "transform");
+ const bool constrained = (transform_flag & ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED) != 0;
+ const bool inverted = (transform_flag & ED_MANIPULATOR_ARROW_XFORM_FLAG_INVERTED) != 0;
const bool use_precision = (tweak_flag & WM_MANIPULATOR_TWEAK_PRECISE) != 0;
float value = manipulator_value_from_offset(data, inter, ofs_new, constrained, inverted, use_precision);
@@ -363,9 +369,9 @@ static int manipulator_arrow_invoke(
static void manipulator_arrow_property_update(wmManipulator *mpr, wmManipulatorProperty *mpr_prop)
{
ArrowManipulator3D *arrow = (ArrowManipulator3D *)mpr;
- const int draw_options = RNA_enum_get(arrow->manipulator.ptr, "draw_options");
- const bool constrained = (draw_options & ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED) != 0;
- const bool inverted = (draw_options & ED_MANIPULATOR_ARROW_STYLE_INVERTED) != 0;
+ const int transform_flag = RNA_enum_get(arrow->manipulator.ptr, "transform");
+ const bool constrained = (transform_flag & ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED) != 0;
+ const bool inverted = (transform_flag & ED_MANIPULATOR_ARROW_XFORM_FLAG_INVERTED) != 0;
manipulator_property_data_update(mpr, &arrow->data, mpr_prop, constrained, inverted);
}
@@ -448,21 +454,35 @@ static void MANIPULATOR_WT_arrow_3d(wmManipulatorType *wt)
wt->struct_size = sizeof(ArrowManipulator3D);
/* rna */
- static EnumPropertyItem rna_enum_draw_style[] = {
+ static EnumPropertyItem rna_enum_draw_style_items[] = {
{ED_MANIPULATOR_ARROW_STYLE_NORMAL, "NORMAL", 0, "Normal", ""},
{ED_MANIPULATOR_ARROW_STYLE_CROSS, "CROSS", 0, "Cross", ""},
{ED_MANIPULATOR_ARROW_STYLE_BOX, "BOX", 0, "Box", ""},
{ED_MANIPULATOR_ARROW_STYLE_CONE, "CONE", 0, "Cone", ""},
{0, NULL, 0, NULL, NULL}
};
- static EnumPropertyItem rna_enum_draw_options[] = {
- {ED_MANIPULATOR_ARROW_STYLE_INVERTED, "INVERT", 0, "Inverted", ""},
- {ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED, "CONSTRAIN", 0, "Constrained", ""},
+ static EnumPropertyItem rna_enum_draw_options_items[] = {
+ {ED_MANIPULATOR_ARROW_DRAW_FLAG_STEM, "STEM", 0, "Stem", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+ static EnumPropertyItem rna_enum_transform_items[] = {
+ {ED_MANIPULATOR_ARROW_XFORM_FLAG_INVERTED, "INVERT", 0, "Inverted", ""},
+ {ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED, "CONSTRAIN", 0, "Constrained", ""},
{0, NULL, 0, NULL, NULL}
};
- RNA_def_enum(wt->srna, "draw_style", rna_enum_draw_style, ED_MANIPULATOR_ARROW_STYLE_NORMAL, "Draw Style", "");
- RNA_def_enum_flag(wt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", "");
+ RNA_def_enum(
+ wt->srna, "draw_style", rna_enum_draw_style_items,
+ ED_MANIPULATOR_ARROW_STYLE_NORMAL,
+ "Draw Style", "");
+ RNA_def_enum_flag(
+ wt->srna, "draw_options", rna_enum_draw_options_items,
+ ED_MANIPULATOR_ARROW_DRAW_FLAG_STEM,
+ "Draw Options", "");
+ RNA_def_enum_flag(
+ wt->srna, "transform", rna_enum_transform_items,
+ 0,
+ "Transform", "");
RNA_def_float(wt->srna, "length", 1.0f, 0.0f, FLT_MAX, "Arrow Line Length", "", 0.0f, FLT_MAX);
RNA_def_float_vector(wt->srna, "aspect", 2, NULL, 0, FLT_MAX, "Aspect", "Cone/box style only", 0.0f, FLT_MAX);
diff --git a/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c
index a6964359595..db33f457056 100644
--- a/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c
+++ b/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c
@@ -45,6 +45,7 @@
#include "GPU_matrix.h"
#include "GPU_select.h"
#include "GPU_batch.h"
+#include "GPU_state.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -80,7 +81,7 @@ typedef struct ButtonManipulator2D {
static void button2d_geom_draw_backdrop(
const wmManipulator *mpr, const float color[4], const bool select)
{
- glLineWidth(mpr->line_width);
+ GPU_line_width(mpr->line_width);
Gwn_VertFormat *format = immVertexFormat();
uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -98,11 +99,12 @@ static void button2d_geom_draw_backdrop(
}
static void button2d_draw_intern(
- const bContext *UNUSED(C), wmManipulator *mpr,
+ const bContext *C, wmManipulator *mpr,
const bool select, const bool highlight)
{
ButtonManipulator2D *button = (ButtonManipulator2D *)mpr;
+ const int draw_options = RNA_enum_get(mpr->ptr, "draw_options");
if (button->is_init == false) {
button->is_init = true;
PropertyRNA *prop = RNA_struct_find_property(mpr->ptr, "icon");
@@ -115,8 +117,8 @@ static void button2d_draw_intern(
/* We shouldn't need the +1, but a NULL char is set. */
char *polys = MEM_mallocN(polys_len + 1, __func__);
RNA_property_string_get(mpr->ptr, prop, polys);
- button->shape_batch[0] = GPU_batch_wire_from_poly_2d_encoded((uchar *)polys, polys_len, NULL);
- button->shape_batch[1] = GPU_batch_tris_from_poly_2d_encoded((uchar *)polys, polys_len, NULL);
+ 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);
}
}
@@ -127,41 +129,90 @@ static void button2d_draw_intern(
manipulator_color_get(mpr, highlight, color);
WM_manipulator_calc_matrix_final(mpr, matrix_final);
+
+ bool is_3d = (mpr->parent_mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D) != 0;
+
+
+ if (draw_options & ED_MANIPULATOR_BUTTON_SHOW_HELPLINE) {
+ float matrix_final_no_offset[4][4];
+ WM_manipulator_calc_matrix_final_no_offset(mpr, matrix_final_no_offset);
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4fv(color);
+ GPU_line_width(mpr->line_width);
+ immUniformColor4fv(color);
+ immBegin(GWN_PRIM_LINE_STRIP, 2);
+ immVertex3fv(pos, matrix_final[3]);
+ immVertex3fv(pos, matrix_final_no_offset[3]);
+ immEnd();
+ immUnbindProgram();
+ }
+
+ bool need_to_pop = true;
gpuPushMatrix();
gpuMultMatrix(matrix_final);
- glEnable(GL_BLEND);
+ 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);
+ gpuMultMatrix(matrix_align);
+ }
- if (select == false) {
+ if (select) {
+ BLI_assert(is_3d);
+ button2d_geom_draw_backdrop(mpr, color, select);
+ }
+ else {
+
+ GPU_blend(true);
if (button->shape_batch[0] != NULL) {
- glEnable(GL_LINE_SMOOTH);
- glLineWidth(1.0f);
+ 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. */
- color[0] = 1.0f - color[0];
- color[1] = 1.0f - color[1];
- color[2] = 1.0f - color[2];
-
GWN_batch_program_set_builtin(button->shape_batch[i], GPU_SHADER_2D_UNIFORM_COLOR);
GWN_batch_uniform_4f(button->shape_batch[i], "color", UNPACK4(color));
GWN_batch_draw(button->shape_batch[i]);
+
+ if (draw_options & ED_MANIPULATOR_BUTTON_SHOW_OUTLINE) {
+ color[0] = 1.0f - color[0];
+ color[1] = 1.0f - color[1];
+ color[2] = 1.0f - color[2];
+ }
}
- glDisable(GL_LINE_SMOOTH);
- gpuPopMatrix();
+ GPU_line_smooth(false);
+ GPU_polygon_smooth(true);
}
else if (button->icon != ICON_NONE) {
button2d_geom_draw_backdrop(mpr, color, select);
- gpuPopMatrix();
- UI_icon_draw(
- mpr->matrix_basis[3][0] - (ICON_DEFAULT_WIDTH / 2.0) * UI_DPI_FAC,
- mpr->matrix_basis[3][1] - (ICON_DEFAULT_HEIGHT / 2.0) * UI_DPI_FAC,
- button->icon);
- }
- else {
- gpuPopMatrix();
+ float size[2];
+ if (is_3d) {
+ const float fac = 2.0f;
+ gpuTranslate2f(-(fac / 2), -(fac / 2));
+ gpuScale2f(fac / (ICON_DEFAULT_WIDTH * UI_DPI_FAC), fac / (ICON_DEFAULT_HEIGHT * UI_DPI_FAC));
+ size[0] = 1.0f;
+ size[1] = 1.0f;
+ }
+ else {
+ size[0] = mpr->matrix_basis[3][0] - (ICON_DEFAULT_WIDTH / 2.0) * UI_DPI_FAC;
+ size[1] = mpr->matrix_basis[3][1] - (ICON_DEFAULT_HEIGHT / 2.0) * UI_DPI_FAC;
+ gpuPopMatrix();
+ need_to_pop = false;
+ }
+ UI_icon_draw(size[0], size[1], button->icon);
}
+ GPU_blend(false);
+ }
+
+ if (need_to_pop) {
+ gpuPopMatrix();
}
- glDisable(GL_BLEND);
}
static void manipulator_button2d_draw_select(const bContext *C, wmManipulator *mpr, int select_id)
@@ -174,9 +225,9 @@ static void manipulator_button2d_draw(const bContext *C, wmManipulator *mpr)
{
const bool is_highlight = (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0;
- glEnable(GL_BLEND);
+ GPU_blend(true);
button2d_draw_intern(C, mpr, false, is_highlight);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
static int manipulator_button2d_test_select(
@@ -244,11 +295,19 @@ static void MANIPULATOR_WT_button_2d(wmManipulatorType *wt)
wt->struct_size = sizeof(ButtonManipulator2D);
/* rna */
+ static EnumPropertyItem rna_enum_draw_options[] = {
+ {ED_MANIPULATOR_BUTTON_SHOW_OUTLINE, "OUTLINE", 0, "Outline", ""},
+ {ED_MANIPULATOR_BUTTON_SHOW_HELPLINE, "HELPLINE", 0, "Help Line", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
PropertyRNA *prop;
+
+ RNA_def_enum_flag(wt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", "");
+
prop = RNA_def_property(wt->srna, "icon", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_enum_icon_items);
- /* Passed to 'GPU_batch_from_poly_2d_encoded' */
+ /* Passed to 'GPU_batch_tris_from_poly_2d_encoded' */
RNA_def_property(wt->srna, "shape", PROP_STRING, PROP_BYTESTRING);
/* Currently only used for cursor display. */
diff --git a/source/blender/editors/manipulator_library/manipulator_types/cage2d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/cage2d_manipulator.c
index 784c03be949..b7b19ccd634 100644
--- a/source/blender/editors/manipulator_library/manipulator_types/cage2d_manipulator.c
+++ b/source/blender/editors/manipulator_library/manipulator_types/cage2d_manipulator.c
@@ -49,6 +49,7 @@
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_select.h"
+#include "GPU_state.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -66,16 +67,6 @@
#define MANIPULATOR_RESIZER_SIZE 10.0f
#define MANIPULATOR_MARGIN_OFFSET_SCALE 1.5f
-static void manipulator_calc_matrix_final_no_offset(
- const wmManipulator *mpr, float orig_matrix_final_no_offset[4][4])
-{
- float mat_identity[4][4];
- struct WM_ManipulatorMatrixParams params = {NULL};
- unit_m4(mat_identity);
- params.matrix_offset = mat_identity;
- WM_manipulator_calc_matrix_final_params(mpr, &params, orig_matrix_final_no_offset);
-}
-
static void manipulator_calc_rect_view_scale(
const wmManipulator *mpr, const float dims[2], float scale[2])
{
@@ -88,7 +79,7 @@ static void manipulator_calc_rect_view_scale(
asp[1] = dims[0] / dims[1];
}
float x_axis[3], y_axis[3];
- manipulator_calc_matrix_final_no_offset(mpr, matrix_final_no_offset);
+ WM_manipulator_calc_matrix_final_no_offset(mpr, matrix_final_no_offset);
mul_v3_mat3_m4v3(x_axis, matrix_final_no_offset, mpr->matrix_offset[0]);
mul_v3_mat3_m4v3(y_axis, matrix_final_no_offset, mpr->matrix_offset[1]);
@@ -430,7 +421,7 @@ static void cage2d_draw_box_interaction(
}
else {
BLI_assert(ELEM(prim_type, GWN_PRIM_LINE_STRIP, GWN_PRIM_LINES));
- glLineWidth(line_width + 3.0f);
+ GPU_line_width(line_width + 3.0f);
immBegin(prim_type, verts_len);
immAttrib3f(attr_id.col, 0.0f, 0.0f, 0.0f);
@@ -439,7 +430,7 @@ static void cage2d_draw_box_interaction(
}
immEnd();
- glLineWidth(line_width);
+ GPU_line_width(line_width);
immBegin(prim_type, verts_len);
immAttrib3fv(attr_id.col, color);
@@ -568,14 +559,14 @@ static void manipulator_cage2d_draw_intern(
/* Handy for quick testing draw (if it's outside bounds). */
if (false) {
- glEnable(GL_BLEND);
+ GPU_blend(true);
uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_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();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
if (select) {
@@ -620,13 +611,13 @@ static void manipulator_cage2d_draw_intern(
};
if (draw_style == ED_MANIPULATOR_CAGE2D_STYLE_BOX) {
/* corner manipulators */
- glLineWidth(mpr->line_width + 3.0f);
+ GPU_line_width(mpr->line_width + 3.0f);
cage2d_draw_box_corners(&r, margin, (const float[3]){0, 0, 0});
/* corner manipulators */
float color[4];
manipulator_color_get(mpr, highlight, color);
- glLineWidth(mpr->line_width);
+ GPU_line_width(mpr->line_width);
cage2d_draw_box_corners(&r, margin, color);
bool show = false;
@@ -655,12 +646,12 @@ static void manipulator_cage2d_draw_intern(
float color[4];
manipulator_color_get(mpr, highlight, color);
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
+ GPU_line_smooth(true);
+ GPU_blend(true);
- glLineWidth(mpr->line_width + 3.0f);
+ GPU_line_width(mpr->line_width + 3.0f);
cage2d_draw_circle_wire(&r, margin, (const float[3]){0, 0, 0}, transform_flag, draw_options);
- glLineWidth(mpr->line_width);
+ GPU_line_width(mpr->line_width);
cage2d_draw_circle_wire(&r, margin, color, transform_flag, draw_options);
@@ -668,15 +659,15 @@ static void manipulator_cage2d_draw_intern(
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);
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
+ GPU_blend(false);
+ GPU_line_smooth(false);
}
else {
BLI_assert(0);
}
}
- glLineWidth(1.0);
+ GPU_line_width(1.0);
gpuPopMatrix();
}
@@ -841,7 +832,7 @@ static int manipulator_cage2d_invoke(
RectTransformInteraction *data = MEM_callocN(sizeof(RectTransformInteraction), "cage_interaction");
copy_m4_m4(data->orig_matrix_offset, mpr->matrix_offset);
- manipulator_calc_matrix_final_no_offset(mpr, data->orig_matrix_final_no_offset);
+ WM_manipulator_calc_matrix_final_no_offset(mpr, data->orig_matrix_final_no_offset);
if (manipulator_window_project_2d(
C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, false, data->orig_mouse) == 0)
diff --git a/source/blender/editors/manipulator_library/manipulator_types/cage3d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/cage3d_manipulator.c
index 6c2e2bd564d..a907816b08f 100644
--- a/source/blender/editors/manipulator_library/manipulator_types/cage3d_manipulator.c
+++ b/source/blender/editors/manipulator_library/manipulator_types/cage3d_manipulator.c
@@ -48,6 +48,7 @@
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_select.h"
+#include "GPU_state.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -303,14 +304,14 @@ static void manipulator_cage3d_draw_intern(
/* Handy for quick testing draw (if it's outside bounds). */
if (false) {
- glEnable(GL_BLEND);
+ GPU_blend(true);
uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_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();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
if (select) {
@@ -358,13 +359,13 @@ static void manipulator_cage3d_draw_intern(
#endif
if (draw_style == ED_MANIPULATOR_CAGE2D_STYLE_BOX) {
/* corner manipulators */
- glLineWidth(mpr->line_width + 3.0f);
+ GPU_line_width(mpr->line_width + 3.0f);
cage3d_draw_box_corners(size_real, margin, (const float[3]){0, 0, 0});
/* corner manipulators */
float color[4];
manipulator_color_get(mpr, highlight, color);
- glLineWidth(mpr->line_width);
+ GPU_line_width(mpr->line_width);
cage3d_draw_box_corners(size_real, margin, color);
bool show = false;
@@ -388,29 +389,29 @@ static void manipulator_cage3d_draw_intern(
float color[4];
manipulator_color_get(mpr, highlight, color);
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_POLYGON_SMOOTH);
- glEnable(GL_BLEND);
+ GPU_line_smooth(true);
+ GPU_polygon_smooth(true);
+ GPU_blend(true);
- glLineWidth(mpr->line_width + 3.0f);
+ GPU_line_width(mpr->line_width + 3.0f);
cage3d_draw_circle_wire(size_real, margin, (const float[3]){0, 0, 0}, transform_flag, draw_options);
- glLineWidth(mpr->line_width);
+ GPU_line_width(mpr->line_width);
cage3d_draw_circle_wire(size_real, margin, color, transform_flag, draw_options);
/* corner manipulators */
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);
- glDisable(GL_BLEND);
- glDisable(GL_POLYGON_SMOOTH);
- glDisable(GL_LINE_SMOOTH);
+ GPU_blend(false);
+ GPU_polygon_smooth(false);
+ GPU_line_smooth(false);
}
else {
BLI_assert(0);
}
}
- glLineWidth(1.0);
+ GPU_line_width(1.0);
gpuPopMatrix();
}
diff --git a/source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c
index a3034597f56..74ba8bd77a9 100644
--- a/source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c
+++ b/source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c
@@ -51,6 +51,7 @@
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
#include "GPU_select.h"
+#include "GPU_state.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -94,6 +95,9 @@ typedef struct DialInteraction {
#define DIAL_WIDTH 1.0f
#define DIAL_RESOLUTION 48
+/* Could make option, negative to clip more (don't show when view aligned). */
+#define DIAL_CLIP_BIAS 0.02
+
/**
* We can't use this for the #wmManipulatorType.matrix_basis_get callback, it conflicts with depth picking.
*/
@@ -120,7 +124,7 @@ static void dial_geom_draw(
const int draw_options = RNA_enum_get(mpr->ptr, "draw_options");
const bool filled = (draw_options & ED_MANIPULATOR_DIAL_DRAW_FLAG_FILL) != 0;
- glLineWidth(mpr->line_width);
+ GPU_line_width(mpr->line_width);
Gwn_VertFormat *format = immVertexFormat();
uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -155,7 +159,7 @@ static void dial_geom_draw(
*/
static void dial_ghostarc_draw_helpline(const float angle, const float co_outer[3], const float color[4])
{
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
gpuPushMatrix();
gpuRotate3f(RAD2DEGF(angle), 0.0f, 0.0f, -1.0f);
@@ -310,9 +314,9 @@ static void dial_draw_intern(
/* draw! */
for (int i = 0; i < 2; i++) {
- glDisable(GL_POLYGON_SMOOTH);
+ GPU_polygon_smooth(false);
dial_ghostarc_draw(mpr, angle_ofs, angle_delta, (const float[4]){0.8f, 0.8f, 0.8f, 0.4f});
- glEnable(GL_POLYGON_SMOOTH);
+ GPU_polygon_smooth(true);
dial_ghostarc_draw_helpline(angle_ofs, co_outer, color); /* starting position */
dial_ghostarc_draw_helpline(angle_ofs + angle_delta, co_outer, color); /* starting position + current value */
@@ -347,6 +351,7 @@ static void manipulator_dial_draw_select(const bContext *C, wmManipulator *mpr,
copy_v3_v3(clip_plane, rv3d->viewinv[2]);
clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], mpr->matrix_basis[3]);
+ clip_plane[3] += DIAL_CLIP_BIAS * mpr->scale_final;
glEnable(GL_CLIP_DISTANCE0);
}
@@ -373,14 +378,14 @@ static void manipulator_dial_draw(const bContext *C, wmManipulator *mpr)
copy_v3_v3(clip_plane, rv3d->viewinv[2]);
clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], mpr->matrix_basis[3]);
- clip_plane[3] -= 0.02f * mpr->scale_final;
+ clip_plane[3] += DIAL_CLIP_BIAS * mpr->scale_final;
glEnable(GL_CLIP_DISTANCE0);
}
- glEnable(GL_BLEND);
+ GPU_blend(true);
dial_draw_intern(C, mpr, false, is_highlight, clip_plane);
- glDisable(GL_BLEND);
+ GPU_blend(false);
if (clip_plane) {
glDisable(GL_CLIP_DISTANCE0);
diff --git a/source/blender/editors/manipulator_library/manipulator_types/grab3d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/grab3d_manipulator.c
index e2d1979b7a6..458dc2fd1c8 100644
--- a/source/blender/editors/manipulator_library/manipulator_types/grab3d_manipulator.c
+++ b/source/blender/editors/manipulator_library/manipulator_types/grab3d_manipulator.c
@@ -46,6 +46,7 @@
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
#include "GPU_select.h"
+#include "GPU_state.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -102,7 +103,7 @@ static void grab_geom_draw(
const int draw_style = RNA_enum_get(mpr->ptr, "draw_style");
const bool filled = (draw_options & ED_MANIPULATOR_GRAB_DRAW_FLAG_FILL) != 0;
- glLineWidth(mpr->line_width);
+ GPU_line_width(mpr->line_width);
Gwn_VertFormat *format = immVertexFormat();
uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -188,9 +189,9 @@ static void grab3d_draw_intern(
gpuMultMatrix(matrix_align);
}
- glEnable(GL_BLEND);
+ GPU_blend(true);
grab_geom_draw(mpr, color, select, draw_options);
- glDisable(GL_BLEND);
+ GPU_blend(false);
gpuPopMatrix();
if (mpr->interaction_data) {
@@ -201,9 +202,9 @@ static void grab3d_draw_intern(
gpuMultMatrix(matrix_align);
}
- glEnable(GL_BLEND);
+ GPU_blend(true);
grab_geom_draw(mpr, (const float[4]){0.5f, 0.5f, 0.5f, 0.5f}, select, draw_options);
- glDisable(GL_BLEND);
+ GPU_blend(false);
gpuPopMatrix();
}
}
@@ -221,9 +222,9 @@ static void manipulator_grab_draw(const bContext *C, wmManipulator *mpr)
(void)is_modal;
- glEnable(GL_BLEND);
+ GPU_blend(true);
grab3d_draw_intern(C, mpr, false, is_highlight);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
static int manipulator_grab_modal(
diff --git a/source/blender/editors/manipulator_library/manipulator_types/primitive3d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/primitive3d_manipulator.c
index 531cf742e6f..419873ccfff 100644
--- a/source/blender/editors/manipulator_library/manipulator_types/primitive3d_manipulator.c
+++ b/source/blender/editors/manipulator_library/manipulator_types/primitive3d_manipulator.c
@@ -42,6 +42,7 @@
#include "GPU_immediate.h"
#include "GPU_matrix.h"
#include "GPU_select.h"
+#include "GPU_state.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -101,9 +102,9 @@ static void manipulator_primitive_draw_intern(
gpuPushMatrix();
gpuMultMatrix(matrix_final);
- glEnable(GL_BLEND);
+ GPU_blend(true);
manipulator_primitive_draw_geom(color_inner, color_outer, draw_style);
- glDisable(GL_BLEND);
+ GPU_blend(false);
gpuPopMatrix();
@@ -117,9 +118,9 @@ static void manipulator_primitive_draw_intern(
gpuPushMatrix();
gpuMultMatrix(inter->init_matrix_final);
- glEnable(GL_BLEND);
+ GPU_blend(true);
manipulator_primitive_draw_geom(color_inner, color_outer, draw_style);
- glDisable(GL_BLEND);
+ GPU_blend(false);
gpuPopMatrix();
}
diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c
index 689a96a3dec..6b5fce26deb 100644
--- a/source/blender/editors/mask/mask_draw.c
+++ b/source/blender/editors/mask/mask_draw.c
@@ -56,6 +56,7 @@
#include "GPU_draw.h"
#include "GPU_shader.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -132,7 +133,7 @@ static void draw_single_handle(const MaskLayer *mask_layer, const MaskSplinePoin
/* this could be split into its own loop */
if (draw_type == MASK_DT_OUTLINE) {
- glLineWidth(3.0f);
+ GPU_line_width(3.0f);
immBegin(GWN_PRIM_LINES, 2);
immVertex2fv(pos, point_pos);
immVertex2fv(pos, handle_pos);
@@ -152,7 +153,7 @@ static void draw_single_handle(const MaskLayer *mask_layer, const MaskSplinePoin
break;
}
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
immBegin(GWN_PRIM_LINES, 2);
immVertex2fv(pos, point_pos);
immVertex2fv(pos, handle_pos);
@@ -262,7 +263,7 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
immUnbindProgram();
if (is_smooth) {
- glEnable(GL_LINE_SMOOTH);
+ GPU_line_smooth(true);
}
/* control points */
@@ -329,7 +330,7 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
}
if (is_smooth) {
- glDisable(GL_LINE_SMOOTH);
+ GPU_line_smooth(false);
}
if (is_spline_sel) {
@@ -412,13 +413,13 @@ static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (*
*/
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- glLineWidth(3.0f);
+ 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);
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
mask_color_active_tint(rgb_tmp, rgb_spline, is_active);
immUniformColor4ubv(rgb_tmp);
@@ -430,7 +431,7 @@ static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (*
case MASK_DT_BLACK:
case MASK_DT_WHITE:
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- glLineWidth(1.0f);
+ 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; }
@@ -456,7 +457,7 @@ static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (*
* probably better with geometry shader (after core profile switch)
*/
#if 0
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
GPU_basic_shader_line_stipple(3, 0xAAAA);
@@ -508,7 +509,7 @@ static void draw_spline_curve(const bContext *C, MaskLayer *masklay, MaskSpline
return;
if (is_smooth) {
- glEnable(GL_LINE_SMOOTH);
+ GPU_line_smooth(true);
}
feather_points = BKE_mask_spline_feather_differentiated_points_with_resolution(spline, &tot_feather_point, resol, (is_fill != false));
@@ -547,15 +548,15 @@ static void draw_spline_curve(const bContext *C, MaskLayer *masklay, MaskSpline
MEM_freeN(diff_points);
if (is_smooth) {
- glDisable(GL_LINE_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)
{
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
GPU_enable_program_point_size();
MaskLayer *masklay;
@@ -592,7 +593,7 @@ static void draw_masklays(const bContext *C, Mask *mask, const char draw_flag, c
}
GPU_disable_program_point_size();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
void ED_mask_draw(const bContext *C,
@@ -690,8 +691,8 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar,
if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) {
/* More blending types could be supported in the future. */
- glEnable(GL_BLEND);
- glBlendFunc(GL_DST_COLOR, GL_ZERO);
+ GPU_blend(true);
+ GPU_blend_set_func(GPU_DST_COLOR, GPU_ZERO);
}
gpuPushMatrix();
@@ -707,7 +708,7 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar,
gpuPopMatrix();
if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) {
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
MEM_freeN(buffer);
diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c
index 9a2635c37d2..f51f05f2d2e 100644
--- a/source/blender/editors/mask/mask_edit.c
+++ b/source/blender/editors/mask/mask_edit.c
@@ -540,7 +540,9 @@ void ED_keymap_mask(wmKeyConfig *keyconf)
/* geometry */
WM_keymap_add_item(keymap, "MASK_OT_add_vertex_slide", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "MASK_OT_add_feather_vertex_slide", ACTIONMOUSE, KM_PRESS, KM_SHIFT, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "MASK_OT_delete", XKEY, KM_PRESS, 0, 0);
+#endif
WM_keymap_add_item(keymap, "MASK_OT_delete", DELKEY, KM_PRESS, 0, 0);
/* selection */
@@ -594,7 +596,11 @@ void ED_keymap_mask(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "MASK_OT_slide_point", ACTIONMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "MASK_OT_slide_spline_curvature", ACTIONMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "MASK_OT_handle_type_set", VKEY, KM_PRESS, 0, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "MASK_OT_normals_make_consistent", NKEY, KM_PRESS, KM_CTRL, 0);
+#else
+ WM_keymap_add_item(keymap, "MASK_OT_normals_make_consistent", NKEY, KM_PRESS, KM_SHIFT, 0);
+#endif
// WM_keymap_add_item(keymap, "MASK_OT_feather_weight_clear", SKEY, KM_PRESS, KM_ALT, 0);
/* ... matches curve editmode */
diff --git a/source/blender/editors/mask/mask_editaction.c b/source/blender/editors/mask/mask_editaction.c
index 16147bdc7f8..771deca69b6 100644
--- a/source/blender/editors/mask/mask_editaction.c
+++ b/source/blender/editors/mask/mask_editaction.c
@@ -205,21 +205,21 @@ void ED_masklayer_frames_select_border(MaskLayer *masklay, float min, float max,
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 */
+ /* Lasso */
if (keyframe_region_lasso_test(ked->data, pt))
masklayshape_select(masklay_shape, select_mode);
}
@@ -336,4 +336,3 @@ void ED_masklayer_snap_frames(MaskLayer *masklay, Scene *scene, short mode)
break;
}
}
-
diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c
index 7ffd82e262c..8559be67ece 100644
--- a/source/blender/editors/mask/mask_select.c
+++ b/source/blender/editors/mask/mask_select.c
@@ -481,7 +481,7 @@ void MASK_OT_select_border(wmOperatorType *ot)
WM_operator_properties_gesture_border_select(ot);
}
-static bool do_lasso_select_mask(bContext *C, const int mcords[][2], short moves, short select)
+static bool do_lasso_select_mask(bContext *C, const int mcords[][2], short moves, bool select, bool extend)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
@@ -514,6 +514,10 @@ static bool do_lasso_select_mask(bContext *C, const int mcords[][2], short moves
/* TODO: handles? */
/* TODO: uw? */
+ if (MASKPOINT_ISSEL_ANY(point) && select && extend) {
+ continue;
+ }
+
float screen_co[2];
/* point in screen coords */
@@ -526,9 +530,13 @@ static bool do_lasso_select_mask(bContext *C, const int mcords[][2], short moves
{
BKE_mask_point_select_set(point, select);
BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, select);
+ changed = true;
+ }
+ else if (select && !extend) {
+ BKE_mask_point_select_set(point, false);
+ BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, false);
+ changed = true;
}
-
- changed = true;
}
}
}
@@ -548,10 +556,9 @@ static int clip_lasso_select_exec(bContext *C, wmOperator *op)
const int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
if (mcords) {
- short select;
-
- select = !RNA_boolean_get(op->ptr, "deselect");
- do_lasso_select_mask(C, mcords, mcords_tot, select);
+ const bool select = !RNA_boolean_get(op->ptr, "deselect");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ do_lasso_select_mask(C, mcords, mcords_tot, select, extend);
MEM_freeN((void *)mcords);
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 6d1f478249a..405c19f1c1d 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -33,13 +33,14 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "DNA_meshdata_types.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
-#include "BKE_DerivedMesh.h"
+#include "BKE_context.h"
+#include "BKE_customdata.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
-#include "BKE_context.h"
#include "BIF_gl.h"
@@ -52,6 +53,8 @@
#include "GPU_draw.h"
+#include "DEG_depsgraph.h"
+
/* own include */
/* copy the face flags, most importantly selection from the mesh to the final derived mesh,
@@ -59,12 +62,12 @@
void paintface_flush_flags(Object *ob, short flag)
{
Mesh *me = BKE_mesh_from_object(ob);
- DerivedMesh *dm = ob->derivedFinal;
+ Mesh *me_eval = ob->runtime.mesh_eval;
MPoly *polys, *mp_orig;
const int *index_array = NULL;
int totpoly;
int i;
-
+
BLI_assert((flag & ~(SELECT | ME_HIDE)) == 0);
if (me == NULL)
@@ -78,14 +81,14 @@ void paintface_flush_flags(Object *ob, short flag)
BKE_mesh_flush_select_from_polys(me);
}
- if (dm == NULL)
+ if (me_eval == NULL)
return;
/* Mesh polys => Final derived polys */
- if ((index_array = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX))) {
- polys = dm->getPolyArray(dm);
- totpoly = dm->getNumPolys(dm);
+ 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++) {
@@ -106,7 +109,7 @@ void paintface_hide(Object *ob, const bool unselected)
Mesh *me;
MPoly *mpoly;
int a;
-
+
me = BKE_mesh_from_object(ob);
if (me == NULL || me->totpoly == 0) return;
@@ -122,10 +125,10 @@ void paintface_hide(Object *ob, const bool unselected)
if (mpoly->flag & ME_HIDE) {
mpoly->flag &= ~ME_FACE_SEL;
}
-
+
mpoly++;
}
-
+
BKE_mesh_flush_hidden_from_polys(me);
paintface_flush_flags(ob, SELECT | ME_HIDE);
@@ -258,7 +261,7 @@ void paintface_deselect_all_visible(Object *ob, int action, bool flush_flags)
me = BKE_mesh_from_object(ob);
if (me == NULL) return;
-
+
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
@@ -311,7 +314,7 @@ bool paintface_minmax(Object *ob, float r_min[3], float r_max[3])
if (!me || !me->mloopuv) {
return ok;
}
-
+
copy_m3_m4(bmat, ob->obmat);
mvert = me->mvert;
@@ -338,19 +341,19 @@ bool paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], b
Mesh *me;
MPoly *mpoly, *mpoly_sel;
unsigned int a, index;
-
+
/* Get the face under the cursor */
me = BKE_mesh_from_object(ob);
if (!ED_mesh_pick_face(C, ob, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE))
return false;
-
+
if (index >= me->totpoly)
return false;
mpoly_sel = me->mpoly + index;
if (mpoly_sel->flag & ME_HIDE) return false;
-
+
/* clear flags */
mpoly = me->mpoly;
a = me->totpoly;
@@ -360,7 +363,7 @@ bool paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], b
mpoly++;
}
}
-
+
me->act_face = (int)index;
if (extend) {
@@ -378,10 +381,11 @@ bool paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], b
else {
mpoly_sel->flag |= ME_FACE_SEL;
}
-
+
/* image window redraw */
paintface_flush_flags(ob, SELECT);
+ DEG_id_tag_update(ob->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views
return true;
@@ -399,7 +403,7 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, bool select, bool exten
const int size[2] = {
BLI_rcti_size_x(rect) + 1,
BLI_rcti_size_y(rect) + 1};
-
+
me = BKE_mesh_from_object(ob);
if ((me == NULL) || (me->totpoly == 0) || (size[0] * size[1] <= 0)) {
@@ -455,7 +459,7 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, bool select, bool exten
IMB_freeImBuf(ibuf);
MEM_freeN(selar);
-#ifdef __APPLE__
+#ifdef __APPLE__
glReadBuffer(GL_BACK);
#endif
@@ -471,8 +475,8 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, bool select, bool exten
void paintvert_flush_flags(Object *ob)
{
Mesh *me = BKE_mesh_from_object(ob);
- DerivedMesh *dm = ob->derivedFinal;
- MVert *dm_mvert, *dm_mv;
+ Mesh *me_eval = ob->runtime.mesh_eval;
+ MVert *mvert_eval, *mv;
const int *index_array = NULL;
int totvert;
int i;
@@ -484,28 +488,28 @@ void paintvert_flush_flags(Object *ob)
* since this could become slow for realtime updates (circle-select for eg) */
BKE_mesh_flush_select_from_verts(me);
- if (dm == NULL)
+ if (me_eval == NULL)
return;
- index_array = dm->getVertDataArray(dm, CD_ORIGINDEX);
+ index_array = CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX);
- dm_mvert = dm->getVertArray(dm);
- totvert = dm->getNumVerts(dm);
+ mvert_eval = me_eval->mvert;
+ totvert = me_eval->totvert;
- dm_mv = dm_mvert;
+ mv = mvert_eval;
if (index_array) {
int orig_index;
- for (i = 0; i < totvert; i++, dm_mv++) {
+ for (i = 0; i < totvert; i++, mv++) {
orig_index = index_array[i];
if (orig_index != ORIGINDEX_NONE) {
- dm_mv->flag = me->mvert[index_array[i]].flag;
+ mv->flag = me->mvert[index_array[i]].flag;
}
}
}
else {
- for (i = 0; i < totvert; i++, dm_mv++) {
- dm_mv->flag = me->mvert[i].flag;
+ for (i = 0; i < totvert; i++, mv++) {
+ mv->flag = me->mvert[i].flag;
}
}
@@ -520,7 +524,7 @@ void paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
me = BKE_mesh_from_object(ob);
if (me == NULL) return;
-
+
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c
index 292b28c772c..66ad057e3ec 100644
--- a/source/blender/editors/mesh/editmesh_add.c
+++ b/source/blender/editors/mesh/editmesh_add.c
@@ -77,7 +77,7 @@ static Object *make_prim_init(
obedit = ED_object_add_type(C, OB_MESH, idname, loc, rot, false, layer);
/* create editmode */
- ED_object_editmode_enter(C, EM_DO_UNDO | EM_IGNORE_LAYER); /* rare cases the active layer is messed up */
+ ED_object_editmode_enter(C, EM_IGNORE_LAYER); /* rare cases the active layer is messed up */
r_creation_data->was_editmode = true;
}
@@ -100,7 +100,7 @@ static void make_prim_finish(bContext *C, Object *obedit, const MakePrimitiveDat
/* userdef */
if (exit_editmode) {
- ED_object_editmode_exit(C, EM_FREEDATA); /* adding EM_DO_UNDO messes up operator redo */
+ ED_object_editmode_exit(C, EM_FREEDATA);
}
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
}
diff --git a/source/blender/editors/mesh/editmesh_add_manipulator.c b/source/blender/editors/mesh/editmesh_add_manipulator.c
index cb531151b84..bfeccfe33a4 100644
--- a/source/blender/editors/mesh/editmesh_add_manipulator.c
+++ b/source/blender/editors/mesh/editmesh_add_manipulator.c
@@ -154,7 +154,7 @@ static void manipulator_mesh_placement_update_from_op(ManipulatorPlacementGroup
UNUSED_VARS(op);
/* For now don't read back from the operator. */
#if 0
- RNA_property_float_get_array(op->ptr, man->data.prop_matrix, &man->cage->matrix_offset[0][0]);
+ RNA_property_float_get_array(op->ptr, man->data.prop_matrix, &man->cage->matrix_offset[0][0]);
#endif
}
@@ -189,9 +189,7 @@ static void manipulator_placement_prop_matrix_set(
mul_m4_m4m4(mat, man->cage->matrix_basis, value);
if (is_negative_m4(mat)) {
- negate_v3(mat[0]);
- negate_v3(mat[1]);
- negate_v3(mat[2]);
+ negate_mat3_m4(mat);
}
RNA_property_float_set_array(op->ptr, man->data.prop_matrix, &mat[0][0]);
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index ca5af7a535d..6c5133c93c8 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -37,6 +37,7 @@
#include "BKE_global.h"
#include "BKE_editmesh.h"
#include "BKE_unit.h"
+#include "BKE_layer.h"
#include "RNA_define.h"
#include "RNA_access.h"
@@ -77,15 +78,22 @@ static const float value_scale_per_inch[NUM_VALUE_KINDS] = { 0.0f, 100.0f, 1.0f,
typedef struct {
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];
+ NumInput num_input[NUM_VALUE_KINDS];
float shift_value[NUM_VALUE_KINDS]; /* The current value when shift is pressed. Negative when shift not active. */
bool is_modal;
+ BevelObjectStore *ob_store;
+ uint ob_store_len;
+
/* modal only */
float mcenter[2];
- BMBackup mesh_backup;
void *draw_handle_pixel;
short twflag;
short value_mode; /* Which value does mouse movement and numeric input affect? */
@@ -122,30 +130,41 @@ static void edbm_bevel_update_header(bContext *C, wmOperator *op)
WM_bool_as_string(opdata->value_mode == PROFILE_VALUE),
offset_str, RNA_int_get(op->ptr, "segments"), RNA_float_get(op->ptr, "profile"));
- ED_area_headerprint(sa, msg);
+ ED_area_status_text(sa, msg);
}
}
static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
{
- Object *obedit = CTX_data_edit_object(C);
Scene *scene = CTX_data_scene(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
BevelData *opdata;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
float pixels_per_inch;
int i;
- if (em->bm->totvertsel == 0) {
- return false;
- }
-
if (is_modal) {
RNA_float_set(op->ptr, "offset", 0.0f);
}
op->customdata = opdata = MEM_mallocN(sizeof(BevelData), "beveldata_mesh_operator");
+ uint objects_used_len = 0;
+
+ {
+ uint ob_store_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &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];
+ 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->em = em;
opdata->is_modal = is_modal;
opdata->value_mode = OFFSET_VALUE;
opdata->segments = (float) RNA_int_get(op->ptr, "segments");
@@ -155,7 +174,7 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
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;
+ opdata->scale[i] = value_scale_per_inch[i] / pixels_per_inch;
initNumInput(&opdata->num_input[i]);
opdata->num_input[i].idx_max = 0;
@@ -174,7 +193,9 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
View3D *v3d = CTX_wm_view3d(C);
ARegion *ar = CTX_wm_region(C);
- opdata->mesh_backup = EDBM_redo_state_store(em);
+ 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;
@@ -191,8 +212,10 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
static bool edbm_bevel_calc(wmOperator *op)
{
BevelData *opdata = op->customdata;
- BMEditMesh *em = opdata->em;
+ BMEditMesh *em;
BMOperator bmop;
+ bool changed = false;
+
const float offset = RNA_float_get(op->ptr, "offset");
const int offset_type = RNA_enum_get(op->ptr, "offset_type");
const int segments = RNA_int_get(op->ptr, "segments");
@@ -202,40 +225,45 @@ static bool edbm_bevel_calc(wmOperator *op)
int material = RNA_int_get(op->ptr, "material");
const bool loop_slide = RNA_boolean_get(op->ptr, "loop_slide");
- /* revert to original mesh */
- if (opdata->is_modal) {
- EDBM_redo_state_restore(opdata->mesh_backup, em, false);
- }
- if (em->ob) {
- material = CLAMPIS(material, -1, em->ob->totcol - 1);
- }
+ for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
+ em = opdata->ob_store[ob_index].em;
- 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",
- BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, profile,
- clamp_overlap, material, loop_slide);
+ /* revert to original mesh */
+ if (opdata->is_modal) {
+ EDBM_redo_state_restore(opdata->ob_store[ob_index].mesh_backup, em, false);
+ }
- BMO_op_exec(em->bm, &bmop);
+ if (em->ob) {
+ material = CLAMPIS(material, -1, em->ob->totcol - 1);
+ }
- 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);
- }
+ 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",
+ BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, profile,
+ clamp_overlap, material, loop_slide);
- /* no need to de-select existing geometry */
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- return false;
- }
+ BMO_op_exec(em->bm, &bmop);
- EDBM_mesh_normals_update(opdata->em);
+ 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);
+ }
- EDBM_update_generic(opdata->em, true, true);
+ /* no need to de-select existing geometry */
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ continue;
+ }
- return true;
+ EDBM_mesh_normals_update(em);
+
+ EDBM_update_generic(em, true, true);
+ changed = true;
+ }
+ return changed;
}
static void edbm_bevel_exit(bContext *C, wmOperator *op)
@@ -245,20 +273,23 @@ static void edbm_bevel_exit(bContext *C, wmOperator *op)
ScrArea *sa = CTX_wm_area(C);
if (sa) {
- ED_area_headerprint(sa, NULL);
+ ED_area_status_text(sa, NULL);
}
if (opdata->is_modal) {
View3D *v3d = CTX_wm_view3d(C);
ARegion *ar = CTX_wm_region(C);
- EDBM_redo_state_free(&opdata->mesh_backup, NULL, false);
+ 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->twflag = opdata->twflag;
}
G.moving = 0;
}
- MEM_freeN(opdata);
+ MEM_SAFE_FREE(opdata->ob_store);
+ MEM_SAFE_FREE(op->customdata);
op->customdata = NULL;
}
@@ -266,8 +297,10 @@ static void edbm_bevel_cancel(bContext *C, wmOperator *op)
{
BevelData *opdata = op->customdata;
if (opdata->is_modal) {
- EDBM_redo_state_free(&opdata->mesh_backup, opdata->em, true);
- EDBM_update_generic(opdata->em, false, true);
+ 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);
@@ -305,7 +338,7 @@ static void edbm_bevel_calc_initial_length(wmOperator *op, const wmEvent *event,
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
+ /* 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) ?
@@ -519,7 +552,7 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
(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;
@@ -561,7 +594,7 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
case VKEY:
if (event->val == KM_RELEASE)
break;
-
+
{
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "vertex_only");
RNA_property_boolean_set(op->ptr, prop, !RNA_property_boolean_get(op->ptr, prop));
@@ -570,7 +603,7 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
edbm_bevel_update_header(C, op);
handled = true;
break;
-
+
}
/* Modal numinput inactive, try to handle numeric inputs last... */
@@ -624,7 +657,7 @@ void MESH_OT_bevel(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
RNA_def_enum(ot->srna, "offset_type", offset_type_items, 0, "Amount Type", "What distance Amount measures");
- prop = RNA_def_float(ot->srna, "offset", 0.0f, -1e6f, 1e6f, "Amount", "", 0.0f, 1.0f);
+ prop = RNA_def_float(ot->srna, "offset", 0.0f, -1e6f, 1e6f, "Amount", "", 0.0f, 100.0f);
RNA_def_property_float_array_funcs_runtime(prop, NULL, NULL, mesh_ot_bevel_offset_range_func);
RNA_def_int(ot->srna, "segments", 1, 1, SEGMENTS_HARD_MAX, "Segments", "Segments for curved edge", 1, 8);
RNA_def_float(ot->srna, "profile", 0.5f, PROFILE_HARD_MIN, 1.0f, "Profile",
diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c
index ee06f7abd2b..568983e47ee 100644
--- a/source/blender/editors/mesh/editmesh_bisect.c
+++ b/source/blender/editors/mesh/editmesh_bisect.c
@@ -160,7 +160,7 @@ static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
v3d->twflag = 0;
/* initialize modal callout */
- ED_area_headerprint(CTX_wm_area(C), IFACE_("LMB: Click and drag to draw cut line"));
+ ED_workspace_status_text(C, IFACE_("LMB: Click and drag to draw cut line"));
}
return ret;
}
@@ -185,10 +185,10 @@ static int mesh_bisect_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* update or clear modal callout */
if (event->type == EVT_MODAL_MAP) {
if (event->val == GESTURE_MODAL_BEGIN) {
- ED_area_headerprint(CTX_wm_area(C), IFACE_("LMB: Release to confirm cut line"));
+ ED_workspace_status_text(C, IFACE_("LMB: Release to confirm cut line"));
}
else {
- ED_area_headerprint(CTX_wm_area(C), NULL);
+ ED_workspace_status_text(C, NULL);
}
}
@@ -368,7 +368,8 @@ void MESH_OT_bisect(struct wmOperatorType *ot)
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", "", 0.00001, 0.1);
+ 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);
diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c
index 6c6283633cd..4841de3c856 100644
--- a/source/blender/editors/mesh/editmesh_extrude.c
+++ b/source/blender/editors/mesh/editmesh_extrude.c
@@ -365,19 +365,64 @@ void MESH_OT_extrude_repeat(wmOperatorType *ot)
#ifdef USE_MANIPULATOR
+const float extrude_button_scale = 0.15f;
+const float extrude_button_offset_scale = 1.5f;
+const float extrude_arrow_scale = 1.0f;
+const float extrude_arrow_xyz_axis_scale = 1.0f;
+const float extrude_arrow_normal_axis_scale = 1.75f;
+
+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,
+};
+
typedef struct ManipulatorExtrudeGroup {
- /* Extrude . */
- struct wmManipulator *axis_arrow;
- /* Redo Z-axis translation. */
- struct wmManipulator *axis_redo;
+
+ /* XYZ & normal. */
+ struct wmManipulator *invoke_xyz_no[4];
+ struct wmManipulator *adjust_xyz_no[5];
+
+ struct {
+ float normal_mat3[3][3]; /* use Z axis for normal. */
+ int orientation_type;
+ } data;
wmOperatorType *ot_extrude;
} ManipulatorExtrudeGroup;
+static void manipulator_mesh_extrude_orientation_matrix_set(
+ struct ManipulatorExtrudeGroup *man, const float mat[3][3])
+{
+ for (int i = 0; i < 3; i++) {
+ /* Set orientation without location. */
+ for (int j = 0; j < 3; j++) {
+ copy_v3_v3(man->adjust_xyz_no[i]->matrix_basis[j], mat[j]);
+ }
+ /* nop when (i == 2). */
+ swap_v3_v3(man->adjust_xyz_no[i]->matrix_basis[i], man->adjust_xyz_no[i]->matrix_basis[2]);
+ /* Orient to normal gives generally less awkward results. */
+ if (man->data.orientation_type != V3D_MANIP_NORMAL) {
+ if (dot_v3v3(man->adjust_xyz_no[i]->matrix_basis[2], man->data.normal_mat3[2]) < 0.0f) {
+ negate_v3(man->adjust_xyz_no[i]->matrix_basis[2]);
+ }
+ }
+ mul_v3_v3fl(
+ man->invoke_xyz_no[i]->matrix_offset[3],
+ man->adjust_xyz_no[i]->matrix_basis[2],
+ (extrude_arrow_xyz_axis_scale * extrude_button_offset_scale) / extrude_button_scale);
+ }
+}
+
static bool manipulator_mesh_extrude_poll(const bContext *C, wmManipulatorGroupType *wgt)
{
- WorkSpace *workspace = CTX_wm_workspace(C);
- if (!STREQ(workspace->tool.manipulator_group, "MESH_WGT_extrude") ||
+ ScrArea *sa = CTX_wm_area(C);
+ bToolRef_Runtime *tref_rt = sa->runtime.tool ? sa->runtime.tool->runtime : NULL;
+ if ((tref_rt == NULL) ||
+ !STREQ(wgt->idname, tref_rt->manipulator_group) ||
!ED_operator_editmesh_view3d((bContext *)C))
{
WM_manipulator_group_type_unlink_delayed_ptr(wgt);
@@ -388,54 +433,72 @@ static bool manipulator_mesh_extrude_poll(const bContext *C, wmManipulatorGroupT
static void manipulator_mesh_extrude_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
{
- const int constraint_z[3] = {0, 0, 1};
-
struct ManipulatorExtrudeGroup *man = MEM_callocN(sizeof(ManipulatorExtrudeGroup), __func__);
mgroup->customdata = man;
const wmManipulatorType *wt_arrow = WM_manipulatortype_find("MANIPULATOR_WT_arrow_3d", true);
- const wmManipulatorType *wt_grab = WM_manipulatortype_find("MANIPULATOR_WT_grab_3d", true);
-
- man->axis_arrow = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL);
- man->axis_redo = WM_manipulator_new_ptr(wt_grab, mgroup, NULL);
+ const wmManipulatorType *wt_grab = WM_manipulatortype_find("MANIPULATOR_WT_button_2d", true);
- man->ot_extrude = WM_operatortype_find("MESH_OT_extrude_context_move", true);
+ for (int i = 0; i < 4; i++) {
+ man->adjust_xyz_no[i] = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL);
+ man->invoke_xyz_no[i] = WM_manipulator_new_ptr(wt_grab, mgroup, NULL);
+ man->invoke_xyz_no[i]->flag |= WM_MANIPULATOR_DRAW_OFFSET_SCALE;
+ }
- UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, man->axis_arrow->color);
- UI_GetThemeColor3fv(TH_MANIPULATOR_SECONDARY, man->axis_redo->color);
+ {
+ PropertyRNA *prop = RNA_struct_find_property(man->invoke_xyz_no[3]->ptr, "shape");
+ for (int i = 0; i < 4; i++) {
+ RNA_property_string_set_bytes(
+ man->invoke_xyz_no[i]->ptr, prop,
+ (const char *)shape_plus, ARRAY_SIZE(shape_plus));
+ }
+ }
- man->axis_redo->color[3] = 0.3f;
- man->axis_redo->color_hi[3] = 0.3f;
+ man->ot_extrude = WM_operatortype_find("MESH_OT_extrude_context_move", true);
- WM_manipulator_set_scale(man->axis_arrow, 2.0);
- WM_manipulator_set_scale(man->axis_redo, 1.0);
+ for (int i = 0; i < 3; i++) {
+ UI_GetThemeColor3fv(TH_AXIS_X + i, man->invoke_xyz_no[i]->color);
+ UI_GetThemeColor3fv(TH_AXIS_X + i, man->adjust_xyz_no[i]->color);
+ }
+ UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, man->invoke_xyz_no[3]->color);
+ UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, man->adjust_xyz_no[3]->color);
- RNA_enum_set(man->axis_arrow->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_NORMAL);
- RNA_enum_set(man->axis_redo->ptr, "draw_style", ED_MANIPULATOR_GRAB_STYLE_RING_2D);
+ for (int i = 0; i < 4; i++) {
+ WM_manipulator_set_scale(man->invoke_xyz_no[i], extrude_button_scale);
+ WM_manipulator_set_scale(man->adjust_xyz_no[i], extrude_arrow_scale);
+ }
+ WM_manipulator_set_scale(man->adjust_xyz_no[3], extrude_arrow_normal_axis_scale);
- RNA_enum_set(man->axis_redo->ptr, "draw_options",
- ED_MANIPULATOR_GRAB_DRAW_FLAG_FILL);
+ for (int i = 0; i < 4; i++) {
+ }
- WM_manipulator_set_flag(man->axis_redo, WM_MANIPULATOR_DRAW_VALUE, true);
+ for (int i = 0; i < 4; i++) {
+ WM_manipulator_set_flag(man->adjust_xyz_no[i], WM_MANIPULATOR_DRAW_VALUE, true);
+ }
- /* New extrude. */
- {
- PointerRNA *ptr = WM_manipulator_operator_set(man->axis_arrow, 0, man->ot_extrude, NULL);
+ /* XYZ & normal axis extrude. */
+ for (int i = 0; i < 4; i++) {
+ PointerRNA *ptr = WM_manipulator_operator_set(man->invoke_xyz_no[i], 0, man->ot_extrude, NULL);
{
+ int constraint[3] = {0, 0, 0};
+ constraint[MIN2(i, 2)] = 1;
PointerRNA macroptr = RNA_pointer_get(ptr, "TRANSFORM_OT_translate");
RNA_boolean_set(&macroptr, "release_confirm", true);
- RNA_boolean_set_array(&macroptr, "constraint_axis", constraint_z);
+ RNA_boolean_set_array(&macroptr, "constraint_axis", constraint);
}
}
+
/* Adjust extrude. */
- {
- PointerRNA *ptr = WM_manipulator_operator_set(man->axis_redo, 0, man->ot_extrude, NULL);
+ for (int i = 0; i < 4; i++) {
+ PointerRNA *ptr = WM_manipulator_operator_set(man->adjust_xyz_no[i], 0, man->ot_extrude, NULL);
{
+ int constraint[3] = {0, 0, 0};
+ constraint[MIN2(i, 2)] = 1;
PointerRNA macroptr = RNA_pointer_get(ptr, "TRANSFORM_OT_translate");
RNA_boolean_set(&macroptr, "release_confirm", true);
- RNA_boolean_set_array(&macroptr, "constraint_axis", constraint_z);
+ RNA_boolean_set_array(&macroptr, "constraint_axis", constraint);
}
- wmManipulatorOpElem *mpop = WM_manipulator_operator_get(man->axis_redo, 0);
+ wmManipulatorOpElem *mpop = WM_manipulator_operator_get(man->adjust_xyz_no[i], 0);
mpop->is_redo = true;
}
}
@@ -444,72 +507,141 @@ static void manipulator_mesh_extrude_refresh(const bContext *C, wmManipulatorGro
{
ManipulatorExtrudeGroup *man = mgroup->customdata;
- WM_manipulator_set_flag(man->axis_arrow, WM_MANIPULATOR_HIDDEN, true);
- WM_manipulator_set_flag(man->axis_redo, WM_MANIPULATOR_HIDDEN, true);
+ for (int i = 0; i < 4; i++) {
+ WM_manipulator_set_flag(man->invoke_xyz_no[i], WM_MANIPULATOR_HIDDEN, true);
+ WM_manipulator_set_flag(man->adjust_xyz_no[i], WM_MANIPULATOR_HIDDEN, true);
+ }
if (G.moving) {
return;
}
- int orientation_type;
- {
- PointerRNA ot_ptr;
- WM_operator_last_properties_ensure(man->ot_extrude, &ot_ptr);
- PointerRNA macroptr = RNA_pointer_get(&ot_ptr, "TRANSFORM_OT_translate");
- orientation_type = RNA_enum_get(&macroptr, "constraint_orientation");
- }
+ Scene *scene = CTX_data_scene(C);
+ man->data.orientation_type = scene->orientation_type;
+ bool use_normal = (man->data.orientation_type != V3D_MANIP_NORMAL);
+ const int axis_len_used = use_normal ? 4 : 3;
struct TransformBounds tbounds;
+
+ if (use_normal) {
+ struct TransformBounds tbounds_normal;
+ if (!ED_transform_calc_manipulator_stats(
+ C, &(struct TransformCalcParams){
+ .orientation_type = V3D_MANIP_NORMAL + 1,
+ }, &tbounds_normal))
+ {
+ unit_m3(tbounds_normal.axis);
+ }
+ copy_m3_m3(man->data.normal_mat3, tbounds_normal.axis);
+ }
+
+ /* TODO(campbell): run second since this modifies the 3D view, it should not. */
if (!ED_transform_calc_manipulator_stats(
C, &(struct TransformCalcParams){
- .orientation_type = orientation_type + 1,
+ .orientation_type = man->data.orientation_type + 1,
}, &tbounds))
{
return;
}
+ /* Main axis is normal. */
+ if (!use_normal) {
+ copy_m3_m3(man->data.normal_mat3, tbounds.axis);
+ }
+
+ /* Offset the add icon. */
+ mul_v3_v3fl(
+ man->invoke_xyz_no[3]->matrix_offset[3],
+ man->data.normal_mat3[2],
+ (extrude_arrow_normal_axis_scale * extrude_button_offset_scale) / extrude_button_scale);
+
/* Needed for normal orientation. */
- copy_m4_m3(man->axis_arrow->matrix_basis, tbounds.axis);
- copy_m4_m3(man->axis_redo->matrix_basis, tbounds.axis);
+ manipulator_mesh_extrude_orientation_matrix_set(man, tbounds.axis);
+ if (use_normal) {
+ copy_m4_m3(man->adjust_xyz_no[3]->matrix_basis, man->data.normal_mat3);
+ }
- WM_manipulator_set_matrix_location(man->axis_arrow, tbounds.center);
- WM_manipulator_set_matrix_location(man->axis_redo, tbounds.center);
+ /* Location. */
+ for (int i = 0; i < axis_len_used; i++) {
+ WM_manipulator_set_matrix_location(man->invoke_xyz_no[i], tbounds.center);
+ WM_manipulator_set_matrix_location(man->adjust_xyz_no[i], tbounds.center);
+ }
wmOperator *op = WM_operator_last_redo(C);
bool has_redo = (op && op->type == man->ot_extrude);
- WM_manipulator_set_flag(man->axis_arrow, WM_MANIPULATOR_HIDDEN, false);
- WM_manipulator_set_flag(man->axis_redo, WM_MANIPULATOR_HIDDEN, !has_redo);
+ /* Un-hide. */
+ for (int i = 0; i < axis_len_used; i++) {
+ WM_manipulator_set_flag(man->invoke_xyz_no[i], WM_MANIPULATOR_HIDDEN, false);
+ WM_manipulator_set_flag(man->adjust_xyz_no[i], WM_MANIPULATOR_HIDDEN, !has_redo);
+ }
- {
- wmManipulatorOpElem *mpop = WM_manipulator_operator_get(man->axis_arrow, 0);
+ /* Operator properties. */
+ if (use_normal) {
+ wmManipulatorOpElem *mpop = WM_manipulator_operator_get(man->invoke_xyz_no[3], 0);
PointerRNA macroptr = RNA_pointer_get(&mpop->ptr, "TRANSFORM_OT_translate");
- RNA_enum_set(&macroptr, "constraint_orientation", orientation_type);
+ RNA_enum_set(&macroptr, "constraint_orientation", V3D_MANIP_NORMAL);
}
/* Redo with current settings. */
if (has_redo) {
- /* We could also access this from 'ot->last_properties' */
-
wmOperator *op_transform = op->macro.last;
- wmManipulatorOpElem *mpop = WM_manipulator_operator_get(man->axis_redo, 0);
-
- PointerRNA macroptr = RNA_pointer_get(&mpop->ptr, "TRANSFORM_OT_translate");
-
float value[4];
RNA_float_get_array(op_transform->ptr, "value", value);
- RNA_float_set_array(&macroptr, "value", value);
-
int constraint_axis[3];
RNA_boolean_get_array(op_transform->ptr, "constraint_axis", constraint_axis);
- RNA_boolean_set_array(&macroptr, "constraint_axis", constraint_axis);
+ int orientation_type = RNA_enum_get(op_transform->ptr, "constraint_orientation");
+
+ /* We could also access this from 'ot->last_properties' */
+ for (int i = 0; i < 4; i++) {
+ if ((i != 3) ?
+ (orientation_type == man->data.orientation_type && constraint_axis[i]) :
+ (orientation_type == V3D_MANIP_NORMAL && constraint_axis[2]))
+ {
+ wmManipulatorOpElem *mpop = WM_manipulator_operator_get(man->adjust_xyz_no[i], 0);
+
+ PointerRNA macroptr = RNA_pointer_get(&mpop->ptr, "TRANSFORM_OT_translate");
+
+ RNA_float_set_array(&macroptr, "value", value);
+ RNA_boolean_set_array(&macroptr, "constraint_axis", constraint_axis);
+ RNA_enum_set(&macroptr, "constraint_orientation", orientation_type);
+ }
+ else {
+ /* TODO(campbell): ideally we could adjust all,
+ * this is complicated by how operator redo and the transform macro works. */
+ WM_manipulator_set_flag(man->adjust_xyz_no[i], WM_MANIPULATOR_HIDDEN, true);
+ }
+ }
+ }
+
+ for (int i = 0; i < 4; i++) {
+ RNA_enum_set(
+ man->invoke_xyz_no[i]->ptr,
+ "draw_options",
+ (man->adjust_xyz_no[i]->flag & WM_MANIPULATOR_HIDDEN) ?
+ ED_MANIPULATOR_BUTTON_SHOW_HELPLINE : 0);
+ }
+}
+
+static void manipulator_mesh_extrude_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ ManipulatorExtrudeGroup *man = mgroup->customdata;
+ switch (man->data.orientation_type) {
+ case V3D_MANIP_VIEW:
+ {
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ float mat[3][3];
+ copy_m3_m4(mat, rv3d->viewinv);
+ normalize_m3(mat);
+ manipulator_mesh_extrude_orientation_matrix_set(man, mat);
+ break;
+ }
}
}
static void manipulator_mesh_extrude_message_subscribe(
const bContext *C, wmManipulatorGroup *mgroup, struct wmMsgBus *mbus)
{
- ManipulatorExtrudeGroup *man = mgroup->customdata;
ARegion *ar = CTX_wm_region(C);
/* Subscribe to view properties */
@@ -520,11 +652,9 @@ static void manipulator_mesh_extrude_message_subscribe(
};
{
- PointerRNA ot_ptr;
- WM_operator_last_properties_ensure(man->ot_extrude, &ot_ptr);
- PointerRNA macroptr = RNA_pointer_get(&ot_ptr, "TRANSFORM_OT_translate");
- WM_msg_subscribe_rna(mbus, &macroptr, NULL, &msg_sub_value_mpr_tag_refresh, __func__);
+ WM_msg_subscribe_rna_anon_prop(mbus, Scene, transform_orientation, &msg_sub_value_mpr_tag_refresh);
}
+
}
static void MESH_WGT_extrude(struct wmManipulatorGroupType *wgt)
@@ -540,6 +670,7 @@ static void MESH_WGT_extrude(struct wmManipulatorGroupType *wgt)
wgt->poll = manipulator_mesh_extrude_poll;
wgt->setup = manipulator_mesh_extrude_setup;
wgt->refresh = manipulator_mesh_extrude_refresh;
+ wgt->draw_prepare = manipulator_mesh_extrude_draw_prepare;
wgt->message_subscribe = manipulator_mesh_extrude_message_subscribe;
}
diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c
index 985d873dfc2..8758fa66a14 100644
--- a/source/blender/editors/mesh/editmesh_inset.c
+++ b/source/blender/editors/mesh/editmesh_inset.c
@@ -112,7 +112,7 @@ static void edbm_inset_update_header(wmOperator *op, bContext *C)
WM_bool_as_string(RNA_boolean_get(op->ptr, "use_individual"))
);
- ED_area_headerprint(sa, msg);
+ ED_area_status_text(sa, msg);
}
}
@@ -202,7 +202,7 @@ static void edbm_inset_exit(bContext *C, wmOperator *op)
}
if (sa) {
- ED_area_headerprint(sa, NULL);
+ ED_area_status_text(sa, NULL);
}
MEM_SAFE_FREE(opdata->ob_store);
diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c
index d681d904e74..9af700aa6bf 100644
--- a/source/blender/editors/mesh/editmesh_intersect.c
+++ b/source/blender/editors/mesh/editmesh_intersect.c
@@ -33,6 +33,7 @@
#include "BLI_kdopbvh.h"
#include "BLI_linklist_stack.h"
+#include "BKE_layer.h"
#include "BKE_editmesh_bvh.h"
#include "BKE_context.h"
#include "BKE_report.h"
@@ -146,9 +147,6 @@ enum {
static int edbm_intersect_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
const int mode = RNA_enum_get(op->ptr, "mode");
int (*test_fn)(BMFace *, void *);
bool use_separate_all = false;
@@ -186,29 +184,45 @@ static int edbm_intersect_exec(bContext *C, wmOperator *op)
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, &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);
- has_isect = BM_mesh_intersect(
- bm,
- em->looptris, em->tottri,
- test_fn, NULL,
- use_self, use_separate_all, true, true, true,
- -1,
- eps);
-
- if (use_separate_cut) {
- /* detach selected/un-selected faces */
- BM_mesh_separate_faces(
- bm,
- BM_elem_cb_check_hflag_enabled_simple(const BMFace *, BM_ELEM_SELECT));
- }
+ 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);
+ if (has_isect) {
+ edbm_intersect_select(em);
+ }
+ else {
+ isect_len++;
+ }
}
- else {
+ MEM_freeN(objects);
+
+ if (isect_len == objects_len) {
BKE_report(op->reports, RPT_WARNING, "No intersections found");
}
-
return OPERATOR_FINISHED;
}
@@ -266,9 +280,6 @@ void MESH_OT_intersect(struct wmOperatorType *ot)
static int edbm_intersect_boolean_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
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");
@@ -276,23 +287,39 @@ static int edbm_intersect_boolean_exec(bContext *C, wmOperator *op)
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, &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(
- bm,
- em->looptris, em->tottri,
- test_fn, NULL,
- false, false, true, true, true,
- boolean_operation,
- eps);
+ 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);
+ if (has_isect) {
+ edbm_intersect_select(em);
+ }
+ else {
+ isect_len++;
+ }
}
- else {
+ MEM_freeN(objects);
+
+ if (isect_len == objects_len) {
BKE_report(op->reports, RPT_WARNING, "No intersections found");
}
-
return OPERATOR_FINISHED;
}
@@ -652,257 +679,270 @@ static BMEdge *bm_face_split_edge_find(
static int edbm_face_split_by_edges_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
const char hflag = BM_ELEM_TAG;
BMEdge *e;
BMIter iter;
- BLI_SMALLSTACK_DECLARE(loop_stack, BMLoop *);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &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;
- {
- BMVert *v;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_disable(v, hflag);
+ if ((bm->totedgesel == 0) ||
+ (bm->totfacesel == 0))
+ {
+ continue;
}
- }
-
- /* edge index is set to -1 then used to assosiate 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);
+ BLI_SMALLSTACK_DECLARE(loop_stack, BMLoop *);
+ {
+ BMVert *v;
+ BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_flag_disable(v, 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);
+ /* edge index is set to -1 then used to assosiate 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(f, hflag);
+ BM_elem_flag_disable(e, hflag);
}
- BM_elem_flag_disable(f, BM_ELEM_INTERNAL_TAG);
- BM_elem_index_set(f, i); /* set_ok */
+ BM_elem_index_set(e, -1); /* set_dirty */
}
- }
- 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++;
- }
- }
+ bm->elem_index_dirty |= BM_EDGE;
- if (loop_stack_len == 0) {
- /* pass */
- }
- else if (loop_stack_len == 1) {
- l_best = BLI_SMALLSTACK_POP(loop_stack);
+ {
+ 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 {
- /* complicated case, match the edge with a face-loop */
+ 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];
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ float e_dir[3];
- /* we want closest to zero */
- float dot_best = FLT_MAX;
+ /* we want closest to zero */
+ float dot_best = FLT_MAX;
- sub_v3_v3v3(e_dir, v_other->co, v->co);
- normalize_v3(e_dir);
+ sub_v3_v3v3(e_dir, v_other->co, v->co);
+ normalize_v3(e_dir);
- while ((l = BLI_SMALLSTACK_POP(loop_stack))) {
- float dot_test;
+ 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 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;
+ /* 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 */
+ 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);
+ {
+ 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);
+ 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);
}
- 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__);
+ /* 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__);
+ MemArena *mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
- BM_mesh_elem_index_ensure(bm, BM_FACE);
+ BM_mesh_elem_index_ensure(bm, BM_FACE);
- {
- BMBVHTree *bmbvh = BKE_bmbvh_new(bm, em->looptris, em->tottri, BMBVH_RESPECT_SELECT, NULL, false);
+ {
+ 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 */
- }
+ 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);
+ 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 */
+ 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);
- }
+ BKE_bmbvh_free(bmbvh);
+ }
- bm->elem_index_dirty |= BM_EDGE;
+ bm->elem_index_dirty |= BM_EDGE;
- BM_mesh_elem_table_ensure(bm, BM_FACE);
+ 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));
+ /* 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));
+ } while ((e_link = e_link->next));
+ }
}
- }
- {
- MemArena *mem_arena_edgenet = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ {
+ MemArena *mem_arena_edgenet = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
- GHashIterator gh_iter;
+ 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);
+ 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);
+ 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_clear(mem_arena_edgenet);
+ }
- BLI_memarena_free(mem_arena_edgenet);
- }
+ BLI_memarena_free(mem_arena_edgenet);
+ }
- BLI_memarena_free(mem_arena);
+ BLI_memarena_free(mem_arena);
- BLI_ghash_free(face_edge_map, NULL, NULL);
+ BLI_ghash_free(face_edge_map, NULL, NULL);
- EDBM_mesh_normals_update(em);
- EDBM_update_generic(em, true, true);
- }
+ EDBM_mesh_normals_update(em);
+ EDBM_update_generic(em, true, true);
+ }
- BLI_stack_free(edges_loose);
+ BLI_stack_free(edges_loose);
#endif /* USE_NET_ISLAND_CONNECT */
+ }
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 80fed05a0b5..a511100ff4e 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2007 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Joseph Eagar, Joshua Leung, Howard Trickey,
* Campbell Barton
*
@@ -48,7 +48,7 @@
#include "BLT_translation.h"
-#include "BKE_DerivedMesh.h"
+#include "BKE_bvhutils.h"
#include "BKE_context.h"
#include "BKE_editmesh.h"
#include "BKE_editmesh_bvh.h"
@@ -58,6 +58,7 @@
#include "GPU_immediate.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "ED_screen.h"
#include "ED_space_api.h"
@@ -301,7 +302,7 @@ static void knife_update_header(bContext *C, wmOperator *op, KnifeTool_OpData *k
#undef WM_MODALKEY
- ED_area_headerprint(CTX_wm_area(C), header);
+ ED_workspace_status_text(C, header);
}
static void knife_project_v2(const KnifeTool_OpData *kcd, const float co[3], float sco[2])
@@ -1010,7 +1011,7 @@ static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd)
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformThemeColor(TH_TRANSFORM);
- glLineWidth(2.0);
+ GPU_line_width(2.0);
immBegin(GWN_PRIM_LINES, 2);
immVertex3fv(pos, v1);
@@ -1041,7 +1042,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
View3D *v3d = CTX_wm_view3d(C);
const KnifeTool_OpData *kcd = arg;
- if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
+ if (v3d->zbuf) GPU_depth_test(false);
glPolygonOffset(1.0f, 1.0f);
@@ -1057,7 +1058,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
knifetool_draw_angle_snapping(kcd);
immUniformColor3ubv(kcd->colors.line);
- glLineWidth(2.0);
+ GPU_line_width(2.0);
immBegin(GWN_PRIM_LINES, 2);
immVertex3fv(pos, kcd->prev.cage);
@@ -1067,7 +1068,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
if (kcd->prev.vert) {
immUniformColor3ubv(kcd->colors.point);
- glPointSize(11);
+ GPU_point_size(11);
immBegin(GWN_PRIM_POINTS, 1);
immVertex3fv(pos, kcd->prev.cage);
@@ -1076,7 +1077,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
if (kcd->prev.bmface) {
immUniformColor3ubv(kcd->colors.curpoint);
- glPointSize(9);
+ GPU_point_size(9);
immBegin(GWN_PRIM_POINTS, 1);
immVertex3fv(pos, kcd->prev.cage);
@@ -1085,7 +1086,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
if (kcd->curr.edge) {
immUniformColor3ubv(kcd->colors.edge);
- glLineWidth(2.0);
+ GPU_line_width(2.0);
immBegin(GWN_PRIM_LINES, 2);
immVertex3fv(pos, kcd->curr.edge->v1->cageco);
@@ -1094,7 +1095,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
}
else if (kcd->curr.vert) {
immUniformColor3ubv(kcd->colors.point);
- glPointSize(11);
+ GPU_point_size(11);
immBegin(GWN_PRIM_POINTS, 1);
immVertex3fv(pos, kcd->curr.cage);
@@ -1103,7 +1104,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
if (kcd->curr.bmface) {
immUniformColor3ubv(kcd->colors.curpoint);
- glPointSize(9);
+ GPU_point_size(9);
immBegin(GWN_PRIM_POINTS, 1);
immVertex3fv(pos, kcd->curr.cage);
@@ -1114,12 +1115,12 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
KnifeLineHit *lh;
int i;
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
/* draw any snapped verts first */
immUniformColor4ubv(kcd->colors.point_a);
- glPointSize(11);
+ GPU_point_size(11);
immBeginAtMost(GWN_PRIM_POINTS, kcd->totlinehit);
@@ -1134,7 +1135,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
/* now draw the rest */
immUniformColor4ubv(kcd->colors.curpoint_a);
- glPointSize(7);
+ GPU_point_size(7);
immBeginAtMost(GWN_PRIM_POINTS, kcd->totlinehit);
@@ -1147,7 +1148,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
immEnd();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
if (kcd->totkedge > 0) {
@@ -1155,7 +1156,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
KnifeEdge *kfe;
immUniformColor3ubv(kcd->colors.line);
- glLineWidth(1.0);
+ GPU_line_width(1.0);
immBeginAtMost(GWN_PRIM_LINES, BLI_mempool_len(kcd->kedges) * 2);
@@ -1176,7 +1177,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
KnifeVert *kfv;
immUniformColor3ubv(kcd->colors.point);
- glPointSize(5.0);
+ GPU_point_size(5.0);
immBeginAtMost(GWN_PRIM_POINTS, BLI_mempool_len(kcd->kverts));
@@ -1195,7 +1196,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
gpuPopMatrix();
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
+ if (v3d->zbuf) GPU_depth_test(true);
}
/**
@@ -1806,7 +1807,7 @@ static void knife_input_ray_segment(KnifeTool_OpData *kcd, const float mval[2],
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);
+ 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);
@@ -2787,7 +2788,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (!obedit || obedit->type != OB_MESH || BKE_editmesh_from_object(obedit) != kcd->em) {
knifetool_exit(C, op);
- ED_area_headerprint(CTX_wm_area(C), NULL);
+ ED_workspace_status_text(C, NULL);
return OPERATOR_FINISHED;
}
@@ -2808,7 +2809,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
ED_region_tag_redraw(kcd->ar);
knifetool_exit(C, op);
- ED_area_headerprint(CTX_wm_area(C), NULL);
+ ED_workspace_status_text(C, NULL);
return OPERATOR_CANCELLED;
case KNF_MODAL_CONFIRM:
@@ -2817,7 +2818,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
knifetool_finish(op);
knifetool_exit(C, op);
- ED_area_headerprint(CTX_wm_area(C), NULL);
+ ED_workspace_status_text(C, NULL);
return OPERATOR_FINISHED;
case KNF_MODAL_MIDPOINT_ON:
diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c
index ba030c42a04..5ccbcf063ad 100644
--- a/source/blender/editors/mesh/editmesh_knife_project.c
+++ b/source/blender/editors/mesh/editmesh_knife_project.c
@@ -40,6 +40,7 @@
#include "BKE_curve.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_editmesh.h"
+#include "BKE_mesh_runtime.h"
#include "BKE_report.h"
#include "DEG_depsgraph.h"
@@ -62,27 +63,28 @@ static LinkNode *knifeproject_poly_from_object(const bContext *C, Scene *scene,
{
Depsgraph *depsgraph = CTX_data_depsgraph(C);
ARegion *ar = CTX_wm_region(C);
- DerivedMesh *dm;
- bool dm_needsFree;
+ struct Mesh *me_eval;
+ bool me_eval_needs_free;
if (ob->type == OB_MESH || ob->derivedFinal) {
- dm = ob->derivedFinal ? ob->derivedFinal : mesh_get_derived_final(depsgraph, scene, ob, CD_MASK_BAREMESH);
- dm_needsFree = false;
+ me_eval = (ob->runtime.mesh_eval ?
+ ob->runtime.mesh_eval : mesh_get_eval_final(depsgraph, scene, ob, CD_MASK_BAREMESH));
+ me_eval_needs_free = false;
}
else if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
- dm = CDDM_from_curve(ob);
- dm_needsFree = true;
+ me_eval = BKE_mesh_new_nomain_from_curve(ob);
+ me_eval_needs_free = true;
}
else {
- dm = NULL;
+ me_eval = NULL;
}
- if (dm) {
+ if (me_eval) {
ListBase nurbslist = {NULL, NULL};
float projmat[4][4];
- BKE_mesh_to_curve_nurblist(dm, &nurbslist, 0); /* wire */
- BKE_mesh_to_curve_nurblist(dm, &nurbslist, 1); /* boundary */
+ 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);
@@ -109,12 +111,11 @@ static LinkNode *knifeproject_poly_from_object(const bContext *C, Scene *scene,
BKE_nurbList_free(&nurbslist);
- if (dm_needsFree) {
- dm->release(dm);
+ if (me_eval_needs_free) {
+ BKE_mesh_free(me_eval);
}
}
-
return polys;
}
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index 37b85ae9f09..78d98025476 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2007 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Joseph Eagar, Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
@@ -48,6 +48,7 @@
#include "GPU_immediate.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "UI_interface.h"
@@ -77,7 +78,7 @@
typedef struct RingSelOpData {
ARegion *ar; /* region that ringsel was activated in */
void *draw_handle; /* for drawing preview loop */
-
+
float (*edges)[2][3];
int totedge;
@@ -109,10 +110,10 @@ static void ringsel_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
{
View3D *v3d = CTX_wm_view3d(C);
RingSelOpData *lcd = arg;
-
+
if ((lcd->totedge > 0) || (lcd->totpoint > 0)) {
if (v3d && v3d->zbuf)
- glDisable(GL_DEPTH_TEST);
+ GPU_depth_test(false);
gpuPushMatrix();
gpuMultMatrix(lcd->ob->obmat);
@@ -134,7 +135,7 @@ static void ringsel_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
}
if (lcd->totpoint > 0) {
- glPointSize(3.0f);
+ GPU_point_size(3.0f);
immBegin(GWN_PRIM_POINTS, lcd->totpoint);
@@ -150,7 +151,7 @@ static void ringsel_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
gpuPopMatrix();
if (v3d && v3d->zbuf)
- glEnable(GL_DEPTH_TEST);
+ GPU_depth_test(true);
}
}
@@ -172,7 +173,7 @@ static void edgering_find_order(BMEdge *lasteed, BMEdge *eed,
break;
}
}
-
+
/* this should never happen */
if (!l) {
v[0][0] = eed->v1;
@@ -181,7 +182,7 @@ static void edgering_find_order(BMEdge *lasteed, BMEdge *eed,
v[1][1] = lasteed->v2;
return;
}
-
+
l2 = BM_loop_other_edge_loop(l, eed->v1);
rev = (l2 == l->prev);
while (l2->v != lasteed->v1 && l2->v != lasteed->v2) {
@@ -400,6 +401,7 @@ static void edgering_select(RingSelOpData *lcd)
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, DEG_TAG_SELECT_UPDATE);
WM_main_add_notifier(NC_GEOM | ND_SELECT, ob_iter->data);
}
}
@@ -446,7 +448,7 @@ static void ringsel_finish(bContext *C, wmOperator *op)
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) */
@@ -494,8 +496,9 @@ static void ringsel_finish(bContext *C, wmOperator *op)
BM_select_history_store(em->bm, lcd->eed->v1); /* low priority TODO, get vertrex close to mouse */
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, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, lcd->ob->data);
}
}
@@ -508,7 +511,7 @@ static void ringsel_exit(bContext *UNUSED(C), wmOperator *op)
/* deactivate the extra drawing stuff in 3D-View */
ED_region_draw_cb_exit(lcd->ar->type, lcd->draw_handle);
-
+
edgering_preview_free(lcd);
MEM_freeN(lcd->objects);
@@ -701,8 +704,7 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
#endif
if (is_interactive) {
- ScrArea *sa = CTX_wm_area(C);
- ED_area_headerprint(sa, IFACE_("Select a ring to be cut, use mouse-wheel or page-up/down for number of cuts, "
+ 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;
}
@@ -727,7 +729,7 @@ static int loopcut_finish(RingSelOpData *lcd, bContext *C, wmOperator *op)
{
/* finish */
ED_region_tag_redraw(lcd->ar);
- ED_area_headerprint(CTX_wm_area(C), NULL);
+ ED_workspace_status_text(C, NULL);
if (lcd->eed) {
/* set for redo */
@@ -776,26 +778,26 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
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_area_headerprint(CTX_wm_area(C), NULL);
+ ED_workspace_status_text(C, NULL);
return OPERATOR_CANCELLED;
case ESCKEY:
if (event->val == KM_RELEASE) {
/* cancel */
ED_region_tag_redraw(lcd->ar);
- ED_area_headerprint(CTX_wm_area(C), NULL);
-
+ ED_workspace_status_text(C, NULL);
+
ringcut_cancel(C, op);
return OPERATOR_CANCELLED;
}
-
+
ED_region_tag_redraw(lcd->ar);
handled = true;
break;
@@ -868,7 +870,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
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 = CLAMPIS(cuts, 0, SUBD_CUTS_MAX);
+ 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;
@@ -876,7 +878,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
if (smoothness != lcd->smoothness) {
- lcd->smoothness = CLAMPIS(smoothness, -SUBD_SMOOTH_MAX, SUBD_SMOOTH_MAX);
+ 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);
@@ -895,9 +897,9 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
BLI_snprintf(buf, sizeof(buf), IFACE_("Number of Cuts: %s, Smooth: %s (Alt)"),
str_rep, str_rep + NUM_STR_REP_LEN);
- ED_area_headerprint(CTX_wm_area(C), buf);
+ ED_workspace_status_text(C, buf);
}
-
+
/* keep going until the user confirms */
return OPERATOR_RUNNING_MODAL;
}
@@ -911,11 +913,11 @@ void MESH_OT_edgering_select(wmOperatorType *ot)
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;
-
+ ot->poll = ED_operator_editmesh_region_view3d;
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -932,14 +934,14 @@ void MESH_OT_loopcut(wmOperatorType *ot)
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;
diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c
index 4081e3b0302..64d890a7314 100644
--- a/source/blender/editors/mesh/editmesh_path.c
+++ b/source/blender/editors/mesh/editmesh_path.c
@@ -29,6 +29,8 @@
* \ingroup edmesh
*/
+#include "MEM_guardedalloc.h"
+
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
@@ -41,6 +43,7 @@
#include "BLI_math.h"
#include "BLI_linklist.h"
+#include "BKE_layer.h"
#include "BKE_context.h"
#include "BKE_editmesh.h"
#include "BKE_report.h"
@@ -726,67 +729,87 @@ 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);
- Object *obedit = CTX_data_edit_object(C);
- 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;
+ 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, &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;
+ /* 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_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_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);
+ 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);
+ edbm_shortest_path_pick_ex(scene, obedit, &op_params, ele_src, ele_dst);
- return OPERATOR_FINISHED;
+ found_valid_elements = true;
+ }
}
- else {
- BKE_report(op->reports, RPT_WARNING, "Path selection requires two matching elements to be selected");
+ 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)
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 0387f3e002e..99a95c27b7b 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -397,6 +397,18 @@ bool EDBM_backbuf_circle_init(
* to avoid the bias interfering with distance comparisons when mixing types.
* \{ */
+#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)
+
+#define FAKE_SELECT_MODE_END(vc, fake_select_mode) \
+ 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
@@ -470,11 +482,16 @@ BMVert *EDBM_vert_find_nearest_ex(
BMVert *eve;
/* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
- ED_view3d_backbuf_validate(vc);
+ {
+ FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_VERTEX);
+ ED_view3d_backbuf_validate_with_select_mode(vc, select_mode);
- index = ED_view3d_backbuf_sample_rect(
- vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test);
- eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL;
+ index = ED_view3d_backbuf_sample_rect(
+ vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test);
+ 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_test < *r_dist) {
@@ -657,23 +674,16 @@ BMEdge *EDBM_edge_find_nearest_ex(
unsigned int index;
BMEdge *eed;
- /* Make sure that the edges also are considered to find nearest.
- * TODO: cleanup: add `selectmode` as a parameter
- * XXX: Without selectmode as parameter we need to resort to this super ugly hack,
- * because we should never write to evaluate data. */
- const short ts_selectmode = vc->scene->toolsettings->selectmode;
-
- Scene *scene_eval = (Scene *)DEG_get_evaluated_id(vc->depsgraph, &vc->scene->id);
- scene_eval->toolsettings->selectmode |= SCE_SELECT_EDGE;
-
/* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
- ED_view3d_backbuf_validate(vc);
+ {
+ FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_EDGE);
+ ED_view3d_backbuf_validate_with_select_mode(vc, select_mode);
- /* restore `selectmode` */
- scene_eval->toolsettings->selectmode = ts_selectmode;
+ index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test);
+ eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL;
- index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test);
- 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;
@@ -834,10 +844,15 @@ BMFace *EDBM_face_find_nearest_ex(
unsigned int index;
BMFace *efa;
- ED_view3d_backbuf_validate(vc);
+ {
+ FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_FACE);
+ ED_view3d_backbuf_validate_with_select_mode(vc, select_mode);
- index = ED_view3d_backbuf_sample(vc, vc->mval[0], vc->mval[1]);
- efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL;
+ index = ED_view3d_backbuf_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;
@@ -1046,7 +1061,7 @@ static bool unified_findnearest(
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);
@@ -1067,6 +1082,9 @@ static bool unified_findnearest(
return (hit.v.ele || hit.e.ele || hit.f.ele);
}
+#undef FAKE_SELECT_MODE_BEGIN
+#undef FAKE_SELECT_MODE_END
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -1396,6 +1414,7 @@ static int edbm_select_similar_region_exec(bContext *C, wmOperator *op)
MEM_freeN(group_index);
if (changed) {
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
else {
@@ -1603,6 +1622,7 @@ static int edbm_loop_multiselect_exec(bContext *C, wmOperator *op)
MEM_freeN(edarray);
// if (EM_texFaceCheck())
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
MEM_freeN(objects);
@@ -1703,17 +1723,6 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de
mvalf[1] = (float)(vc.mval[1] = mval[1]);
em = vc.em;
- /* Make sure that the edges are also considered for selection.
- * TODO: cleanup: add `selectmode` as a parameter */
- const short ts_selectmode = vc.scene->toolsettings->selectmode;
- vc.scene->toolsettings->selectmode |= SCE_SELECT_EDGE;
-
- /* no afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad */
- ED_view3d_backbuf_validate(&vc);
-
- /* restore `selectmode` */
- vc.scene->toolsettings->selectmode = ts_selectmode;
-
eed = EDBM_edge_find_nearest_ex(&vc, &dist, NULL, true, true, NULL);
if (eed == NULL) {
return false;
@@ -1817,6 +1826,7 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de
}
}
+ DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
return true;
@@ -1923,10 +1933,11 @@ static int edbm_select_all_exec(bContext *C, wmOperator *op)
EDBM_selectmode_flush(em);
break;
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
- MEM_SAFE_FREE(objects);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -1968,6 +1979,7 @@ static int edbm_faces_select_interior_exec(bContext *C, wmOperator *UNUSED(op))
continue;
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
MEM_freeN(objects);
@@ -2025,10 +2037,11 @@ bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect
Object *ob_iter = objects[ob_index];
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, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data);
}
}
- MEM_SAFE_FREE(objects);
+ MEM_freeN(objects);
}
if (efa) {
@@ -2143,8 +2156,10 @@ bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect
* switch UV layers, vgroups for eg. */
if (vc.view_layer->basact != basact) {
vc.view_layer->basact = basact;
+ DEG_id_tag_update(&vc.scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, vc.scene);
}
+ DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
return true;
@@ -2429,7 +2444,7 @@ bool EDBM_selectmode_toggle(
}
if (only_update) {
- MEM_SAFE_FREE(objects);
+ MEM_freeN(objects);
return false;
}
@@ -2475,14 +2490,14 @@ bool EDBM_selectmode_toggle(
Object *ob_iter = objects[ob_index];
BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
EDBM_selectmode_set(em_iter);
- DEG_id_tag_update(ob_iter->data, DEG_TAG_COPY_ON_WRITE);
+ DEG_id_tag_update(ob_iter->data, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE);
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, DEG_TAG_COPY_ON_WRITE);
}
- MEM_SAFE_FREE(objects);
+ MEM_freeN(objects);
return ret;
}
@@ -2925,11 +2940,12 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op)
select_linked_delimit_end(em);
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
- MEM_SAFE_FREE(objects);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -3101,7 +3117,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE
has_edges = true;
}
}
- MEM_SAFE_FREE(objects);
+ MEM_freeN(objects);
if (has_edges == false) {
return OPERATOR_CANCELLED;
}
@@ -3136,6 +3152,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE
* index selections isn't very common. */
RNA_int_set(op->ptr, "index", index);
+ DEG_id_tag_update(basact->object->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, basact->object->data);
return OPERATOR_FINISHED;
@@ -3165,6 +3182,7 @@ static int edbm_select_linked_pick_exec(bContext *C, wmOperator *op)
edbm_select_linked_pick_ex(em, ele, sel, delimit);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -3207,47 +3225,57 @@ void MESH_OT_select_linked_pick(wmOperatorType *ot)
static int edbm_select_face_by_sides_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMFace *efa;
- BMIter iter;
+ 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, &objects_len);
- if (!RNA_boolean_get(op->ptr, "extend"))
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ 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;
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!extend) {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ }
- bool 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;
+ }
- 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);
+ }
}
- if (select) {
- BM_face_select_set(em->bm, efa, true);
- }
- }
+ EDBM_selectmode_flush(em);
- EDBM_selectmode_flush(em);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -3341,6 +3369,7 @@ static int edbm_select_loose_exec(bContext *C, wmOperator *op)
EDBM_selectmode_flush(em);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
@@ -3375,28 +3404,48 @@ void MESH_OT_select_loose(wmOperatorType *ot)
static int edbm_select_mirror_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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;
- if (em->bm->totvert && em->bm->totvertsel) {
- int totmirr, totfail;
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &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, &totmirr, &totfail);
+ EDBM_select_mirrored(em, axis, extend, &tot_mirr_iter, &tot_fail_iter);
}
}
- if (totmirr) {
+ if (tot_mirr_iter) {
EDBM_selectmode_flush(em);
+
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
- ED_mesh_report_mirror_ex(op, totmirr, totfail, em->bm->selectmode);
+ 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;
}
@@ -3446,6 +3495,7 @@ static int edbm_select_more_exec(bContext *C, wmOperator *op)
}
EDBM_select_more(em, use_face_step);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
@@ -3496,6 +3546,7 @@ static int edbm_select_less_exec(bContext *C, wmOperator *op)
}
EDBM_select_less(em, use_face_step);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
@@ -3712,18 +3763,39 @@ static bool edbm_deselect_nth(BMEditMesh *em, const struct CheckerIntervalParams
static int edbm_select_nth_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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;
- if (edbm_deselect_nth(em, &op_params) == false) {
- BKE_report(op->reports, RPT_ERROR, "Mesh has no active vert/edge/face");
- return OPERATOR_CANCELLED;
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &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);
- EDBM_update_generic(em, false, false);
+ 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;
}
@@ -3800,6 +3872,7 @@ static int edbm_select_sharp_edges_exec(bContext *C, wmOperator *op)
else {
EDBM_selectmode_flush(em);
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
MEM_freeN(objects);
@@ -3837,59 +3910,71 @@ void MESH_OT_edges_select_sharp(wmOperatorType *ot)
static int edbm_select_linked_flat_faces_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- BLI_LINKSTACK_DECLARE(stack, BMFace *);
-
- BMIter iter, liter, liter2;
- BMFace *f;
- BMLoop *l, *l2;
+ 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, &objects_len);
const float angle_limit_cos = cosf(RNA_float_get(op->ptr, "sharpness"));
- BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
-
- BLI_LINKSTACK_INIT(stack);
+ 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_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))
- {
+ if (bm->totfacesel == 0) {
continue;
}
- BLI_assert(BLI_LINKSTACK_SIZE(stack) == 0);
+ BLI_LINKSTACK_DECLARE(stack, BMFace *);
- do {
- BM_face_select_set(bm, f, true);
+ BMIter iter, liter, liter2;
+ BMFace *f;
+ BMLoop *l, *l2;
- BM_elem_flag_enable(f, BM_ELEM_TAG);
+ BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- BM_ITER_ELEM (l2, &liter2, l, BM_LOOPS_OF_LOOP) {
- float angle_cos;
+ BLI_LINKSTACK_INIT(stack);
- if (BM_elem_flag_test(l2->f, BM_ELEM_TAG) ||
- BM_elem_flag_test(l2->f, BM_ELEM_HIDDEN))
- {
- 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);
+
+ do {
+ BM_face_select_set(bm, f, true);
+
+ 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;
+
+ 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);
+ if (angle_cos > angle_limit_cos) {
+ BLI_LINKSTACK_PUSH(stack, l2->f);
+ }
}
}
- }
- } while ((f = BLI_LINKSTACK_POP(stack)));
- }
+ } while ((f = BLI_LINKSTACK_POP(stack)));
+ }
- BLI_LINKSTACK_FREE(stack);
+ BLI_LINKSTACK_FREE(stack);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -3983,6 +4068,7 @@ static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op)
}
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
EDBM_selectmode_flush(em);
@@ -4086,6 +4172,7 @@ static int edbm_select_random_exec(bContext *C, wmOperator *op)
EDBM_deselect_flush(em);
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
@@ -4180,6 +4267,7 @@ static int edbm_select_ungrouped_exec(bContext *C, wmOperator *op)
if (changed) {
EDBM_selectmode_flush(em);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
}
@@ -4352,6 +4440,7 @@ static int edbm_region_to_loop_exec(bContext *C, wmOperator *UNUSED(op))
EDBM_selectmode_to_scene(C);
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
MEM_freeN(objects);
@@ -4559,6 +4648,7 @@ static int edbm_loop_to_region_exec(bContext *C, wmOperator *op)
EDBM_selectmode_flush(em);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
MEM_freeN(objects);
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index f0e5d7f9118..d7617a14ff3 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -98,13 +98,13 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op)
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, "quadtri") &&
+ 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, "quadtri");
+ 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);
@@ -131,7 +131,7 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op)
EDBM_update_generic(em, true, true);
}
- MEM_SAFE_FREE(objects);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -170,7 +170,7 @@ void MESH_OT_subdivide(wmOperatorType *ot)
WM_operatortype_props_advanced_begin(ot);
- RNA_def_boolean(ot->srna, "quadtri", 0, "Quad/Tri Mode", "Tries to prevent ngons");
+ 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)");
@@ -359,6 +359,7 @@ void MESH_OT_unsubdivide(wmOperatorType *ot)
void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em)
{
+ Main *bmain = CTX_data_main(C);
Object *obedit = em->ob;
BMIter iter;
BMVert *eve;
@@ -366,21 +367,22 @@ void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em)
ED_view3d_init_mats_rv3d(obedit, ar->regiondata);
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), CTX_data_scene(C), CTX_data_depsgraph(C), 0,
+ 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_mixed(
+ if (ED_transform_snap_object_project_view3d(
snap_context,
- SCE_SELECT_FACE,
+ SCE_SNAP_MODE_FACE,
&(const struct SnapObjectParams){
.snap_select = SNAP_NOT_ACTIVE,
.use_object_edit_cage = false,
+ .use_occlusion_test = true,
},
- mval, NULL, true,
+ mval, NULL,
co_proj, NULL))
{
mul_v3_m4v3(eve->co, obedit->imat, co_proj);
@@ -437,7 +439,7 @@ static int edbm_delete_exec(bContext *C, wmOperator *op)
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_FACES)))
+ EDBM_op_callf(em, op, "delete geom=%he context=%i", BM_ELEM_SELECT, DEL_EDGES)))
{
continue;
}
@@ -477,7 +479,7 @@ static int edbm_delete_exec(bContext *C, wmOperator *op)
EDBM_update_generic(em, true, true);
}
- MEM_SAFE_FREE(objects);
+ MEM_freeN(objects);
return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
@@ -510,6 +512,7 @@ void MESH_OT_delete(wmOperatorType *ot)
/* 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);
}
/** \} */
@@ -602,7 +605,7 @@ static int edbm_delete_loose_exec(bContext *C, wmOperator *op)
edbm_report_delete_info(op->reports, totelem_old, totelem_new);
- MEM_SAFE_FREE(objects);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -857,70 +860,83 @@ static void edbm_add_edge_face_exec__tricky_finalize_sel(BMesh *bm, BMElem *ele_
static int edbm_add_edge_face_exec(bContext *C, wmOperator *op)
{
- BMOperator bmop;
- Object *obedit = CTX_data_edit_object(C);
- 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;
/* when this is used to dissolve we could avoid this, but checking isnt too slow */
-#ifdef USE_FACE_CREATE_SEL_EXTEND
- BMElem *ele_desel;
- BMFace *ele_desel_face;
+ 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, &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);
- /* 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 ((em->bm->totvertsel == 0) &&
+ (em->bm->totedgesel == 0) &&
+ (em->bm->totvertsel == 0))
+ {
+ 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))
- {
- return OPERATOR_CANCELLED;
- }
+ bool use_smooth = edbm_add_edge_face__smooth_get(em->bm);
+ int totedge_orig = em->bm->totedge;
+ int totface_orig = em->bm->totface;
- BMO_op_exec(em->bm, &bmop);
+ BMOperator bmop;
+#ifdef USE_FACE_CREATE_SEL_EXTEND
+ BMElem *ele_desel;
+ BMFace *ele_desel_face;
- /* cancel if nothing was done */
- if ((totedge_orig == em->bm->totedge) &&
- (totface_orig == em->bm->totface))
- {
- EDBM_op_finish(em, &bmop, op, true);
- return OPERATOR_CANCELLED;
- }
+ /* 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;
+ }
#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);
+ {
+ /* 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);
- }
+ 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)) {
- return OPERATOR_CANCELLED;
- }
+ 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;
}
@@ -1015,7 +1031,7 @@ void MESH_OT_mark_seam(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
prop = RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
WM_operatortype_props_advanced_begin(ot);
}
@@ -1088,97 +1104,103 @@ void MESH_OT_mark_sharp(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", "");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ 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 int edbm_vert_connect_exec(bContext *C, wmOperator *op)
+static bool edbm_connect_vert_pair(BMEditMesh *em, 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, &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 bmop;
- bool is_pair = (bm->totvertsel == 2);
- int len = 0;
- bool check_degenerate = true;
- const int verts_len = bm->totvertsel;
- BMVert **verts;
- bool checks_succeded = true;
-
- if (!is_pair) {
- continue;
+ 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 (!is_pair) {
+ 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;
+ }
}
- verts = MEM_mallocN(sizeof(*verts) * verts_len, __func__);
+ if (BM_vert_pair_share_face_check_cb(
+ verts[0], verts[1],
+ BM_elem_cb_check_hflag_disabled_simple(BMFace *, BM_ELEM_HIDDEN)))
{
- BMIter iter;
- BMVert *v;
- int i = 0;
+ check_degenerate = false;
+ is_pair = false;
+ }
+ }
- BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- verts[i++] = v;
- }
- }
+ 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 (is_pair) {
- 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 (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 (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;
- }
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ len = 0;
}
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;
- }
+ EDBM_selectmode_flush(em); /* so newly created edges get the selection state from the vertex */
+
+ EDBM_update_generic(em, true, true);
}
- if (checks_succeded) {
- BMO_op_exec(bm, &bmop);
- len = BMO_slot_get(bmop.slots_out, "edges.out")->len;
+ }
+ MEM_freeN(verts);
- if (len) {
- if (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);
- }
- }
+ return len;
+}
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- len = 0;
- }
- else {
- EDBM_selectmode_flush(em); /* so newly created edges get the selection state from the vertex */
+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, &objects_len);
- EDBM_update_generic(em, true, true);
- }
- }
- MEM_freeN(verts);
- if (len == 0) {
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (!edbm_connect_vert_pair(em, op)) {
failed_objects_len++;
}
}
@@ -1422,43 +1444,66 @@ static bool bm_vert_connect_select_history_edge_to_vert_path(BMesh *bm, ListBase
static int edbm_vert_connect_path_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- bool is_pair = (em->bm->totvertsel == 2);
- ListBase selected_orig = {NULL, NULL};
- int retval;
+ 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, &objects_len);
- /* when there is only 2 vertices, we can ignore selection order */
- if (is_pair) {
- return edbm_vert_connect_exec(C, op);
- }
+ 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->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->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_vert_connect_select_history(bm)) {
- EDBM_selectmode_flush(em);
- EDBM_update_generic(em, true, true);
- retval = OPERATOR_FINISHED;
+ 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;
+ }
}
- else {
+
+ MEM_freeN(objects);
+
+ if (failed_selection_order_len == objects_len) {
BKE_report(op->reports, RPT_ERROR, "Invalid selection order");
- retval = OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
-
- if (!BLI_listbase_is_empty(&selected_orig)) {
- BM_select_history_clear(bm);
- bm->selected = selected_orig;
+ else if (failed_connect_len == objects_len) {
+ BKE_report(op->reports, RPT_ERROR, "Could not connect vertices");
+ return OPERATOR_CANCELLED;
}
- return retval;
+ return OPERATOR_FINISHED;
}
void MESH_OT_vert_connect_path(wmOperatorType *ot)
@@ -1478,20 +1523,29 @@ void MESH_OT_vert_connect_path(wmOperatorType *ot)
static int edbm_vert_connect_concave_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- 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, &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_op_call_and_selectf(
- em, op,
- "faces.out", true,
- "connect_verts_concave faces=%hf",
- BM_ELEM_SELECT))
- {
- return OPERATOR_CANCELLED;
- }
+ 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);
+ }
- EDBM_update_generic(em, true, true);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -1518,22 +1572,32 @@ void MESH_OT_vert_connect_concave(wmOperatorType *ot)
static int edbm_vert_connect_nonplaner_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
+ 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, &objects_len);
- if (!EDBM_op_call_and_selectf(
- em, op,
- "faces.out", true,
- "connect_verts_nonplanar faces=%hf angle_limit=%f",
- BM_ELEM_SELECT, angle_limit))
- {
- return OPERATOR_CANCELLED;
- }
+ 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_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);
return OPERATOR_FINISHED;
}
@@ -2250,7 +2314,7 @@ void MESH_OT_vertices_smooth_laplacian(wmOperatorType *ot)
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", 5e-5f, 1e-7f, 1000.0f,
+ 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);
@@ -3562,7 +3626,7 @@ static Base *mesh_separate_tagged(Main *bmain, Scene *scene, ViewLayer *view_lay
base_new = ED_object_add_duplicate(bmain, scene, view_layer, base_old, USER_DUP_MESH);
/* DAG_relations_tag_update(bmain); */ /* normally would call directly after but in this case delay recalc */
- assign_matarar(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)); /* new in 2.5 */
ED_object_base_select(base_new, BA_SELECT);
@@ -3578,7 +3642,7 @@ static Base *mesh_separate_tagged(Main *bmain, Scene *scene, ViewLayer *view_lay
BM_mesh_normals_update(bm_new);
- BM_mesh_bm_to_me(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_btmesh = NULL;
@@ -3891,7 +3955,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
if (retval_iter) {
BM_mesh_bm_to_me(
- bm_old, me,
+ bmain, bm_old, me,
(&(struct BMeshToMeshParams){
.calc_object_remap = true,
}));
@@ -4290,11 +4354,13 @@ void MESH_OT_fill_grid(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- prop = RNA_def_int(ot->srna, "span", 1, 1, 1000, "Span", "Number of sides (zero disables)", 1, 100);
+ 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", "Number of sides (zero disables)", -100, 100);
+ 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", "");
+ RNA_def_boolean(ot->srna, "use_interp_simple", false, "Simple Blending",
+ "Use simple interpolation of grid vertices");
}
/** \} */
@@ -5248,7 +5314,7 @@ static int edbm_dissolve_degenerate_exec(bContext *C, wmOperator *op)
} /* objects */
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);
@@ -5385,11 +5451,12 @@ static int edbm_split_exec(bContext *C, wmOperator *op)
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (em->bm->totfacesel == 0) {
+ 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);
@@ -6361,73 +6428,89 @@ void MESH_OT_offset_edge_loops(wmOperatorType *ot)
#ifdef WITH_BULLET
static int edbm_convex_hull_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMOperator bmop;
+ 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");
- EDBM_op_init(
- em, &bmop, op, "convex_hull input=%hvef "
- "use_existing_faces=%b",
- BM_ELEM_SELECT,
- RNA_boolean_get(op->ptr, "use_existing_faces"));
- BMO_op_exec(em->bm, &bmop);
+ float angle_face_threshold = RNA_float_get(op->ptr, "face_threshold");
+ float angle_shape_threshold = RNA_float_get(op->ptr, "shape_threshold");
- /* Hull fails if input is coplanar */
- if (BMO_error_occurred(em->bm)) {
- EDBM_op_finish(em, &bmop, op, true);
- 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, &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);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true);
+ if (em->bm->totvertsel == 0) {
+ continue;
+ }
- /* Delete unused vertices, edges, and faces */
- if (RNA_boolean_get(op->ptr, "delete_unused")) {
- if (!EDBM_op_callf(
- em, op, "delete geom=%S context=%i",
- &bmop, "geom_unused.out", DEL_ONLYTAGGED))
- {
+ 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);
- return OPERATOR_CANCELLED;
+ continue;
}
- }
- /* Delete hole edges/faces */
- if (RNA_boolean_get(op->ptr, "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);
- return OPERATOR_CANCELLED;
+ 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;
+ }
}
- }
- /* Merge adjacent triangles */
- if (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");
+ /* 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;
+ }
+ }
- 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);
- return OPERATOR_CANCELLED;
+ /* 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;
}
- }
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- return OPERATOR_CANCELLED;
- }
- else {
EDBM_update_generic(em, true, true);
EDBM_selectmode_flush(em);
- return OPERATOR_FINISHED;
}
+
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void MESH_OT_convex_hull(wmOperatorType *ot)
@@ -6529,7 +6612,8 @@ void MESH_OT_symmetrize(struct wmOperatorType *ot)
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", "", 1e-5f, 0.1f);
+ 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);
}
/** \} */
@@ -6660,9 +6744,11 @@ void MESH_OT_symmetry_snap(struct wmOperatorType *ot)
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", "", 1e-4f, 1.0f);
- RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 1.0f, "Factor", "", 0.0f, 1.0f);
- RNA_def_boolean(ot->srna, "use_center", true, "Center", "Snap mid verts to the axis center");
+ 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");
}
/** \} */
@@ -6749,7 +6835,7 @@ void MESH_OT_mark_freestyle_edge(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", "");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/** \} */
@@ -6832,7 +6918,7 @@ void MESH_OT_mark_freestyle_face(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", "");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/** \} */
diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c
index 4d4b7a098b0..11606840b42 100644
--- a/source/blender/editors/mesh/editmesh_undo.c
+++ b/source/blender/editors/mesh/editmesh_undo.c
@@ -27,6 +27,7 @@
#include "CLG_log.h"
#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_key_types.h"
#include "DNA_layer_types.h"
@@ -35,7 +36,6 @@
#include "BLI_array_utils.h"
#include "BLI_alloca.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_context.h"
#include "BKE_key.h"
#include "BKE_layer.h"
@@ -511,8 +511,8 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key)
/* BM_mesh_validate(em->bm); */ /* for troubleshooting */
BM_mesh_bm_to_me(
- em->bm, &um->me, (&(struct BMeshToMeshParams){
- /* Undo code should not be manipulating 'G.main->object' hooks/vertex-parent. */
+ 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 = CD_MASK_SHAPE_KEYINDEX,
}));
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index e8f3e592715..5481c52269d 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -43,6 +43,7 @@
#include "BKE_DerivedMesh.h"
#include "BKE_context.h"
+#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_report.h"
@@ -172,6 +173,10 @@ bool EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const bool
BKE_editmesh_tessface_calc(em);
}
+ if (em->ob) {
+ DEG_id_tag_update(&((Mesh *)em->ob->data)->id, DEG_TAG_COPY_ON_WRITE);
+ }
+
return false;
}
else {
@@ -326,7 +331,7 @@ void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index)
* \warning This can invalidate the #DerivedMesh cache of other objects (for linked duplicates).
* Most callers should run #DEG_id_tag_update on \a ob->data, see: T46738, T46913
*/
-void EDBM_mesh_load(Object *ob)
+void EDBM_mesh_load(Main *bmain, Object *ob)
{
Mesh *me = ob->data;
BMesh *bm = me->edit_btmesh->bm;
@@ -338,7 +343,7 @@ void EDBM_mesh_load(Object *ob)
}
BM_mesh_bm_to_me(
- bm, me, (&(struct BMeshToMeshParams){
+ bmain, bm, me, (&(struct BMeshToMeshParams){
.calc_object_remap = true,
}));
@@ -358,7 +363,7 @@ void EDBM_mesh_load(Object *ob)
* cycles.
*/
#if 0
- for (Object *other_object = G.main->object.first;
+ for (Object *other_object = bmain->object.first;
other_object != NULL;
other_object = other_object->id.next)
{
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index 676af4fea5b..b4588257412 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -255,7 +255,7 @@ void ED_mesh_uv_loop_reset(struct bContext *C, struct Mesh *me)
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);
}
@@ -301,7 +301,7 @@ int ED_mesh_uv_texture_add(Mesh *me, const char *name, const bool active_set)
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);
@@ -517,7 +517,7 @@ static int mesh_uv_texture_add_exec(bContext *C, wmOperator *UNUSED(op))
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;
}
@@ -527,7 +527,7 @@ void MESH_OT_uv_texture_add(wmOperatorType *ot)
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;
@@ -538,6 +538,7 @@ void MESH_OT_uv_texture_add(wmOperatorType *ot)
static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
Base *base;
@@ -545,7 +546,7 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *e
Mesh *me;
Object *obedit;
int exitmode = 0;
-
+
if (v3d == NULL) {
BKE_report(op->reports, RPT_ERROR, "No 3D View Available");
return OPERATOR_CANCELLED;
@@ -558,7 +559,7 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *e
BKE_report(op->reports, RPT_ERROR, "Not an object or mesh");
return OPERATOR_CANCELLED;
}
-
+
ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
if (!ima) {
return OPERATOR_CANCELLED;
@@ -576,24 +577,24 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *e
}
if (me->edit_btmesh == NULL)
return OPERATOR_CANCELLED;
-
+
if (exitmode) {
- EDBM_mesh_load(obedit);
+ EDBM_mesh_load(bmain, obedit);
EDBM_mesh_free(me->edit_btmesh);
MEM_freeN(me->edit_btmesh);
me->edit_btmesh = NULL;
- /* load_editMesh free's pointers used by CustomData layers which might be used by DerivedMesh too,
- * so signal to re-create DerivedMesh here (sergey) */
+ /* load_editMesh free's pointers used by CustomData layers which might be used by evaluated mesh too,
+ * so signal to re-create evaluated mesh here (sergey) */
DEG_id_tag_update(&me->id, 0);
}
/* dummie drop support; ensure view shows a result :) */
if (v3d)
v3d->flag2 |= V3D_SOLID_TEX;
-
+
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
-
+
return OPERATOR_FINISHED;
}
@@ -603,14 +604,14 @@ void MESH_OT_drop_named_image(wmOperatorType *ot)
ot->name = "Drop Image to Mesh UV Map";
ot->description = "Assign Image to active UV Map, or create an UV Map";
ot->idname = "MESH_OT_drop_named_image";
-
+
/* api callbacks */
ot->poll = layers_poll;
ot->invoke = drop_named_image_invoke;
-
+
/* flags */
ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
-
+
/* properties */
RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Image name to assign");
RNA_def_string(ot->srna, "filepath", "Path", FILE_MAX, "Filepath", "Path to image file");
@@ -630,7 +631,7 @@ static int mesh_uv_texture_remove_exec(bContext *C, wmOperator *UNUSED(op))
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;
}
@@ -640,7 +641,7 @@ void MESH_OT_uv_texture_remove(wmOperatorType *ot)
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;
@@ -668,7 +669,7 @@ void MESH_OT_vertex_color_add(wmOperatorType *ot)
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;
@@ -694,7 +695,7 @@ void MESH_OT_vertex_color_remove(wmOperatorType *ot)
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;
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index b9e9ae9c1fd..75fead00534 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -48,7 +48,7 @@ struct LinkNode;
/* *** editmesh_utils.c *** */
/*
- * ok: the EDBM module is for editmode bmesh stuff. in contrast, the
+ * ok: the EDBM module is for editmode bmesh stuff. in contrast, the
* BMEdit module is for code shared with blenkernel that concerns
* the BMEditMesh structure. */
diff --git a/source/blender/editors/mesh/mesh_mirror.c b/source/blender/editors/mesh/mesh_mirror.c
index 22bfd8eedea..4b526915551 100644
--- a/source/blender/editors/mesh/mesh_mirror.c
+++ b/source/blender/editors/mesh/mesh_mirror.c
@@ -32,11 +32,13 @@
#include "BLI_bitmap.h"
#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
-#include "BKE_DerivedMesh.h"
#include "BLI_kdtree.h"
#include "BKE_editmesh.h"
+#include "BKE_library.h"
+#include "BKE_mesh.h"
#include "ED_mesh.h"
@@ -50,11 +52,11 @@ 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, DerivedMesh *dm, 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, dm, NULL, 's');
+ ED_mesh_mirror_spatial_table(ob, em, me_eval, NULL, 's');
if (MirrKdStore.tree) {
KDTreeNearest nearest;
@@ -70,11 +72,11 @@ int ED_mesh_mirror_spatial_table(Object *ob, BMEditMesh *em, DerivedMesh *dm, co
}
else if (mode == 's') { /* start table */
Mesh *me = ob->data;
- const bool use_em = (!dm && em && me->edit_btmesh == em);
- const int totvert = use_em ? em->bm->totvert : dm ? dm->getNumVerts(dm) : me->totvert;
+ const bool use_em = (!me_eval && em && me->edit_btmesh == 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, dm, co, 'e');
+ ED_mesh_mirror_spatial_table(ob, em, me_eval, co, 'e');
MirrKdStore.tree = BLI_kdtree_new(totvert);
@@ -91,9 +93,9 @@ int ED_mesh_mirror_spatial_table(Object *ob, BMEditMesh *em, DerivedMesh *dm, co
}
}
else {
- MVert *mvert = dm ? dm->getVertArray(dm) : me->mvert;
+ MVert *mvert = me_eval ? me_eval->mvert : me->mvert;
int i;
-
+
for (i = 0; i < totvert; i++, mvert++) {
BLI_kdtree_insert(MirrKdStore.tree, i, mvert->co);
}
@@ -141,15 +143,15 @@ static int mirrtopo_vert_sort(const void *v1, const void *v2)
return 0;
}
-bool ED_mesh_mirrtopo_recalc_check(Mesh *me, DerivedMesh *dm, MirrTopoStore_t *mesh_topo_store)
+bool ED_mesh_mirrtopo_recalc_check(Mesh *me, Mesh *me_eval, MirrTopoStore_t *mesh_topo_store)
{
const bool is_editmode = (me->edit_btmesh != NULL);
int totvert;
int totedge;
- if (dm) {
- totvert = dm->getNumVerts(dm);
- totedge = dm->getNumEdges(dm);
+ if (me_eval) {
+ totvert = me_eval->totvert;
+ totedge = me_eval->totedge;
}
else if (me->edit_btmesh) {
totvert = me->edit_btmesh->bm->totvert;
@@ -174,12 +176,12 @@ bool ED_mesh_mirrtopo_recalc_check(Mesh *me, DerivedMesh *dm, MirrTopoStore_t *m
}
void ED_mesh_mirrtopo_init(
- Mesh *me, DerivedMesh *dm, MirrTopoStore_t *mesh_topo_store,
+ Mesh *me, Mesh *me_eval, MirrTopoStore_t *mesh_topo_store,
const bool skip_em_vert_array_init)
{
const bool is_editmode = (me->edit_btmesh != NULL);
MEdge *medge = NULL, *med;
- BMEditMesh *em = dm ? NULL : me->edit_btmesh;
+ BMEditMesh *em = me_eval ? NULL : me->edit_btmesh;
/* editmode*/
BMEdge *eed;
@@ -208,7 +210,7 @@ void ED_mesh_mirrtopo_init(
totvert = em->bm->totvert;
}
else {
- totvert = dm ? dm->getNumVerts(dm) : me->totvert;
+ totvert = me_eval ? me_eval->totvert : me->totvert;
}
topo_hash = MEM_callocN(totvert * sizeof(MirrTopoHash_t), "TopoMirr");
@@ -224,8 +226,8 @@ void ED_mesh_mirrtopo_init(
}
}
else {
- totedge = dm ? dm->getNumEdges(dm) : me->totedge;
- medge = dm ? dm->getEdgeArray(dm) : me->medge;
+ 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;
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index 9f3ef6f958d..9e3a4c512c6 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -98,12 +98,12 @@ void ED_operatortypes_mesh(void)
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);
@@ -220,7 +220,7 @@ 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");
@@ -317,24 +317,43 @@ void ED_operatormacros_mesh(void)
/* note mesh keymap also for other space? */
void ED_keymap_mesh(wmKeyConfig *keyconf)
-{
+{
wmKeyMap *keymap;
wmKeyMapItem *kmi;
- int i;
-
+
keymap = WM_keymap_find(keyconf, "Mesh", 0, 0);
keymap->poll = ED_operator_editmesh;
-
+
WM_keymap_add_item(keymap, "MESH_OT_loopcut_slide", RKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "MESH_OT_offset_edge_loops_slide", RKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
WM_keymap_add_item(keymap, "MESH_OT_inset", IKEY, KM_PRESS, 0, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "MESH_OT_poke", PKEY, KM_PRESS, KM_ALT, 0);
+#endif
kmi = WM_keymap_add_item(keymap, "MESH_OT_bevel", BKEY, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "vertex_only", false);
kmi = WM_keymap_add_item(keymap, "MESH_OT_bevel", BKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "vertex_only", true);
/* selecting */
+
+ kmi = WM_keymap_add_item(keymap, "MESH_OT_select_mode", ONEKEY, KM_PRESS, 0, 0);
+ RNA_enum_set(kmi->ptr, "type", SCE_SELECT_VERTEX);
+ kmi = WM_keymap_add_item(keymap, "MESH_OT_select_mode", TWOKEY, KM_PRESS, 0, 0);
+ RNA_enum_set(kmi->ptr, "type", SCE_SELECT_EDGE);
+ kmi = WM_keymap_add_item(keymap, "MESH_OT_select_mode", THREEKEY, KM_PRESS, 0, 0);
+ RNA_enum_set(kmi->ptr, "type", SCE_SELECT_FACE);
+
+ kmi = WM_keymap_add_item(keymap, "MESH_OT_select_mode", ONEKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_enum_set(kmi->ptr, "type", SCE_SELECT_VERTEX);
+ RNA_boolean_set(kmi->ptr, "use_extend", true);
+ kmi = WM_keymap_add_item(keymap, "MESH_OT_select_mode", TWOKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_enum_set(kmi->ptr, "type", SCE_SELECT_EDGE);
+ RNA_boolean_set(kmi->ptr, "use_extend", true);
+ kmi = WM_keymap_add_item(keymap, "MESH_OT_select_mode", THREEKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_enum_set(kmi->ptr, "type", SCE_SELECT_FACE);
+ RNA_boolean_set(kmi->ptr, "use_extend", true);
+
/* standard mouse selection goes via space_view3d */
kmi = WM_keymap_add_item(keymap, "MESH_OT_loop_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "extend", false);
@@ -371,21 +390,22 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "MESH_OT_select_next_item", PADPLUSKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
WM_keymap_add_item(keymap, "MESH_OT_select_prev_item", PADMINUS, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "MESH_OT_select_non_manifold", MKEY, KM_PRESS, (KM_CTRL | KM_SHIFT | KM_ALT), 0);
-
+#endif
+
WM_keymap_add_item(keymap, "MESH_OT_select_linked", LKEY, KM_PRESS, KM_CTRL, 0);
kmi = WM_keymap_add_item(keymap, "MESH_OT_select_linked_pick", LKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "deselect", false);
kmi = WM_keymap_add_item(keymap, "MESH_OT_select_linked_pick", LKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "deselect", true);
-
+
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "MESH_OT_faces_select_linked_flat", FKEY, KM_PRESS, (KM_CTRL | KM_SHIFT | KM_ALT), 0);
+#endif
WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_select_similar", GKEY, KM_PRESS, KM_SHIFT, 0);
-
- /* selection mode */
- WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_select_mode", TABKEY, KM_PRESS, KM_CTRL, 0);
-
+
/* hide */
kmi = WM_keymap_add_item(keymap, "MESH_OT_hide", HKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "unselected", false);
@@ -394,20 +414,31 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "MESH_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0);
/* tools */
+#ifdef USE_WM_KEYMAP_27X
kmi = WM_keymap_add_item(keymap, "MESH_OT_normals_make_consistent", NKEY, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "inside", false);
kmi = WM_keymap_add_item(keymap, "MESH_OT_normals_make_consistent", NKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "inside", true);
-
+#else
+ kmi = WM_keymap_add_item(keymap, "MESH_OT_normals_make_consistent", NKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "inside", false);
+ kmi = WM_keymap_add_item(keymap, "MESH_OT_normals_make_consistent", NKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
+ RNA_boolean_set(kmi->ptr, "inside", true);
+#endif
+
WM_keymap_add_item(keymap, "VIEW3D_OT_edit_mesh_extrude_move_normal", EKEY, KM_PRESS, 0, 0); /* python operator */
WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_extrude", EKEY, KM_PRESS, KM_ALT, 0);
-
+
WM_keymap_add_item(keymap, "TRANSFORM_OT_edge_crease", EKEY, KM_PRESS, KM_SHIFT, 0);
-
+
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "MESH_OT_spin", RKEY, KM_PRESS, KM_ALT, 0);
-
+#endif
+
WM_keymap_add_item(keymap, "MESH_OT_fill", FKEY, KM_PRESS, KM_ALT, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "MESH_OT_beautify_fill", FKEY, KM_PRESS, KM_SHIFT | KM_ALT, 0);
+#endif
kmi = WM_keymap_add_item(keymap, "MESH_OT_quads_convert_to_tris", TKEY, KM_PRESS, KM_CTRL, 0);
RNA_enum_set(kmi->ptr, "quad_method", MOD_TRIANGULATE_QUAD_BEAUTY);
@@ -439,9 +470,9 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "MESH_OT_edge_face_add", FKEY, KM_PRESS, 0, 0);
// WM_keymap_add_item(keymap, "MESH_OT_skin", FKEY, KM_PRESS, KM_CTRL|KM_ALT, 0); /* python, removed */
WM_keymap_add_item(keymap, "MESH_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
-
+
WM_keymap_add_menu(keymap, "INFO_MT_mesh_add", AKEY, KM_PRESS, KM_SHIFT, 0);
-
+
WM_keymap_add_item(keymap, "MESH_OT_separate", PKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "MESH_OT_split", YKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "MESH_OT_vert_connect_path", JKEY, KM_PRESS, 0, 0);
@@ -454,20 +485,24 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_CLICK, KM_SHIFT | KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "rotate_source", false);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_delete", XKEY, KM_PRESS, 0, 0);
+#endif
WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_delete", DELKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "MESH_OT_dissolve_mode", XKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "MESH_OT_dissolve_mode", DELKEY, KM_PRESS, KM_CTRL, 0);
-
+
kmi = WM_keymap_add_item(keymap, "MESH_OT_knife_tool", KKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "use_occlude_geometry", true);
RNA_boolean_set(kmi->ptr, "only_selected", false);
+#ifdef USE_WM_KEYMAP_27X
kmi = WM_keymap_add_item(keymap, "MESH_OT_knife_tool", KKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "use_occlude_geometry", false);
RNA_boolean_set(kmi->ptr, "only_selected", true);
-
+#endif
+
WM_keymap_add_item(keymap, "OBJECT_OT_vertex_parent_set", PKEY, KM_PRESS, KM_CTRL, 0);
/* menus */
@@ -478,16 +513,17 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
WM_keymap_add_menu(keymap, "VIEW3D_MT_hook", HKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_menu(keymap, "VIEW3D_MT_uv_map", UKEY, KM_PRESS, 0, 0);
WM_keymap_add_menu(keymap, "VIEW3D_MT_vertex_group", GKEY, KM_PRESS, KM_CTRL, 0);
-
+
+#ifdef USE_WM_KEYMAP_27X
/* useful stuff from object-mode */
- for (i = 0; i <= 5; i++) {
+ for (int i = 0; i <= 5; i++) {
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_subdivision_set", ZEROKEY + i, KM_PRESS, KM_CTRL, 0);
RNA_int_set(kmi->ptr, "level", i);
}
-
+#endif
+
ED_keymap_proportional_cycle(keyconf, keymap);
ED_keymap_proportional_editmode(keyconf, keymap, true);
knifetool_modal_keymap(keyconf);
}
-
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index 83458127820..537056cd1ba 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -34,9 +34,10 @@
#include "MEM_guardedalloc.h"
-#include "DNA_mesh_types.h"
#include "DNA_key_types.h"
#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -49,11 +50,12 @@
#include "BKE_context.h"
#include "BKE_deform.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_key.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
+#include "BKE_mesh_iterators.h"
+#include "BKE_mesh_runtime.h"
#include "BKE_material.h"
#include "BKE_object.h"
#include "BKE_object_deform.h"
@@ -286,7 +288,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
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");
@@ -306,23 +308,23 @@ int join_mesh_exec(bContext *C, wmOperator *op)
totloop += me->totloop;
totpoly += me->totpoly;
totmat += base->object->totcol;
-
+
if (base->object == ob)
ok = true;
-
+
/* check for shapekeys */
if (me->key)
haskey++;
}
}
CTX_DATA_END;
-
- /* that way the active object is always selected */
+
+ /* 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;
@@ -331,7 +333,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
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;
@@ -346,23 +348,23 @@ int join_mesh_exec(bContext *C, wmOperator *op)
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
+ * - 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);
@@ -372,17 +374,17 @@ int join_mesh_exec(bContext *C, wmOperator *op)
}
else if (haskey) {
/* add a new key-block and add to the mesh */
- key = me->key = BKE_key_add((ID *)me);
+ 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, Base *, base, selected_editable_bases)
{
/* only act if a mesh, and not the one we're joining to */
if ((ob != base->object) && (base->object->type == OB_MESH)) {
me = base->object->data;
-
+
/* Join this object's vertex groups to the base one's */
for (dg = base->object->defbase.first; dg; dg = dg->next) {
/* See if this group exists in the object (if it doesn't, add it to the end) */
@@ -394,8 +396,8 @@ int join_mesh_exec(bContext *C, wmOperator *op)
}
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) {
@@ -419,7 +421,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
}
}
}
-
+
/* if this mesh has shapekeys, check if destination mesh already has matching entries too */
if (me->key && key) {
/* for remapping KeyBlock.relative */
@@ -481,7 +483,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
edgeofs = 0;
loopofs = 0;
polyofs = 0;
-
+
/* inverse transform for all selected meshes in this object */
invert_m4_m4(imat, ob->obmat);
@@ -522,10 +524,10 @@ int join_mesh_exec(bContext *C, wmOperator *op)
}
}
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);
@@ -546,7 +548,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
/* 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];
@@ -573,13 +575,13 @@ int join_mesh_exec(bContext *C, wmOperator *op)
/* 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_libblock_free_ex(bmain, nkey, false, false);
}
-
+
/* ensure newly inserted keys are time sorted */
if (key && (key->type != KEY_RELATIVE)) {
BKE_key_sort(key);
@@ -592,6 +594,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
return OPERATOR_FINISHED;
@@ -599,28 +602,29 @@ int join_mesh_exec(bContext *C, wmOperator *op)
/*********************** JOIN AS SHAPES ***************************/
-/* Append selected meshes vertex locations as shapes of the active mesh,
+/* Append selected meshes vertex locations as shapes of the active mesh,
* return 0 if no join is made (error) and 1 of the join is done */
int join_mesh_shapes_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
Depsgraph *depsgraph = CTX_data_depsgraph(C);
Mesh *me = (Mesh *)ob->data;
Mesh *selme = NULL;
- DerivedMesh *dm = NULL;
+ Mesh *me_deformed = NULL;
Key *key = me->key;
KeyBlock *kb;
bool ok = false, nonequal_verts = false;
-
+
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
if (base->object == ob) continue;
-
+
if (base->object->type == OB_MESH) {
selme = (Mesh *)base->object->data;
-
+
if (selme->totvert == me->totvert)
ok = true;
else
@@ -628,7 +632,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op)
}
}
CTX_DATA_END;
-
+
if (!ok) {
if (nonequal_verts)
BKE_report(op->reports, RPT_WARNING, "Selected meshes must have equal numbers of vertices");
@@ -636,41 +640,42 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op)
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((ID *)me);
+ 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, kb);
+ BKE_keyblock_convert_from_mesh(me, key, kb);
}
-
+
/* now ready to add new keys from selected meshes */
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
if (base->object == ob) continue;
-
+
if (base->object->type == OB_MESH) {
selme = (Mesh *)base->object->data;
-
+
if (selme->totvert == me->totvert) {
- dm = mesh_get_derived_deform(depsgraph, scene, base->object, CD_MASK_BAREMESH);
-
- if (!dm) continue;
-
+ me_deformed = mesh_get_eval_deform(depsgraph, scene, base->object, CD_MASK_BAREMESH);
+
+ if (!me_deformed) {
+ continue;
+ }
+
kb = BKE_keyblock_add(key, base->object->id.name + 2);
-
- DM_to_meshkey(dm, me, kb);
-
- dm->release(dm);
+
+ BKE_mesh_runtime_eval_to_meshkey(me_deformed, me, kb);
}
}
}
CTX_DATA_END;
-
+
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
-
+
return OPERATOR_FINISHED;
}
@@ -686,16 +691,15 @@ static MirrTopoStore_t mesh_topo_store = {NULL, -1. - 1, -1};
/* mode is 's' start, or 'e' end, or 'u' use */
/* if end, ob can be NULL */
/* 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, DerivedMesh *dm, char mode)
+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, dm, &mesh_topo_store)) {
- ED_mesh_mirror_topo_table(ob, dm, 's');
+ 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, dm, &mesh_topo_store, false);
+ 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);
@@ -710,35 +714,35 @@ int ED_mesh_mirror_topo_table(
/** \} */
-static int mesh_get_x_mirror_vert_spatial(Object *ob, DerivedMesh *dm, int index)
+static int mesh_get_x_mirror_vert_spatial(Object *ob, Mesh *mesh, int index)
{
Mesh *me = ob->data;
- MVert *mvert = dm ? dm->getVertArray(dm) : me->mvert;
+ 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];
-
- return ED_mesh_mirror_spatial_table(ob, NULL, dm, vec, 'u');
+
+ return ED_mesh_mirror_spatial_table(ob, NULL, mesh, vec, 'u');
}
-static int mesh_get_x_mirror_vert_topo(Object *ob, DerivedMesh *dm, int index)
+static int mesh_get_x_mirror_vert_topo(Object *ob, Mesh *mesh, int index)
{
- if (ED_mesh_mirror_topo_table(ob, dm, 'u') == -1)
+ if (ED_mesh_mirror_topo_table(ob, mesh, 'u') == -1)
return -1;
return mesh_topo_store.index_lookup[index];
}
-int mesh_get_x_mirror_vert(Object *ob, DerivedMesh *dm, int index, const bool use_topology)
+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, dm, index);
+ return mesh_get_x_mirror_vert_topo(ob, me_eval, index);
}
else {
- return mesh_get_x_mirror_vert_spatial(ob, dm, index);
+ return mesh_get_x_mirror_vert_spatial(ob, me_eval, index);
}
}
@@ -746,7 +750,7 @@ static BMVert *editbmesh_get_x_mirror_vert_spatial(Object *ob, BMEditMesh *em, c
{
float vec[3];
int i;
-
+
/* ignore nan verts */
if ((isfinite(co[0]) == false) ||
(isfinite(co[1]) == false) ||
@@ -754,11 +758,11 @@ static BMVert *editbmesh_get_x_mirror_vert_spatial(Object *ob, BMEditMesh *em, c
{
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);
@@ -775,14 +779,14 @@ static BMVert *editbmesh_get_x_mirror_vert_topo(Object *ob, struct BMEditMesh *e
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;
}
@@ -793,7 +797,7 @@ static BMVert *editbmesh_get_x_mirror_vert_topo(Object *ob, struct BMEditMesh *e
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)
{
@@ -865,19 +869,19 @@ static float *editmesh_get_mirror_uv(BMEditMesh *em, int axis, float *uv, float
{
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;
-
+
}
}
}
@@ -926,7 +930,7 @@ static int mirror_facerotation(MFace *a, MFace *b)
else if (a->v2 == b->v1 && a->v3 == b->v2 && a->v1 == b->v3)
return 2;
}
-
+
return -1;
}
@@ -935,8 +939,8 @@ static bool mirror_facecmp(const void *a, const void *b)
return (mirror_facerotation((MFace *)a, (MFace *)b) == -1);
}
-/* BMESH_TODO, convert to MPoly (functions above also) */
-int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, DerivedMesh *dm)
+/* 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;
@@ -947,22 +951,22 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, DerivedMesh *dm)
BLI_assert(em == NULL); /* Does not work otherwise, currently... */
const bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
- const int totvert = dm ? dm->getNumVerts(dm) : me->totvert;
- const int totface = dm ? dm->getNumTessFaces(dm) : me->totface;
+ 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");
- mvert = dm ? dm->getVertArray(dm) : me->mvert;
- mface = dm ? dm->getTessFaceArray(dm) : 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, dm, 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, dm, a, use_topology);
+ mirrorverts[a] = mesh_get_x_mirror_vert(ob, me_eval, a, use_topology);
- ED_mesh_mirror_spatial_table(ob, em, dm, 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++)
@@ -991,7 +995,7 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, DerivedMesh *dm)
BLI_ghash_free(fhash, NULL, NULL);
MEM_freeN(mirrorverts);
-
+
return mirrorfaces;
}
@@ -1038,21 +1042,22 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int
static void ed_mesh_pick_face_vert__mpoly_find(
/* context */
struct ARegion *ar, const float mval[2],
- /* mesh data */
- DerivedMesh *dm, MPoly *mp, MLoop *mloop,
+ /* 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 co[3], sco[2], len;
+ float sco[2];
const int v_idx = ml->v;
- dm->getVertCo(dm, v_idx, co);
+ const float *co = mvert[v_idx].co;
if (ED_view3d_project_float_object(ar, co, sco, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
- len = len_manhattan_v2v2(mval, sco);
- if (len < *r_len_best) {
- *r_len_best = len;
+ 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;
}
}
@@ -1075,7 +1080,7 @@ bool ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], unsigned
struct ARegion *ar = CTX_wm_region(C);
/* derived mesh to find deformed locations */
- DerivedMesh *dm = mesh_get_derived_final(depsgraph, scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX);
+ Mesh *me_eval = mesh_get_eval_final(depsgraph, scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX);
int v_idx_best = ORIGINDEX_NONE;
@@ -1083,36 +1088,38 @@ bool ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], unsigned
const float mval_f[2] = {UNPACK2(mval)};
float len_best = FLT_MAX;
- MPoly *dm_mpoly;
- MLoop *dm_mloop;
- unsigned int dm_mpoly_tot;
+ MPoly *me_eval_mpoly;
+ MLoop *me_eval_mloop;
+ MVert *me_eval_mvert;
+ unsigned int me_eval_mpoly_len;
const int *index_mp_to_orig;
- dm_mpoly = dm->getPolyArray(dm);
- dm_mloop = dm->getLoopArray(dm);
+ me_eval_mpoly = me_eval->mpoly;
+ me_eval_mloop = me_eval->mloop;
+ me_eval_mvert = me_eval->mvert;
- dm_mpoly_tot = dm->getNumPolys(dm);
+ me_eval_mpoly_len = me_eval->totpoly;
- index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
+ 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 < dm_mpoly_tot; 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,
- dm, &dm_mpoly[i], dm_mloop,
+ &me_eval_mpoly[i], me_eval_mvert, me_eval_mloop,
&len_best, &v_idx_best);
}
}
}
else {
- if (poly_index < dm_mpoly_tot) {
+ if (poly_index < me_eval_mpoly_len) {
ed_mesh_pick_face_vert__mpoly_find(
ar, mval_f,
- dm, &dm_mpoly[poly_index], dm_mloop,
+ &me_eval_mpoly[poly_index], me_eval_mvert, me_eval_mloop,
&len_best, &v_idx_best);
}
}
@@ -1120,15 +1127,12 @@ bool ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], unsigned
/* map 'dm -> me' index if possible */
if (v_idx_best != ORIGINDEX_NONE) {
const int *index_mv_to_orig;
-
- index_mv_to_orig = dm->getVertDataArray(dm, CD_ORIGINDEX);
+ 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];
}
}
- dm->release(dm);
-
if ((v_idx_best != ORIGINDEX_NONE) && (v_idx_best < me->totvert)) {
*index = v_idx_best;
return true;
@@ -1202,7 +1206,7 @@ bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int
}
else {
/* derived mesh to find deformed locations */
- DerivedMesh *dm = mesh_get_derived_final(vc.depsgraph, vc.scene, ob, CD_MASK_BAREMESH);
+ Mesh *me_eval = mesh_get_eval_final(vc.depsgraph, vc.scene, ob, CD_MASK_BAREMESH);
ARegion *ar = vc.ar;
RegionView3D *rv3d = ar->regiondata;
@@ -1214,7 +1218,7 @@ bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int
ED_view3d_init_mats_rv3d(ob, rv3d);
- if (dm == NULL) {
+ if (me_eval == NULL) {
return false;
}
@@ -1225,9 +1229,7 @@ bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int
data.len_best = FLT_MAX;
data.v_idx_best = -1;
- dm->foreachMappedVert(dm, ed_mesh_pick_vert__mapFunc, &data, DM_FOREACH_NOP);
-
- dm->release(dm);
+ BKE_mesh_foreach_mapped_vert(me_eval, ed_mesh_pick_vert__mapFunc, &data, MESH_FOREACH_NOP);
if (data.v_idx_best == -1) {
return false;
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index 0835618043d..1ae122a3801 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -19,7 +19,7 @@
* All rights reserved.
*
* The Original Code is: all of this file.
-
+
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
@@ -79,7 +79,7 @@ void ED_mball_editmball_make(Object *obedit)
MetaElem *ml; /*, *newml;*/
ml = mb->elems.first;
-
+
while (ml) {
if (ml->flag & SELECT) mb->lastelem = ml;
ml = ml->next;
@@ -107,7 +107,7 @@ MetaElem *ED_mball_add_primitive(bContext *UNUSED(C), Object *obedit, float mat[
ml->flag &= ~SELECT;
ml = ml->next;
}
-
+
ml = BKE_mball_element_add(mball, type);
ml->rad *= dia;
mball->wiresize *= dia;
@@ -154,6 +154,7 @@ static int mball_select_all_exec(bContext *C, wmOperator *op)
break;
}
+ DEG_id_tag_update(&mb->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
return OPERATOR_FINISHED;
@@ -335,6 +336,7 @@ static int mball_select_similar_exec(bContext *C, wmOperator *op)
}
if (changed) {
+ DEG_id_tag_update(&mb->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
}
@@ -371,7 +373,7 @@ 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, &objects_len);
@@ -403,6 +405,7 @@ static int select_random_metaelems_exec(bContext *C, wmOperator *op)
BLI_rng_free(rng);
+ DEG_id_tag_update(&mb->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
}
MEM_freeN(objects);
@@ -415,14 +418,14 @@ void MBALL_OT_select_random_metaelems(struct wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
WM_operator_properties_select_random(ot);
}
@@ -435,7 +438,7 @@ static int duplicate_metaelems_exec(bContext *C, wmOperator *UNUSED(op))
Object *obedit = CTX_data_edit_object(C);
MetaBall *mb = (MetaBall *)obedit->data;
MetaElem *ml, *newml;
-
+
ml = mb->editelems->last;
if (ml) {
while (ml) {
@@ -477,7 +480,7 @@ static int delete_metaelems_exec(bContext *C, wmOperator *UNUSED(op))
Object *obedit = CTX_data_edit_object(C);
MetaBall *mb = (MetaBall *)obedit->data;
MetaElem *ml, *next;
-
+
ml = mb->editelems->first;
if (ml) {
while (ml) {
@@ -549,7 +552,7 @@ void MBALL_OT_hide_metaelems(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* props */
RNA_def_boolean(ot->srna, "unselected", false, "Unselected", "Hide unselected rather than selected");
}
@@ -575,7 +578,7 @@ static int reveal_metaelems_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_GEOM | ND_DATA, mb);
DEG_id_tag_update(obedit->data, 0);
}
-
+
return OPERATOR_FINISHED;
}
@@ -585,11 +588,11 @@ void MBALL_OT_reveal_metaelems(wmOperatorType *ot)
ot->name = "Reveal";
ot->description = "Reveal all hidden metaelements";
ot->idname = "MBALL_OT_reveal_metaelems";
-
+
/* callback functions */
ot->exec = reveal_metaelems_exec;
ot->poll = ED_operator_editmball;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -614,7 +617,9 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
BLI_rcti_init_pt_radius(&rect, mval, 12);
- hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST);
+ hits = view3d_opengl_select(
+ &vc, buffer, MAXPICKBUF, &rect,
+ VIEW3D_SELECT_PICK_NEAREST, VIEW3D_SELECT_FILTER_NOP);
/* does startelem exist? */
ml = mb->editelems->first;
@@ -624,7 +629,7 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
}
if (ml == NULL) startelem = mb->editelems->first;
-
+
if (hits > 0) {
ml = startelem;
while (ml) {
@@ -644,7 +649,7 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
if (ml == NULL) ml = mb->editelems->first;
if (ml == startelem) break;
}
-
+
/* When some metaelem was found, then it is necessary to select or
* deselect it. */
if (ml_act) {
@@ -667,9 +672,10 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
/* Select only metaelem clicked on */
ml_act->flag |= SELECT;
}
-
+
mb->lastelem = ml_act;
-
+
+ DEG_id_tag_update(&mb->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
return true;
@@ -678,5 +684,3 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
return false;
}
-
-
diff --git a/source/blender/editors/metaball/mball_intern.h b/source/blender/editors/metaball/mball_intern.h
index 24a4ea86d87..927a8acf5db 100644
--- a/source/blender/editors/metaball/mball_intern.h
+++ b/source/blender/editors/metaball/mball_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -47,4 +47,3 @@ void MBALL_OT_select_similar(struct wmOperatorType *ot);
void MBALL_OT_select_random_metaelems(struct wmOperatorType *ot);
#endif
-
diff --git a/source/blender/editors/metaball/mball_ops.c b/source/blender/editors/metaball/mball_ops.c
index 3af85c33bcc..b1b1da00fd6 100644
--- a/source/blender/editors/metaball/mball_ops.c
+++ b/source/blender/editors/metaball/mball_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -45,10 +45,10 @@ void ED_operatortypes_metaball(void)
{
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_select_all);
WM_operatortype_append(MBALL_OT_select_similar);
WM_operatortype_append(MBALL_OT_select_random_metaelems);
@@ -71,22 +71,24 @@ void ED_keymap_metaball(wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
wmKeyMapItem *kmi;
-
+
keymap = WM_keymap_find(keyconf, "Metaball", 0, 0);
keymap->poll = ED_operator_editmball;
WM_keymap_add_item(keymap, "OBJECT_OT_metaball_add", AKEY, KM_PRESS, KM_SHIFT, 0);
-
+
WM_keymap_add_item(keymap, "MBALL_OT_reveal_metaelems", HKEY, KM_PRESS, KM_ALT, 0);
kmi = WM_keymap_add_item(keymap, "MBALL_OT_hide_metaelems", HKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "unselected", false);
kmi = WM_keymap_add_item(keymap, "MBALL_OT_hide_metaelems", HKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "unselected", true);
-
+
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "MBALL_OT_delete_metaelems", XKEY, KM_PRESS, 0, 0);
+#endif
WM_keymap_add_item(keymap, "MBALL_OT_delete_metaelems", DELKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "MBALL_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
-
+
kmi = WM_keymap_add_item(keymap, "MBALL_OT_select_all", AKEY, KM_PRESS, 0, 0);
RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE);
kmi = WM_keymap_add_item(keymap, "MBALL_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0);
@@ -97,4 +99,3 @@ void ED_keymap_metaball(wmKeyConfig *keyconf)
ED_keymap_proportional_cycle(keyconf, keymap);
ED_keymap_proportional_editmode(keyconf, keymap, true);
}
-
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 366667163b0..ac3f8d58de8 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -71,7 +71,6 @@
#include "BKE_displist.h"
#include "BKE_effect.h"
#include "BKE_font.h"
-#include "BKE_group.h"
#include "BKE_lamp.h"
#include "BKE_lattice.h"
#include "BKE_layer.h"
@@ -83,6 +82,7 @@
#include "BKE_material.h"
#include "BKE_mball.h"
#include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
#include "BKE_nla.h"
#include "BKE_object.h"
#include "BKE_particle.h"
@@ -306,7 +306,7 @@ void ED_object_add_generic_props(wmOperatorType *ot, bool do_editmode)
void ED_object_add_mesh_props(wmOperatorType *ot)
{
- RNA_def_boolean(ot->srna, "calc_uvs", false, "Generate UVs", "Generate a default UV map");
+ 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,
@@ -424,8 +424,9 @@ Object *ED_object_add_type(
Object *ob;
/* for as long scene has editmode... */
- if (CTX_data_edit_object(C))
- ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR | EM_DO_UNDO); /* freedata, and undo */
+ if (CTX_data_edit_object(C)) {
+ ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR);
+ }
/* deselects all, sets scene->basact */
ob = BKE_object_add(bmain, scene, view_layer, type, name);
@@ -930,6 +931,7 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv
/* if empty under cursor, then set object */
if (base && base->object->type == OB_EMPTY) {
ob = base->object;
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
}
else {
@@ -944,7 +946,7 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv
/* add under the mouse */
ED_object_location_from_view(C, ob->loc);
- ED_view3d_cursor3d_position(C, ob->loc, event->mval);
+ ED_view3d_cursor3d_position(C, event->mval, false, ob->loc);
}
BKE_object_empty_draw_type_set(ob, OB_EMPTY_IMAGE);
@@ -1011,7 +1013,21 @@ static int object_lamp_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
ob = ED_object_add_type(C, OB_LAMP, get_lamp_defname(type), loc, rot, false, layer);
- BKE_object_obdata_size_init(ob, RNA_float_get(op->ptr, "radius"));
+
+ float size = RNA_float_get(op->ptr, "radius");
+ /* Better defaults for lamp 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 = (Lamp *)ob->data;
la->type = type;
@@ -1047,48 +1063,55 @@ void OBJECT_OT_lamp_add(wmOperatorType *ot)
ED_object_add_generic_props(ot, false);
}
-/********************* Add Group Instance Operator ********************/
+/********************* Add Collection Instance Operator ********************/
-static int group_instance_add_exec(bContext *C, wmOperator *op)
+static int collection_instance_add_exec(bContext *C, wmOperator *op)
{
- Group *group;
+ Main *bmain = CTX_data_main(C);
+ Collection *collection;
unsigned int layer;
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);
- group = (Group *)BKE_libblock_find_name(ID_GR, 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, loc, mval);
+ ED_view3d_cursor3d_position(C, mval, false, loc);
RNA_float_set_array(op->ptr, "location", loc);
}
}
else
- group = BLI_findlink(&CTX_data_main(C)->group, RNA_enum_get(op->ptr, "group"));
+ collection = BLI_findlink(&CTX_data_main(C)->collection, RNA_enum_get(op->ptr, "collection"));
if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &layer, NULL))
return OPERATOR_CANCELLED;
- if (group) {
- Main *bmain = CTX_data_main(C);
+ if (collection) {
Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_add_type(C, OB_EMPTY, group->id.name + 2, loc, rot, false, layer);
- ob->dup_group = group;
- ob->transflag |= OB_DUPLIGROUP;
- id_us_plus(&group->id);
+ 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, layer);
+ ob->dup_group = 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(&group->id, 0);
-
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
return OPERATOR_FINISHED;
@@ -1098,27 +1121,27 @@ static int group_instance_add_exec(bContext *C, wmOperator *op)
}
/* only used as menu */
-void OBJECT_OT_group_instance_add(wmOperatorType *ot)
+void OBJECT_OT_collection_instance_add(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
- ot->name = "Add Group Instance";
- ot->description = "Add a dupligroup instance";
- ot->idname = "OBJECT_OT_group_instance_add";
+ 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 = group_instance_add_exec;
+ ot->exec = collection_instance_add_exec;
ot->poll = ED_operator_objectmode;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- RNA_def_string(ot->srna, "name", "Group", MAX_ID_NAME - 2, "Name", "Group name to add");
- prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "");
- RNA_def_enum_funcs(prop, RNA_group_itemf);
+ 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);
@@ -1196,7 +1219,7 @@ void ED_object_base_free_and_unlink(Main *bmain, Scene *scene, Object *ob)
DEG_id_tag_update_ex(bmain, &ob->id, DEG_TAG_BASE_FLAGS_UPDATE);
- BKE_collections_object_remove(bmain, &scene->id, ob, true);
+ BKE_scene_collections_object_remove(bmain, scene, ob, true);
}
static int object_delete_exec(bContext *C, wmOperator *op)
@@ -1208,7 +1231,7 @@ static int object_delete_exec(bContext *C, wmOperator *op)
const bool use_global = RNA_boolean_get(op->ptr, "use_global");
bool changed = false;
- if (CTX_data_edit_object(C))
+ if (CTX_data_edit_object(C))
return OPERATOR_CANCELLED;
CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
@@ -1282,9 +1305,10 @@ static int object_delete_exec(bContext *C, wmOperator *op)
if (scene->id.tag & LIB_TAG_DOIT) {
scene->id.tag &= ~LIB_TAG_DOIT;
-
+
DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
}
@@ -1330,7 +1354,7 @@ static void copy_object_set_idnew(bContext *C)
/********************* Make Duplicates Real ************************/
/**
- * \note regarding hashing dupli-objects when using OB_DUPLIGROUP, skip the first member of #DupliObject.persistent_id
+ * \note regarding hashing dupli-objects when using OB_DUPLICOLLECTION, skip the first member of #DupliObject.persistent_id
* since its a unique index and we only want to know if the group objects are from the same dupli-group instance.
*/
static unsigned int dupliobject_group_hash(const void *ptr)
@@ -1345,7 +1369,7 @@ static unsigned int dupliobject_group_hash(const void *ptr)
}
/**
- * \note regarding hashing dupli-objects when NOT using OB_DUPLIGROUP, include the first member of #DupliObject.persistent_id
+ * \note regarding hashing dupli-objects when NOT using OB_DUPLICOLLECTION, include the first member of #DupliObject.persistent_id
* since its the index of the vertex/face the object is instantiated on and we want to identify objects on the same vertex/face.
*/
static unsigned int dupliobject_hash(const void *ptr)
@@ -1417,7 +1441,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
dupli_gh = BLI_ghash_ptr_new(__func__);
if (use_hierarchy) {
- if (base->object->transflag & OB_DUPLIGROUP) {
+ if (base->object->transflag & OB_DUPLICOLLECTION) {
parent_gh = BLI_ghash_new(dupliobject_group_hash, dupliobject_group_cmp, __func__);
}
else {
@@ -1437,7 +1461,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
ob_dst->totcol = 0;
}
- BKE_collection_object_add_from(scene, base->object, ob_dst);
+ 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);
@@ -1491,7 +1515,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
* 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_DUPLIGROUP) {
+ 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));
@@ -1536,7 +1560,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
}
}
- if (base->object->transflag & OB_DUPLIGROUP && base->object->dup_group) {
+ if (base->object->transflag & OB_DUPLICOLLECTION && base->object->dup_group) {
for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
if (ob->proxy_group == base->object) {
ob->proxy = NULL;
@@ -1626,10 +1650,10 @@ static void convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Objec
}
}
-static void curvetomesh(Depsgraph *depsgraph, Scene *scene, Object *ob)
+static void curvetomesh(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
{
convert_ensure_curve_cache(depsgraph, scene, ob);
- BKE_mesh_from_nurbs(ob); /* also does users */
+ BKE_mesh_from_nurbs(bmain, ob); /* also does users */
if (ob->type == OB_MESH) {
BKE_object_free_modifiers(ob, 0);
@@ -1658,7 +1682,7 @@ static Base *duplibase_for_convert(Main *bmain, Scene *scene, ViewLayer *view_la
obn = BKE_object_copy(bmain, ob);
DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- BKE_collection_object_add_from(scene, ob, obn);
+ 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);
@@ -1776,7 +1800,7 @@ static int convert_exec(bContext *C, wmOperator *op)
newob = ob;
}
- BKE_mesh_to_curve(depsgraph, scene, newob);
+ BKE_mesh_to_curve(bmain, depsgraph, scene, newob);
if (newob->type == OB_CURVE) {
BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */
@@ -1837,7 +1861,7 @@ static int convert_exec(bContext *C, wmOperator *op)
* datablock, but for until we've got granular update
* lets take care by selves.
*/
- BKE_vfont_to_curve(bmain, newob, FO_EDIT);
+ BKE_vfont_to_curve(newob, FO_EDIT);
newob->type = OB_CURVE;
cu->type = OB_CURVE;
@@ -1878,7 +1902,7 @@ static int convert_exec(bContext *C, wmOperator *op)
BKE_curve_curve_dimension_update(cu);
if (target == OB_MESH) {
- curvetomesh(depsgraph, scene, newob);
+ curvetomesh(bmain, depsgraph, scene, newob);
/* meshes doesn't use displist */
BKE_object_free_curve_cache(newob);
@@ -1902,7 +1926,7 @@ static int convert_exec(bContext *C, wmOperator *op)
newob = ob;
}
- curvetomesh(depsgraph, scene, newob);
+ curvetomesh(bmain, depsgraph, scene, newob);
/* meshes doesn't use displist */
BKE_object_free_curve_cache(newob);
@@ -1990,9 +2014,6 @@ static int convert_exec(bContext *C, wmOperator *op)
}
FOREACH_SCENE_OBJECT_END;
}
-
- /* delete object should renew depsgraph */
- DEG_relations_tag_update(bmain);
}
// XXX ED_object_editmode_enter(C, 0);
@@ -2009,6 +2030,7 @@ static int convert_exec(bContext *C, wmOperator *op)
}
DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
@@ -2038,7 +2060,7 @@ void OBJECT_OT_convert(wmOperatorType *ot)
/**************************** Duplicate ************************/
-/*
+/*
* dupflag: a flag made from constants declared in DNA_userdef_types.h
* The flag tells adduplicate() whether to copy data linked to the object, or to reference the existing data.
* U.dupflag for default operations or you can construct a flag as python does
@@ -2063,33 +2085,33 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer
}
else {
obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
- DEG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA);
base = BKE_view_layer_base_find(view_layer, ob);
- if ((base != NULL) && (base->flag & BASE_VISIBLED)) {
- BKE_collection_object_add_from(scene, ob, obn);
+ 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_ensure(scene, view_layer);
- BKE_collection_object_add(&scene->id, layer_collection->scene_collection, obn);
+ 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);
- /* 1) duplis should end up in same group as the original
- * 2) Rigid Body sim participants MUST always be part of a group...
+ /* 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->flag & OB_FROMGROUP) != 0 || ob->rigidbody_object || ob->rigidbody_constraint) {
- Group *group;
- for (group = bmain->group.first; group; group = group->id.next) {
- if (BKE_group_object_exists(group, ob))
- BKE_group_object_add(group, obn);
+ if (ob->rigidbody_object || ob->rigidbody_constraint) {
+ Collection *collection;
+ for (collection = bmain->collection.first; collection; collection = collection->id.next) {
+ if (BKE_collection_has_object(collection, ob))
+ BKE_collection_object_add(bmain, collection, obn);
}
}
/* duplicates using userflags */
if (dupflag & USER_DUP_ACT) {
- BKE_animdata_copy_id_action(&obn->id, true);
+ BKE_animdata_copy_id_action(bmain, &obn->id, true);
}
if (dupflag & USER_DUP_MAT) {
@@ -2103,7 +2125,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer
id_us_min(id);
if (dupflag & USER_DUP_ACT) {
- BKE_animdata_copy_id_action(&obn->mat[a]->id, true);
+ BKE_animdata_copy_id_action(bmain, &obn->mat[a]->id, true);
}
}
}
@@ -2119,7 +2141,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer
}
if (dupflag & USER_DUP_ACT) {
- BKE_animdata_copy_id_action(&psys->part->id, true);
+ BKE_animdata_copy_id_action(bmain, &psys->part->id, true);
}
id_us_min(id);
@@ -2247,9 +2269,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer
}
if (dupflag & USER_DUP_ACT) {
- BKE_animdata_copy_id_action((ID *)obn->data, true);
+ BKE_animdata_copy_id_action(bmain, (ID *)obn->data, true);
if (key) {
- BKE_animdata_copy_id_action((ID *)key, true);
+ BKE_animdata_copy_id_action(bmain, (ID *)key, true);
}
}
@@ -2344,8 +2366,7 @@ static int duplicate_exec(bContext *C, wmOperator *op)
BKE_main_id_clear_newpoins(bmain);
DEG_relations_tag_update(bmain);
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(&CTX_data_scene(C)->id, 0);
+ DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
@@ -2391,7 +2412,7 @@ static int add_named_exec(bContext *C, wmOperator *op)
/* find object, create fake base */
RNA_string_get(op->ptr, "name", name);
- ob = (Object *)BKE_libblock_find_name(ID_OB, name);
+ ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, name);
if (ob == NULL) {
BKE_report(op->reports, RPT_ERROR, "Object not found");
@@ -2414,9 +2435,9 @@ static int add_named_exec(bContext *C, wmOperator *op)
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, basen->object->loc, mval);
+ ED_view3d_cursor3d_position(C, mval, false, basen->object->loc);
}
-
+
ED_object_base_select(basen, BA_SELECT);
ED_object_base_activate(C, basen);
@@ -2427,6 +2448,7 @@ static int add_named_exec(bContext *C, wmOperator *op)
/* TODO(sergey): Only update relations for the current scene. */
DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index a8da5c038b4..8ad0d09a9fb 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -118,6 +118,7 @@ typedef struct MultiresBakerJobData {
/* data passing to multires-baker job */
typedef struct {
+ Scene *scene;
ListBase data;
bool bake_clear; /* Clear the images before baking */
int bake_filter; /* Bake-filter, aka margin */
@@ -241,7 +242,7 @@ static DerivedMesh *multiresbake_create_loresdm(Scene *scene, Object *ob, int *l
tmp_mmd.lvl = *lvl;
tmp_mmd.sculptlvl = *lvl;
- dm = multires_make_derived_from_derived(cddm, &tmp_mmd, ob, 0);
+ dm = multires_make_derived_from_derived(cddm, &tmp_mmd, scene, ob, 0);
cddm->release(cddm);
return dm;
@@ -268,7 +269,7 @@ static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *l
tmp_mmd.lvl = mmd->totlvl;
tmp_mmd.sculptlvl = mmd->totlvl;
- dm = multires_make_derived_from_derived(cddm, &tmp_mmd, ob, 0);
+ dm = multires_make_derived_from_derived(cddm, &tmp_mmd, scene, ob, 0);
cddm->release(cddm);
return dm;
@@ -371,6 +372,7 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op)
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;
@@ -413,6 +415,7 @@ static void init_multiresbake_job(bContext *C, MultiresBakeJob *bkj)
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;
@@ -474,6 +477,7 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa
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;
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index b49a58b3766..5210182510f 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -276,7 +276,7 @@ static void refresh_images(BakeImages *bake_images)
Image *ima = bake_images->data[i].image;
if (ima->ok == IMA_OK_LOADED) {
GPU_free_image(ima);
- DEG_id_tag_update(&ima->id, 0);
+ DEG_id_tag_update(&ima->id, 0);
}
}
}
@@ -625,7 +625,7 @@ static size_t initialize_internal_images(BakeImages *bake_images, ReportList *re
/* create new mesh with edit mode changes and modifiers applied */
static Mesh *bake_mesh_new_from_object(Depsgraph *depsgraph, Main *bmain, Scene *scene, Object *ob)
{
- ED_object_editmode_load(ob);
+ ED_object_editmode_load(bmain, ob);
Mesh *me = BKE_mesh_new_from_object(depsgraph, bmain, scene, ob, 1, 0, 0);
if (me->flag & ME_AUTOSMOOTH) {
@@ -893,7 +893,7 @@ static int bake(
/* the baking itself */
for (i = 0; i < tot_highpoly; i++) {
- ok = RE_bake_engine(re, view_layer, highpoly[i].ob, i, pixel_array_high,
+ 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);
@@ -920,7 +920,7 @@ cage_cleanup:
ob_low->restrictflag &= ~OB_RESTRICT_RENDER;
if (RE_bake_has_engine(re)) {
- ok = RE_bake_engine(re, view_layer, ob_low, 0, pixel_array_low, num_pixels, depth, pass_type, pass_filter, result);
+ ok = RE_bake_engine(re, depsgraph, ob_low, 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");
@@ -1021,7 +1021,8 @@ cage_cleanup:
BakeData *bake = &scene->r.bake;
char name[FILE_MAX];
- BKE_image_path_from_imtype(name, filepath, bmain->name, 0, bake->im_format.imtype, true, false, NULL);
+ 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, "_");
@@ -1120,6 +1121,8 @@ cleanup:
if (me_cage)
BKE_libblock_free(bmain, me_cage);
+ DEG_graph_free(depsgraph);
+
return op_result;
}
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 6a0dedd1d43..2ede8caf7de 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -91,17 +91,17 @@ ListBase *get_active_constraints(Object *ob)
{
if (ob == NULL)
return NULL;
-
+
if (ob->mode & OB_MODE_POSE) {
bPoseChannel *pchan;
-
+
pchan = BKE_pose_channel_active(ob);
if (pchan)
return &pchan->constraints;
}
- else
+ else
return &ob->constraints;
-
+
return NULL;
}
@@ -110,33 +110,33 @@ ListBase *get_constraint_lb(Object *ob, bConstraint *con, bPoseChannel **r_pchan
{
if (r_pchan)
*r_pchan = NULL;
-
+
if (ELEM(NULL, ob, con))
return NULL;
-
+
/* 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;
-
- /* try each bone in order
+
+ /* 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;
-
+
return &pchan->constraints;
}
}
}
-
+
/* done */
return NULL;
}
@@ -152,59 +152,59 @@ bConstraint *get_active_constraint(Object *ob)
/* ------------- PyConstraints ------------------ */
/* this callback sets the text-file to be used for selected menu item */
-static void validate_pyconstraint_cb(void *arg1, void *arg2)
+static void validate_pyconstraint_cb(Main *bmain, void *arg1, void *arg2)
{
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 = G.main->text.first, i = 1; text && index != i; i++, text = text->id.next) ;
+ for (text = bmain->text.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(Text *con_text, int *pyconindex)
+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;
-
+
/* add title first */
sprintf(buf, "Scripts: %%t|[None]%%x0|");
BLI_dynstr_append(pupds, buf);
-
+
/* init active-index first */
if (con_text == NULL)
*pyconindex = 0;
-
+
/* loop through markers, adding them */
- for (text = G.main->text.first, i = 1; text; i++, text = text->id.next) {
+ for (text = bmain->text.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);
-
+
sprintf(buf, "%%x%d", i);
BLI_dynstr_append(pupds, buf);
-
+
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);
-
+
return str;
}
#endif /* WITH_PYTHON */
@@ -232,11 +232,11 @@ static void set_constraint_nth_target(bConstraint *con, Object *target, const ch
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);
@@ -246,7 +246,7 @@ static void set_constraint_nth_target(bConstraint *con, Object *target, const ch
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;
@@ -254,7 +254,7 @@ static void set_constraint_nth_target(bConstraint *con, Object *target, const ch
break;
}
}
-
+
if (cti->flush_constraint_targets)
cti->flush_constraint_targets(con, &targets, 0);
}
@@ -262,7 +262,7 @@ static void set_constraint_nth_target(bConstraint *con, Object *target, const ch
/* ------------- Constraint Sanity Testing ------------------- */
-static void test_constraint(Object *owner, bPoseChannel *pchan, bConstraint *con, int type)
+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};
@@ -280,7 +280,7 @@ static void test_constraint(Object *owner, bPoseChannel *pchan, bConstraint *con
* the constraint is deemed invalid
*/
/* default IK check ... */
- if (BKE_object_exists_check(data->tar) == 0) {
+ if (BKE_object_exists_check(bmain, data->tar) == 0) {
data->tar = NULL;
con->flag |= CONSTRAINT_DISABLE;
}
@@ -291,7 +291,7 @@ static void test_constraint(Object *owner, bPoseChannel *pchan, bConstraint *con
}
if (data->poletar) {
- if (BKE_object_exists_check(data->poletar) == 0) {
+ if (BKE_object_exists_check(bmain, data->poletar) == 0) {
data->poletar = NULL;
con->flag |= CONSTRAINT_DISABLE;
}
@@ -310,7 +310,7 @@ static void test_constraint(Object *owner, bPoseChannel *pchan, bConstraint *con
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(data->tar) == 0) {
+ if (data->tar && BKE_object_exists_check(bmain, data->tar) == 0) {
data->tar = NULL;
con->flag |= CONSTRAINT_DISABLE;
}
@@ -433,7 +433,7 @@ static void test_constraint(Object *owner, bPoseChannel *pchan, bConstraint *con
/* 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(ct->tar) == 0) {
+ if (BKE_object_exists_check(bmain, ct->tar) == 0) {
/* object doesn't exist, but constraint requires target */
ct->tar = NULL;
con->flag |= CONSTRAINT_DISABLE;
@@ -503,12 +503,12 @@ static int constraint_type_get(Object *owner, bPoseChannel *pchan)
/* checks validity of object pointers, and NULLs,
* if Bone doesnt exist it sets the CONSTRAINT_DISABLE flag.
*/
-static void test_constraints(Object *owner, bPoseChannel *pchan)
+static void test_constraints(Main *bmain, Object *owner, bPoseChannel *pchan)
{
bConstraint *curcon;
ListBase *conlist = NULL;
int type;
-
+
if (owner == NULL) return;
type = constraint_type_get(owner, pchan);
@@ -522,48 +522,48 @@ static void test_constraints(Object *owner, bPoseChannel *pchan)
conlist = &pchan->constraints;
break;
}
-
+
/* Check all constraints - is constraint valid? */
if (conlist) {
for (curcon = conlist->first; curcon; curcon = curcon->next) {
- test_constraint(owner, pchan, curcon, type);
+ test_constraint(bmain, owner, pchan, curcon, type);
}
}
}
-void object_test_constraints(Object *owner)
+void object_test_constraints(Main *bmain, Object *owner)
{
if (owner->constraints.first)
- test_constraints(owner, NULL);
-
+ test_constraints(bmain, owner, NULL);
+
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(owner, pchan);
+ test_constraints(bmain, owner, pchan);
}
}
}
-static void object_test_constraint(Object *owner, bConstraint *con)
+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(owner, NULL, con, CONSTRAINT_OBTYPE_OBJECT);
+ 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(owner, pchan, con, CONSTRAINT_OBTYPE_BONE);
+ test_constraint(bmain, owner, pchan, con, CONSTRAINT_OBTYPE_BONE);
break;
}
}
}
}
else {
- test_constraint(owner, NULL, con, CONSTRAINT_OBTYPE_OBJECT);
+ test_constraint(bmain, owner, NULL, con, CONSTRAINT_OBTYPE_OBJECT);
}
}
@@ -623,24 +623,24 @@ static int edit_constraint_invoke_properties(bContext *C, wmOperator *op)
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 (ptr.data) {
con = ptr.data;
RNA_string_set(op->ptr, "constraint", con->name);
-
+
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);
-
+
return 1;
}
-
+
return 0;
}
@@ -650,9 +650,9 @@ static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int
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;
}
@@ -671,14 +671,14 @@ static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int
//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;
}
@@ -689,18 +689,19 @@ 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;
-
+
/* 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(ob);
-
+ ED_object_constraint_update(bmain, ob);
+
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, NULL);
return OPERATOR_FINISHED;
}
@@ -719,15 +720,15 @@ void CONSTRAINT_OT_stretchto_reset(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
edit_constraint_properties(ot);
}
@@ -735,18 +736,19 @@ void CONSTRAINT_OT_stretchto_reset(wmOperatorType *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;
-
+
/* 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(ob);
-
+ ED_object_constraint_update(bmain, ob);
+
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, NULL);
return OPERATOR_FINISHED;
}
@@ -765,15 +767,15 @@ void CONSTRAINT_OT_limitdistance_reset(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
edit_constraint_properties(ot);
}
@@ -786,7 +788,7 @@ static void child_get_inverse_matrix(const bContext *C, Scene *scene, Object *ob
/* 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 */
@@ -881,11 +883,11 @@ static int childof_set_inverse_exec(bContext *C, wmOperator *op)
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);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -903,15 +905,15 @@ void CONSTRAINT_OT_childof_set_inverse(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
edit_constraint_properties(ot);
}
@@ -922,17 +924,17 @@ static int childof_clear_inverse_exec(bContext *C, wmOperator *op)
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;
}
-
+
/* simply clear the matrix */
unit_m4(data->invmat);
-
+
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -950,15 +952,15 @@ void CONSTRAINT_OT_childof_clear_inverse(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
edit_constraint_properties(ot);
}
@@ -967,33 +969,34 @@ void CONSTRAINT_OT_childof_clear_inverse(wmOperatorType *ot)
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(&cu->id, 1);
+ act = verify_adt_action(bmain, &cu->id, 1);
fcu = verify_fcurve(act, NULL, NULL, "eval_time", 0, 1);
-
+
/* standard vertical range - 1:1 = 100 frames */
standardRange = 100.0f;
}
@@ -1008,46 +1011,46 @@ static int followpath_path_animate_exec(bContext *C, wmOperator *op)
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(&ob->id, 1);
+ act = verify_adt_action(bmain, &ob->id, 1);
fcu = verify_fcurve(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)
+ 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;
@@ -1070,20 +1073,20 @@ void CONSTRAINT_OT_followpath_path_animate(wmOperatorType *ot)
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",
+ 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",
+ RNA_def_int(ot->srna, "length", 100, 0, MAXFRAME, "Length",
"Number of frames that path animation should take", 0, MAXFRAME);
}
@@ -1125,7 +1128,7 @@ void CONSTRAINT_OT_objectsolver_set_inverse(wmOperatorType *ot)
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;
@@ -1133,7 +1136,7 @@ void CONSTRAINT_OT_objectsolver_set_inverse(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
edit_constraint_properties(ot);
}
@@ -1171,7 +1174,7 @@ void CONSTRAINT_OT_objectsolver_clear_inverse(wmOperatorType *ot)
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;
@@ -1179,7 +1182,7 @@ void CONSTRAINT_OT_objectsolver_clear_inverse(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
edit_constraint_properties(ot);
}
@@ -1187,26 +1190,26 @@ void CONSTRAINT_OT_objectsolver_clear_inverse(wmOperatorType *ot)
/***************************** BUTTONS ****************************/
void ED_object_constraint_set_active(Object *ob, bConstraint *con)
-{
+{
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;
-
+
BKE_constraints_active_set(lb, con);
}
-void ED_object_constraint_update(Object *ob)
+void ED_object_constraint_update(Main *bmain, Object *ob)
{
if (ob->pose) BKE_pose_update_constraint_flags(ob->pose);
- object_test_constraints(ob);
+ object_test_constraints(bmain, ob);
- if (ob->type == OB_ARMATURE)
+ if (ob->type == OB_ARMATURE)
DEG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB);
- else
+ else
DEG_id_tag_update(&ob->id, OB_RECALC_OB);
}
@@ -1225,7 +1228,7 @@ static void object_pose_tag_update(Main *bmain, Object *ob)
void ED_object_constraint_dependency_update(Main *bmain, Object *ob)
{
- ED_object_constraint_update(ob);
+ ED_object_constraint_update(bmain, ob);
if (ob->pose) {
object_pose_tag_update(bmain, ob);
@@ -1233,23 +1236,28 @@ void ED_object_constraint_dependency_update(Main *bmain, Object *ob)
DEG_relations_tag_update(bmain);
}
-void ED_object_constraint_tag_update(Object *ob, bConstraint *con)
+void ED_object_constraint_tag_update(Main *bmain, Object *ob, bConstraint *con)
{
if (ob->pose) {
BKE_pose_tag_update_constraint_flags(ob->pose);
}
- object_test_constraint(ob, con);
+ object_test_constraint(bmain, ob, con);
if (ob->type == OB_ARMATURE)
DEG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB);
else
DEG_id_tag_update(&ob->id, OB_RECALC_OB);
+
+ /* Do Copy-on-Write tag here too, otherwise constraint
+ * influence/mute buttons in UI have no effect
+ */
+ DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
}
void ED_object_constraint_dependency_tag_update(Main *bmain, Object *ob, bConstraint *con)
{
- ED_object_constraint_tag_update(ob, con);
+ ED_object_constraint_tag_update(bmain, ob, con);
if (ob->pose) {
object_pose_tag_update(bmain, ob);
@@ -1266,6 +1274,7 @@ static int constraint_poll(bContext *C)
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;
@@ -1275,14 +1284,14 @@ static int constraint_delete_exec(bContext *C, wmOperator *UNUSED(op))
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);
- ED_object_constraint_update(ob); /* needed to set the flags on posebones correctly */
+ ED_object_constraint_update(bmain, ob); /* needed to set the flags on posebones correctly */
/* relatiols */
DEG_relations_tag_update(CTX_data_main(C));
/* notifiers */
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
-
+
return OPERATOR_FINISHED;
}
else {
@@ -1297,11 +1306,11 @@ void CONSTRAINT_OT_delete(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1311,20 +1320,20 @@ 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);
-
+
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);
-
+
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
-
+
return OPERATOR_FINISHED;
}
-
+
return OPERATOR_CANCELLED;
}
@@ -1342,15 +1351,15 @@ void CONSTRAINT_OT_move_down(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
edit_constraint_properties(ot);
}
@@ -1360,20 +1369,20 @@ 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);
-
+
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);
-
+
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
-
+
return OPERATOR_FINISHED;
}
-
+
return OPERATOR_CANCELLED;
}
@@ -1391,12 +1400,12 @@ void CONSTRAINT_OT_move_up(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
edit_constraint_properties(ot);
@@ -1410,7 +1419,7 @@ static int pose_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
-
+
/* free constraints for all selected bones */
CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
{
@@ -1418,16 +1427,16 @@ static int pose_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op))
pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_SPLINEIK | PCHAN_HAS_CONST);
}
CTX_DATA_END;
-
+
/* force depsgraph to get recalculated since relationships removed */
DEG_relations_tag_update(bmain);
-
+
/* note, calling BIK_clear_data() isn't needed here */
/* do updates */
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -1437,7 +1446,7 @@ void POSE_OT_constraints_clear(wmOperatorType *ot)
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?
@@ -1447,7 +1456,7 @@ void POSE_OT_constraints_clear(wmOperatorType *ot)
static int object_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
-
+
/* do freeing */
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
@@ -1455,13 +1464,13 @@ static int object_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op))
DEG_id_tag_update(&ob->id, OB_RECALC_OB);
}
CTX_DATA_END;
-
+
/* 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);
-
+
return OPERATOR_FINISHED;
}
@@ -1471,7 +1480,7 @@ void OBJECT_OT_constraints_clear(wmOperatorType *ot)
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;
@@ -1485,19 +1494,19 @@ static int pose_constraint_copy_exec(bContext *C, wmOperator *op)
bPoseChannel *pchan = CTX_data_active_pose_bone(C);
ListBase lb;
CollectionPointerLink *link;
-
+
/* 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;
}
-
+
/* copy all constraints from active posebone to all selected posebones */
CTX_data_selected_pose_bones(C, &lb);
for (link = lb.first; link; link = link->next) {
Object *ob = link->ptr.id.data;
bPoseChannel *chan = link->ptr.data;
-
+
/* 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);
@@ -1509,12 +1518,12 @@ static int pose_constraint_copy_exec(bContext *C, wmOperator *op)
}
}
BLI_freelistN(&lb);
-
+
/* force depsgraph to get recalculated since new relationships added */
DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -1524,7 +1533,7 @@ void POSE_OT_constraints_copy(wmOperatorType *ot)
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;
@@ -1537,7 +1546,7 @@ static int object_constraint_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
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)
{
@@ -1548,13 +1557,13 @@ static int object_constraint_copy_exec(bContext *C, wmOperator *UNUSED(op))
}
}
CTX_DATA_END;
-
+
/* 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);
-
+
return OPERATOR_FINISHED;
}
@@ -1564,7 +1573,7 @@ void OBJECT_OT_constraints_copy(wmOperatorType *ot)
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;
@@ -1582,15 +1591,15 @@ static bool get_new_constraint_target(bContext *C, int con_type, Object **tar_ob
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
+
+ /* 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
+ * - if so, no need to get any targets
*/
switch (con_type) {
/* no-target constraints --------------------------- */
@@ -1602,7 +1611,7 @@ static bool get_new_constraint_target(bContext *C, int con_type, Object **tar_ob
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 */
@@ -1613,7 +1622,7 @@ static bool get_new_constraint_target(bContext *C, int con_type, Object **tar_ob
only_ob = true;
add = false;
break;
-
+
/* mesh only? */
case CONSTRAINT_TYPE_SHRINKWRAP:
only_mesh = true;
@@ -1621,7 +1630,7 @@ static bool get_new_constraint_target(bContext *C, int con_type, Object **tar_ob
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 */
@@ -1632,20 +1641,20 @@ static bool get_new_constraint_target(bContext *C, int con_type, Object **tar_ob
*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
+ /* 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
@@ -1658,7 +1667,7 @@ static bool get_new_constraint_target(bContext *C, int con_type, Object **tar_ob
*tar_ob = ob;
*tar_pchan = BKE_pose_channel_active(ob);
found = true;
-
+
break;
}
else if (((!only_curve) || (ob->type == OB_CURVE)) &&
@@ -1667,21 +1676,21 @@ static bool get_new_constraint_target(bContext *C, int con_type, Object **tar_ob
/* 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);
@@ -1689,18 +1698,18 @@ static bool get_new_constraint_target(bContext *C, int con_type, Object **tar_ob
ViewLayer *view_layer = CTX_data_view_layer(C);
Base *base = BASACT(view_layer), *newbase = NULL;
Object *obt;
-
+
/* add new target object */
obt = BKE_object_add(bmain, scene, view_layer, OB_EMPTY, NULL);
-
+
/* set layers OK */
newbase = BASACT(view_layer);
newbase->lay = base->lay;
obt->lay = newbase->lay;
-
+
/* 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
+ /* 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)
@@ -1715,12 +1724,12 @@ static bool get_new_constraint_target(bContext *C, int con_type, Object **tar_ob
/* 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;
}
@@ -1731,13 +1740,13 @@ static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase
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");
@@ -1756,23 +1765,23 @@ static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase
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 requried, 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
+ /* 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)
@@ -1781,7 +1790,7 @@ static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase
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 */
@@ -1790,15 +1799,15 @@ static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase
char *menustr;
int scriptint = 0;
/* popup a list of usable scripts */
- menustr = buildmenu_pyconstraints(NULL, &scriptint);
+ 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(con->data, &scriptint);
-
+ validate_pyconstraint_cb(bmain, con->data, &scriptint);
+
/* make sure target allowance is set correctly */
BPY_pyconstraint_update(ob, con);
}
@@ -1809,9 +1818,9 @@ static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase
default:
break;
}
-
+
/* make sure all settings are valid - similar to above checks, but sometimes can be wrong */
- object_test_constraints(ob);
+ object_test_constraints(bmain, ob);
if (pchan)
BKE_pose_update_constraint_flags(ob->pose);
@@ -1819,7 +1828,7 @@ static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase
/* 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) {
@@ -1832,10 +1841,10 @@ static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase
}
else
DEG_id_tag_update(&ob->id, OB_RECALC_OB);
-
+
/* notifiers for updates */
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_ADDED, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -1847,12 +1856,12 @@ 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;
-
+
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
*/
@@ -1868,18 +1877,18 @@ 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;
-
+
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;
-
+
return constraint_add_exec(C, op, ob, get_active_constraints(ob), type, with_targets);
}
@@ -1891,15 +1900,15 @@ void OBJECT_OT_constraint_add(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", "");
}
@@ -1910,15 +1919,15 @@ void OBJECT_OT_constraint_add_with_targets(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", "");
}
@@ -1929,15 +1938,15 @@ void POSE_OT_constraint_add(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", "");
}
@@ -1948,15 +1957,15 @@ void POSE_OT_constraint_add_with_targets(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", "");
}
@@ -1971,18 +1980,18 @@ static int pose_ik_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED
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;
@@ -1991,14 +2000,14 @@ static int pose_ik_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED
BKE_report(op->reports, RPT_ERROR, "Bone already has an IK constraint");
return OPERATOR_CANCELLED;
}
-
+
/* prepare popup menu to choose targetting 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?
+ /* bone target, or object target?
* - the only thing that matters is that we want a target...
*/
if (tar_pchan)
@@ -2011,10 +2020,10 @@ static int pose_ik_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED
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;
}
@@ -2023,7 +2032,7 @@ 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");
-
+
/* 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);
}
@@ -2034,15 +2043,15 @@ void POSE_OT_ik_add(wmOperatorType *ot)
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;
-
+
/* 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");
}
@@ -2053,12 +2062,12 @@ void POSE_OT_ik_add(wmOperatorType *ot)
static int pose_ik_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
-
+
/* only remove IK Constraints */
CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
{
bConstraint *con, *next;
-
+
/* TODO: should we be checking if these contraints were local before we try and remove them? */
for (con = pchan->constraints.first; con; con = next) {
next = con->next;
@@ -2069,13 +2078,13 @@ static int pose_ik_clear_exec(bContext *C, wmOperator *UNUSED(op))
pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_TARGET);
}
CTX_DATA_END;
-
+
/* refresh depsgraph */
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -2085,12 +2094,11 @@ void POSE_OT_ik_clear(wmOperatorType *ot)
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;
-
+
/* 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 d4e8955b38e..788f0826848 100644
--- a/source/blender/editors/object/object_data_transfer.c
+++ b/source/blender/editors/object/object_data_transfer.c
@@ -40,9 +40,9 @@
#include "BKE_context.h"
#include "BKE_data_transfer.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_mesh_remap.h"
+#include "BKE_mesh_runtime.h"
#include "BKE_object.h"
#include "BKE_report.h"
@@ -136,20 +136,17 @@ static const EnumPropertyItem *dt_layers_select_src_itemf(
Scene *scene = CTX_data_scene(C);
if (ob_src) {
- DerivedMesh *dm_src;
- CustomData *ldata;
+ Mesh *me_eval;
int num_data, i;
- /* XXX Is this OK? */
- dm_src = mesh_get_derived_final(depsgraph, scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPUV);
- ldata = dm_src->getLoopDataLayout(dm_src);
- num_data = CustomData_number_of_layers(ldata, CD_MLOOPUV);
+ me_eval = mesh_get_eval_final(depsgraph, scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPUV);
+ 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(ldata, CD_MLOOPUV, 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);
}
}
@@ -159,20 +156,17 @@ static const EnumPropertyItem *dt_layers_select_src_itemf(
Scene *scene = CTX_data_scene(C);
if (ob_src) {
- DerivedMesh *dm_src;
- CustomData *ldata;
+ Mesh *me_eval;
int num_data, i;
- /* XXX Is this OK? */
- dm_src = mesh_get_derived_final(depsgraph, scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPCOL);
- ldata = dm_src->getLoopDataLayout(dm_src);
- num_data = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
+ me_eval = mesh_get_eval_final(depsgraph, scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPCOL);
+ 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(ldata, CD_MLOOPCOL, 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);
}
}
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 4b13419f425..e14842c0daa 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -96,6 +96,7 @@
#include "ED_mball.h"
#include "ED_lattice.h"
#include "ED_object.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
#include "ED_undo.h"
#include "ED_image.h"
@@ -112,6 +113,7 @@
#include "WM_api.h"
#include "WM_types.h"
#include "WM_message.h"
+#include "WM_toolsystem.h"
#include "object_intern.h" // own include
@@ -144,16 +146,248 @@ Object *ED_object_active_context(bContext *C)
return ob;
}
+/* ********************** object hiding *************************** */
+
+static int 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);
+ }
+}
+
+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) {
+ ED_object_base_select(base, BA_SELECT);
+ }
+ }
+ }
+
+ if (!changed) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_layer_collection_sync(scene, view_layer);
+ DEG_id_tag_update(&scene->id, DEG_TAG_BASE_FLAGS_UPDATE);
+ 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";
+
+ /* api callbacks */
+ ot->exec = object_hide_view_clear_exec;
+ ot->poll = object_hide_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ PropertyRNA *prop = RNA_def_boolean(ot->srna, "select", false, "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");
+
+ /* Do nothing if no objects was selected. */
+ bool have_selected = false;
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->flag & BASE_VISIBLE) {
+ if (base->flag & BASE_SELECTED) {
+ have_selected = true;
+ break;
+ }
+ }
+ }
+
+ if (!have_selected) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* 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;
+ }
+ }
+ else {
+ if (!(base->flag & BASE_SELECTED)) {
+ ED_object_base_select(base, BA_DESELECT);
+ base->flag |= BASE_HIDDEN;
+ }
+ }
+ }
+
+ BKE_layer_collection_sync(scene, view_layer);
+ DEG_id_tag_update(&scene->id, DEG_TAG_BASE_FLAGS_UPDATE);
+ 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);
+}
+
+static int object_hide_collection_exec(bContext *C, wmOperator *op)
+{
+ int index = RNA_int_get(op->ptr, "collection_index");
+ bool extend = (CTX_wm_window(C)->eventstate->shift != 0);
+
+ if (CTX_wm_window(C)->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);
+
+ if (!lc) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_layer_collection_set_visible(scene, view_layer, lc, extend);
+
+ DEG_id_tag_update(&scene->id, DEG_TAG_BASE_FLAGS_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+#define COLLECTION_INVALID_INDEX -1
+
+void ED_hide_collections_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->collection->flag & COLLECTION_RESTRICT_VIEW) {
+ continue;
+ }
+
+ if ((view_layer->runtime_flag & VIEW_LAYER_HAS_HIDE) &&
+ !(lc->runtime_flag & LAYER_COLLECTION_HAS_VISIBLE_OBJECTS))
+ {
+ uiLayoutSetActive(row, false);
+ }
+
+ 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);
+ }
+
+ /* 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_hide_collections_menu_draw(C, layout);
+
+ UI_popup_menu_end(C, pup);
+
+ return OPERATOR_INTERFACE;
+}
+
+void OBJECT_OT_hide_collection(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Hide Objects By 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);
+}
/* ******************* toggle editmode operator ***************** */
-static bool mesh_needs_keyindex(const Mesh *me)
+static bool mesh_needs_keyindex(Main *bmain, const Mesh *me)
{
if (me->key) {
return false; /* will be added */
}
- for (const Object *ob = G.main->object.first; ob; ob = ob->id.next) {
+ for (const Object *ob = bmain->object.first; ob; ob = ob->id.next) {
if ((ob->parent) && (ob->parent->data == me) && ELEM(ob->partype, PARVERT1, PARVERT3)) {
return true;
}
@@ -189,7 +423,7 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f
return false;
}
- EDBM_mesh_load(obedit);
+ EDBM_mesh_load(bmain, obedit);
if (freedata) {
EDBM_mesh_free(me->edit_btmesh);
@@ -207,7 +441,7 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f
if (arm->edbo == NULL) {
return false;
}
- ED_armature_from_edit(obedit->data);
+ ED_armature_from_edit(bmain, obedit->data);
if (freedata) {
ED_armature_edit_free(obedit->data);
}
@@ -222,7 +456,7 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f
if (cu->editnurb == NULL) {
return false;
}
- ED_curve_editnurb_load(obedit);
+ ED_curve_editnurb_load(bmain, obedit);
if (freedata) {
ED_curve_editnurb_free(obedit);
}
@@ -261,33 +495,29 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f
return true;
}
-bool ED_object_editmode_load(Object *obedit)
+bool ED_object_editmode_load(Main *bmain, Object *obedit)
{
- /* TODO(sergey): use proper main here? */
- return ED_object_editmode_load_ex(G.main, obedit, false);
+ return ED_object_editmode_load_ex(bmain, obedit, false);
}
/**
- * \param C: Can be NULL, only if #EM_DO_UNDO isn't set.
* \param flag:
- * - Only in exceptional cases should #EM_DO_UNDO NOT be in the flag.
* - If #EM_FREEDATA isn't in the flag, use ED_object_editmode_load directly.
*/
-void ED_object_editmode_exit_ex(bContext *C, Scene *scene, Object *obedit, int flag)
+bool ED_object_editmode_exit_ex(Main *bmain, Scene *scene, Object *obedit, int flag)
{
- BLI_assert(C || !(flag & EM_DO_UNDO));
const bool freedata = (flag & EM_FREEDATA) != 0;
if (flag & EM_WAITCURSOR) waitcursor(1);
- if (ED_object_editmode_load_ex(G.main, obedit, freedata) == false) {
+ 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;
}
if (flag & EM_WAITCURSOR) waitcursor(0);
- return;
+ return true;
}
/* freedata only 0 now on file saves and render */
@@ -302,50 +532,46 @@ void ED_object_editmode_exit_ex(bContext *C, Scene *scene, Object *obedit, int f
pid->cache->flag |= PTCACHE_OUTDATED;
}
BLI_freelistN(&pidlist);
-
+
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, OB_RECALC_OB | OB_RECALC_DATA);
-
- if (flag & EM_DO_UNDO)
- ED_undo_push(C, "Editmode");
-
- if (C != NULL) {
- WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene);
- }
- else {
- WM_main_add_notifier(NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene);
- }
+ WM_main_add_notifier(NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene);
obedit->mode &= ~OB_MODE_EDIT;
}
if (flag & EM_WAITCURSOR) waitcursor(0);
+
+ return (obedit->mode & OB_MODE_EDIT) == 0;
}
-void ED_object_editmode_exit(bContext *C, int flag)
+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);
- ED_object_editmode_exit_ex(C, scene, obedit, flag);
+ return ED_object_editmode_exit_ex(bmain, scene, obedit, flag);
}
-void ED_object_editmode_enter_ex(Scene *scene, Object *ob, int flag)
+bool ED_object_editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag)
{
bool ok = false;
- if (ELEM(NULL, ob, ob->data)) return;
- if (ID_IS_LINKED(ob)) return;
+ 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;
-
+ if (BKE_object_is_in_editmode(ob)) {
+ return true;
+ }
+
if (BKE_object_obdata_is_libdata(ob)) {
error_libdata();
- return;
+ return false;
}
if (flag & EM_WAITCURSOR) waitcursor(1);
@@ -357,7 +583,8 @@ void ED_object_editmode_enter_ex(Scene *scene, Object *ob, int flag)
if (ob->type == OB_MESH) {
BMEditMesh *em;
ok = 1;
- const bool use_key_index = mesh_needs_keyindex(ob->data);
+
+ const bool use_key_index = mesh_needs_keyindex(bmain, ob->data);
EDBM_mesh_make(ob, scene->toolsettings->selectmode, use_key_index);
@@ -371,22 +598,8 @@ void ED_object_editmode_enter_ex(Scene *scene, Object *ob, int flag)
WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_MESH, NULL);
}
else if (ob->type == OB_ARMATURE) {
- bArmature *arm = ob->data;
- if (!arm) return;
- /*
- * The function BKE_object_obdata_is_libdata make a problem here, the
- * check for ob->proxy return 0 and let blender enter to edit mode
- * this causes a crash when you try leave the edit mode.
- * The problem is that i can't remove the ob->proxy check from
- * BKE_object_obdata_is_libdata that prevent the bugfix #6614, so
- * i add this little hack here.
- */
- if (ID_IS_LINKED(arm)) {
- error_libdata();
- return;
- }
ok = 1;
- ED_armature_to_edit(arm);
+ ED_armature_to_edit(ob->data);
/* to ensure all goes in restposition and without striding */
DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); /* XXX: should this be OB_RECALC_DATA? */
@@ -428,11 +641,13 @@ void ED_object_editmode_enter_ex(Scene *scene, Object *ob, int flag)
}
if (flag & EM_WAITCURSOR) waitcursor(0);
- BLI_assert((flag & EM_DO_UNDO) == 0);
+
+ return (ob->mode & OB_MODE_EDIT) != 0;
}
-void ED_object_editmode_enter(bContext *C, int flag)
+bool ED_object_editmode_enter(bContext *C, int flag)
{
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob;
@@ -443,11 +658,10 @@ void ED_object_editmode_enter(bContext *C, int flag)
else {
ob = view_layer->basact->object;
}
- if (ob == NULL) return;
- if (ID_IS_LINKED(ob)) return;
-
- ED_object_editmode_enter_ex(scene, ob, flag & ~EM_DO_UNDO);
- if (flag & EM_DO_UNDO) ED_undo_push(C, "Enter Editmode");
+ 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)
@@ -455,6 +669,7 @@ 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);
Object *obact = OBACT(view_layer);
@@ -471,29 +686,31 @@ static int editmode_toggle_exec(bContext *C, wmOperator *op)
FOREACH_SELECTED_OBJECT_BEGIN(view_layer, ob)
{
if ((ob != obact) && (ob->type == obact->type)) {
- ED_object_editmode_enter_ex(scene, ob, EM_WAITCURSOR | EM_NO_CONTEXT);
+ ED_object_editmode_enter_ex(bmain, scene, ob, EM_WAITCURSOR | EM_NO_CONTEXT);
}
}
FOREACH_SELECTED_OBJECT_END;
}
}
else {
- ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR); /* had EM_DO_UNDO but op flag calls undo too [#24685] */
+ ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR);
if ((obact->mode & mode_flag) == 0) {
- FOREACH_SELECTED_OBJECT_BEGIN(view_layer, ob)
+ FOREACH_OBJECT_BEGIN(view_layer, ob)
{
if ((ob != obact) && (ob->type == obact->type)) {
- ED_object_editmode_exit_ex(NULL, scene, ob, EM_FREEDATA | EM_WAITCURSOR);
+ ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA | EM_WAITCURSOR);
}
}
- FOREACH_SELECTED_OBJECT_END;
+ FOREACH_OBJECT_END;
}
}
-
- ED_space_image_uv_sculpt_update(CTX_wm_manager(C), scene);
+
+ ED_space_image_uv_sculpt_update(bmain, CTX_wm_manager(C), scene);
WM_msg_publish_rna_prop(mbus, &obact->id, obact, Object, mode);
+ WM_toolsystem_update_from_context_view3d(C);
+
return OPERATOR_FINISHED;
}
@@ -515,16 +732,16 @@ static int editmode_toggle_poll(bContext *C)
void OBJECT_OT_editmode_toggle(wmOperatorType *ot)
{
-
+
/* 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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -538,7 +755,7 @@ static int posemode_exec(bContext *C, wmOperator *op)
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;
@@ -550,7 +767,7 @@ static int posemode_exec(bContext *C, wmOperator *op)
}
if (obact == CTX_data_edit_object(C)) {
- ED_object_editmode_exit(C, EM_FREEDATA | EM_DO_UNDO);
+ ED_object_editmode_exit(C, EM_FREEDATA);
is_mode_set = false;
}
@@ -559,7 +776,7 @@ static int posemode_exec(bContext *C, wmOperator *op)
if (ok) {
struct Main *bmain = CTX_data_main(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- FOREACH_SELECTED_OBJECT_BEGIN(view_layer, ob)
+ FOREACH_OBJECT_BEGIN(view_layer, ob)
{
if ((ob != obact) &&
(ob->type == OB_ARMATURE) &&
@@ -568,7 +785,7 @@ static int posemode_exec(bContext *C, wmOperator *op)
ED_object_posemode_exit_ex(bmain, ob);
}
}
- FOREACH_SELECTED_OBJECT_END;
+ FOREACH_OBJECT_END;
}
}
else {
@@ -592,20 +809,22 @@ static int posemode_exec(bContext *C, wmOperator *op)
WM_msg_publish_rna_prop(mbus, &obact->id, obact, Object, mode);
+ WM_toolsystem_update_from_context_view3d(C);
+
return OPERATOR_FINISHED;
}
-void OBJECT_OT_posemode_toggle(wmOperatorType *ot)
+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";
-
+
/* api callbacks */
ot->exec = posemode_exec;
ot->poll = ED_operator_object_active_editable;
-
+
/* flag */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -615,7 +834,7 @@ static void copy_texture_space(Object *to, Object *ob)
{
float *poin1 = NULL, *poin2 = NULL;
short texflag = 0;
-
+
if (ob->type == OB_MESH) {
texflag = ((Mesh *)ob->data)->texflag;
poin2 = ((Mesh *)ob->data)->loc;
@@ -630,7 +849,7 @@ static void copy_texture_space(Object *to, Object *ob)
}
else
return;
-
+
if (to->type == OB_MESH) {
((Mesh *)to->data)->texflag = texflag;
poin1 = ((Mesh *)to->data)->loc;
@@ -645,9 +864,9 @@ static void copy_texture_space(Object *to, Object *ob)
}
else
return;
-
+
memcpy(poin1, poin2, 9 * sizeof(float)); /* this was noted in DNA_mesh, curve, mball */
-
+
if (to->type == OB_MESH) {
/* pass */
}
@@ -657,7 +876,7 @@ static void copy_texture_space(Object *to, Object *ob)
else {
BKE_curve_texspace_calc(to->data);
}
-
+
}
/* UNUSED, keep in case we want to copy functionality for use elsewhere */
@@ -667,12 +886,11 @@ static void copy_attr(Main *bmain, Scene *scene, ViewLayer *view_layer, short ev
Base *base;
Curve *cu, *cu1;
Nurb *nu;
- bool do_depgraph_update = false;
-
+
if (ID_IS_LINKED(scene)) return;
if (!(ob = OBACT(view_layer))) return;
-
+
if (BKE_object_is_in_editmode(ob)) {
/* obedit_copymenu(); */
return;
@@ -688,7 +906,7 @@ static void copy_attr(Main *bmain, Scene *scene, ViewLayer *view_layer, short ev
if (base != BASACT(view_layer)) {
if (TESTBASELIB(base)) {
DEG_id_tag_update(&base->object->id, OB_RECALC_DATA);
-
+
if (event == 1) { /* loc */
copy_v3_v3(base->object->loc, ob->loc);
copy_v3_v3(base->object->dloc, ob->dloc);
@@ -718,7 +936,7 @@ static void copy_attr(Main *bmain, Scene *scene, ViewLayer *view_layer, short ev
base->object->dupoff = ob->dupoff;
base->object->dupsta = ob->dupsta;
base->object->dupend = ob->dupend;
-
+
base->object->transflag &= ~OB_DUPLI;
base->object->transflag |= (ob->transflag & OB_DUPLI);
@@ -730,7 +948,7 @@ static void copy_attr(Main *bmain, Scene *scene, ViewLayer *view_layer, short ev
copy_texture_space(base->object, ob);
}
else if (event == 18) { /* font settings */
-
+
if (base->object->type == ob->type) {
cu = ob->data;
cu1 = base->object->data;
@@ -763,25 +981,25 @@ static void copy_attr(Main *bmain, Scene *scene, ViewLayer *view_layer, short ev
id_us_min(&cu1->vfontbi->id);
cu1->vfontbi = cu->vfontbi;
id_us_plus((ID *)cu1->vfontbi);
-
+
BLI_strncpy(cu1->family, cu->family, sizeof(cu1->family));
-
+
DEG_id_tag_update(&base->object->id, OB_RECALC_DATA);
}
}
else if (event == 19) { /* bevel settings */
-
+
if (ELEM(base->object->type, OB_CURVE, OB_FONT)) {
cu = ob->data;
cu1 = base->object->data;
-
+
cu1->bevobj = cu->bevobj;
cu1->taperobj = cu->taperobj;
cu1->width = cu->width;
cu1->bevresol = cu->bevresol;
cu1->ext1 = cu->ext1;
cu1->ext2 = cu->ext2;
-
+
DEG_id_tag_update(&base->object->id, OB_RECALC_DATA);
}
}
@@ -790,17 +1008,17 @@ static void copy_attr(Main *bmain, Scene *scene, ViewLayer *view_layer, short ev
if (ELEM(base->object->type, OB_CURVE, OB_FONT)) {
cu = ob->data;
cu1 = base->object->data;
-
+
cu1->resolu = cu->resolu;
cu1->resolu_ren = cu->resolu_ren;
-
+
nu = cu1->nurb.first;
-
+
while (nu) {
nu->resolu = cu1->resolu;
nu = nu->next;
}
-
+
DEG_id_tag_update(&base->object->id, OB_RECALC_DATA);
}
}
@@ -824,18 +1042,21 @@ static void copy_attr(Main *bmain, Scene *scene, ViewLayer *view_layer, short ev
else if (event == 22) {
/* Copy the constraint channels over */
BKE_constraints_copy(&base->object->constraints, &ob->constraints, true);
-
- do_depgraph_update = true;
+ DEG_id_tag_update(&base->object->id, DEG_TAG_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
}
else if (event == 23) {
base->object->softflag = ob->softflag;
if (base->object->soft) sbFree(base->object->soft);
-
+
base->object->soft = copy_softbody(ob->soft, 0);
if (!modifiers_findByType(base->object, eModifierType_Softbody)) {
BLI_addhead(&base->object->modifiers, modifier_new(eModifierType_Softbody));
}
+
+ DEG_id_tag_update(&base->object->id, DEG_TAG_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
}
else if (event == 26) {
#if 0 // XXX old animation system
@@ -857,7 +1078,7 @@ static void copy_attr(Main *bmain, Scene *scene, ViewLayer *view_layer, short ev
if (ELEM(base->object->type, OB_CURVE, OB_SURF)) {
cu = ob->data;
cu1 = base->object->data;
-
+
if (cu->flag & CU_UV_ORCO)
cu1->flag |= CU_UV_ORCO;
else
@@ -876,9 +1097,6 @@ static void copy_attr(Main *bmain, Scene *scene, ViewLayer *view_layer, short ev
}
}
}
-
- if (do_depgraph_update)
- DEG_relations_tag_update(bmain);
}
static void UNUSED_FUNCTION(copy_attr_menu) (Main *bmain, Scene *scene, ViewLayer *view_layer, Object *obedit)
@@ -886,36 +1104,36 @@ static void UNUSED_FUNCTION(copy_attr_menu) (Main *bmain, Scene *scene, ViewLaye
Object *ob;
short event;
char str[512];
-
+
if (!(ob = OBACT(view_layer))) return;
-
+
if (obedit) {
/* if (ob->type == OB_MESH) */
/* XXX mesh_copy_menu(); */
return;
}
-
+
/* Object Mode */
-
+
/* If you change this menu, don't forget to update the menu in header_view3d.c
* view3d_edit_object_copyattrmenu() and in toolbox.c
*/
-
+
strcpy(str,
"Copy Attributes %t|Location %x1|Rotation %x2|Size %x3|Draw Options %x4|"
"Time Offset %x5|Dupli %x6|Object Color %x31|%l|Mass %x7|Damping %x8|All Physical Attributes %x11|Properties %x9|"
"Logic Bricks %x10|Protected Transform %x29|%l");
-
+
strcat(str, "|Object Constraints %x22");
strcat(str, "|NLA Strips %x26");
-
+
/* XXX if (OB_TYPE_SUPPORT_MATERIAL(ob->type)) { */
/* strcat(str, "|Texture Space %x17"); */
/* } */
-
+
if (ob->type == OB_FONT) strcat(str, "|Font Settings %x18|Bevel Settings %x19");
if (ob->type == OB_CURVE) strcat(str, "|Bevel Settings %x19|UV Orco %x28");
-
+
if ((ob->type == OB_FONT) || (ob->type == OB_CURVE)) {
strcat(str, "|Curve Resolution %x25");
}
@@ -925,16 +1143,16 @@ static void UNUSED_FUNCTION(copy_attr_menu) (Main *bmain, Scene *scene, ViewLaye
}
if (ob->soft) strcat(str, "|Soft Body Settings %x23");
-
+
strcat(str, "|Pass Index %x30");
-
+
if (ob->type == OB_MESH || ob->type == OB_CURVE || ob->type == OB_LATTICE || ob->type == OB_SURF) {
strcat(str, "|Modifiers ... %x24");
}
event = pupmenu(str);
if (event <= 0) return;
-
+
copy_attr(bmain, scene, view_layer, event);
}
@@ -980,16 +1198,16 @@ static int forcefield_toggle_exec(bContext *C, wmOperator *UNUSED(op))
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";
-
+
/* api callbacks */
ot->exec = forcefield_toggle_exec;
ot->poll = ED_operator_object_active_editable;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1000,14 +1218,14 @@ void OBJECT_OT_forcefield_toggle(wmOperatorType *ot)
/* For the objects with animation: update paths for those that have got them
* This should selectively update paths that exist...
*
- * To be called from various tools that do incremental updates
+ * To be called from various tools that do incremental updates
*/
void ED_objects_recalculate_paths(bContext *C, Scene *scene)
{
struct 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)
{
@@ -1016,10 +1234,19 @@ void ED_objects_recalculate_paths(bContext *C, Scene *scene)
animviz_get_object_motionpaths(ob, &targets);
}
CTX_DATA_END;
-
+
/* recalculate paths, then free */
animviz_calc_motionpaths(depsgraph, bmain, scene, &targets);
BLI_freelistN(&targets);
+
+ /* tag objects for copy on write - so paths will draw/redraw */
+ CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects)
+ {
+ if (ob->mpath) {
+ DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
+ }
+ }
+ CTX_DATA_END;
}
@@ -1027,18 +1254,18 @@ void ED_objects_recalculate_paths(bContext *C, Scene *scene)
static int object_calculate_paths_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Object *ob = CTX_data_active_object(C);
-
+
if (ob == NULL)
return OPERATOR_CANCELLED;
-
+
/* 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);
}
-
+
/* show popup dialog to allow editing of range... */
/* FIXME: hardcoded dimensions here are just arbitrary */
return WM_operator_props_dialog_popup(C, op, 10 * UI_UNIT_X, 10 * UI_UNIT_Y);
@@ -1050,28 +1277,28 @@ 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");
-
+
/* 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;
-
+
/* 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);
-
+
/* 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)
@@ -1080,19 +1307,19 @@ void OBJECT_OT_paths_calculate(wmOperatorType *ot)
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",
+ 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",
+ RNA_def_int(ot->srna, "end_frame", 250, MINAFRAME, MAXFRAME, "End",
"Last frame to calculate object paths on", MINFRAME, MAXFRAME / 2.0);
}
@@ -1104,23 +1331,23 @@ static int object_update_paths_poll(bContext *C)
Object *ob = ED_object_active_context(C);
return (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
}
-
+
return false;
}
static int object_update_paths_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
-
+
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);
-
+
/* notifiers for updates */
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -1130,11 +1357,11 @@ void OBJECT_OT_paths_update(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1176,14 +1403,14 @@ void ED_objects_clear_paths(bContext *C, bool only_selected)
static int object_clear_paths_exec(bContext *C, wmOperator *op)
{
bool only_selected = RNA_boolean_get(op->ptr, "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);
-
- return OPERATOR_FINISHED;
+
+ return OPERATOR_FINISHED;
}
/* operator callback/wrapper */
@@ -1201,15 +1428,15 @@ void OBJECT_OT_paths_clear(wmOperatorType *ot)
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");
@@ -1278,7 +1505,7 @@ void OBJECT_OT_shade_flat(wmOperatorType *ot)
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;
@@ -1293,11 +1520,11 @@ void OBJECT_OT_shade_smooth(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1338,7 +1565,7 @@ static const EnumPropertyItem *object_mode_set_itemsf(
/* We need at least this one! */
RNA_enum_items_add_value(&item, &totitem, input, OB_MODE_OBJECT);
}
-
+
/* On top of all the rest, GPencil Stroke Edit Mode
* is available if there's a valid gp datablock...
*/
@@ -1369,12 +1596,28 @@ static int object_mode_set_poll(bContext *C)
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);
bGPdata *gpd = CTX_data_gpencil_data(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;
+ }
+ }
+ }
+ }
+
if (gpd) {
/* GP Mode is not bound to a specific object. Therefore,
* we don't want it to be actually saved on any objects,
@@ -1392,7 +1635,7 @@ static int object_mode_set_exec(bContext *C, wmOperator *op)
WM_operator_name_call(C, "GPENCIL_OT_editmode_toggle", WM_OP_EXEC_REGION_WIN, NULL);
}
}
-
+
if (!ob || !ED_object_mode_compat_test(ob, mode))
return OPERATOR_PASS_THROUGH;
@@ -1427,20 +1670,45 @@ static int object_mode_set_exec(bContext *C, wmOperator *op)
void OBJECT_OT_mode_set(wmOperatorType *ot)
{
PropertyRNA *prop;
-
+
/* 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;
-
+
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 */
-
+
+ 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);
+}
+
+void OBJECT_OT_mode_set_or_submode(wmOperatorType *ot)
+{
+ 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";
+
+ /* api callbacks */
+ ot->exec = object_mode_set_exec;
+
+ 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 */
+
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);
@@ -1511,15 +1779,25 @@ bool ED_object_editmode_calc_active_center(Object *obedit, const bool select_onl
return false;
}
-#define COLLECTION_INVALID_INDEX -1
+static int move_to_collection_poll(bContext *C)
+{
+ if (CTX_wm_space_outliner(C) != NULL) {
+ return ED_outliner_collections_editor_poll(C);
+ }
+ else {
+ 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_add = RNA_boolean_get(op->ptr, "is_add");
+ const bool is_link = STREQ(op->idname, "OBJECT_OT_link_to_collection");
const bool is_new = RNA_boolean_get(op->ptr, "is_new");
- SceneCollection *scene_collection;
+ Collection *collection;
+ ListBase objects = {NULL};
if (!RNA_property_is_set(op->ptr, prop)) {
BKE_report(op->reports, RPT_ERROR, "No collection selected");
@@ -1527,59 +1805,62 @@ static int move_to_collection_exec(bContext *C, wmOperator *op)
}
int collection_index = RNA_property_int_get(op->ptr, prop);
- scene_collection = BKE_collection_from_index(CTX_data_scene(C), collection_index);
- if (scene_collection == NULL) {
+ 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;
}
- Object *single_object = NULL;
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- if (single_object != NULL) {
- single_object = NULL;
- break;
- }
- else {
- single_object = ob;
+ 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;
}
- CTX_DATA_END;
if (is_new) {
char new_collection_name[MAX_NAME];
RNA_string_get(op->ptr, "new_collection_name", new_collection_name);
- scene_collection = BKE_collection_add(&scene->id, scene_collection, COLLECTION_TYPE_NONE, 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_add &&
- BLI_findptr(&scene_collection->objects, single_object, offsetof(LinkData, data)))
+ 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, scene_collection->name);
+ 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;
}
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- if (!is_add) {
- BKE_collection_object_move(&scene->id, scene_collection, NULL, ob);
+ 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(&scene->id, scene_collection, ob);
+ BKE_collection_object_add(bmain, collection, ob);
}
}
- CTX_DATA_END;
+ BLI_freelistN(&objects);
BKE_reportf(op->reports,
RPT_INFO,
"%s %s to %s",
(single_object != NULL) ? single_object->id.name + 2 : "Objects",
- is_add ? "added" : "moved",
- scene_collection->name);
+ is_link ? "linked" : "moved",
+ collection->id.name + 2);
- DEG_relations_tag_update(CTX_data_main(C));
- DEG_id_tag_update(&scene->id, 0);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
@@ -1588,26 +1869,27 @@ static int move_to_collection_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-typedef struct MoveToCollectionData {
+struct MoveToCollectionData {
struct MoveToCollectionData *next, *prev;
int index;
- struct SceneCollection *collection;
+ struct Collection *collection;
struct ListBase submenus;
PointerRNA ptr;
struct wmOperatorType *ot;
-} MoveToCollectionData;
+};
static int move_to_collection_menus_create(wmOperator *op, MoveToCollectionData *menu)
{
int index = menu->index;
- for (SceneCollection *scene_collection = menu->collection->scene_collections.first;
- scene_collection != NULL;
- scene_collection = scene_collection->next)
+ 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 = scene_collection;
+ submenu->collection = collection;
submenu->index = ++index;
index = move_to_collection_menus_create(op, submenu);
submenu->ot = op->type;
@@ -1640,11 +1922,19 @@ static void move_to_collection_menus_free(MoveToCollectionData **menu)
static void move_to_collection_menu_create(bContext *UNUSED(C), uiLayout *layout, void *menu_v)
{
MoveToCollectionData *menu = menu_v;
+ const char *name;
+
+ if (menu->collection->flag & COLLECTION_IS_MASTER) {
+ name = IFACE_("Scene Collection");
+ }
+ else {
+ name = menu->collection->id.name + 2;
+ }
uiItemIntO(layout,
- menu->collection->name,
+ name,
ICON_NONE,
- "OBJECT_OT_move_to_collection",
+ menu->ot->idname,
"collection_index",
menu->index);
uiItemS(layout);
@@ -1667,7 +1957,6 @@ static void move_to_collection_menu_create(bContext *UNUSED(C), uiLayout *layout
"New Collection",
ICON_ZOOMIN,
menu->ptr.data,
- /* We use invoke here so we can read ctrl from event. */
WM_OP_INVOKE_DEFAULT,
0,
NULL);
@@ -1677,15 +1966,15 @@ static void move_to_collection_menus_items(uiLayout *layout, MoveToCollectionDat
{
if (BLI_listbase_is_empty(&menu->submenus)) {
uiItemIntO(layout,
- menu->collection->name,
+ menu->collection->id.name + 2,
ICON_NONE,
- "OBJECT_OT_move_to_collection",
+ menu->ot->idname,
"collection_index",
menu->index);
}
else {
uiItemMenuF(layout,
- menu->collection->name,
+ menu->collection->id.name + 2,
ICON_NONE,
move_to_collection_menu_create,
menu);
@@ -1695,8 +1984,10 @@ static void move_to_collection_menus_items(uiLayout *layout, MoveToCollectionDat
/* This is allocated statically because we need this available for the menus creation callback. */
static MoveToCollectionData *master_collection_menu = NULL;
-static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
+ 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);
@@ -1704,16 +1995,15 @@ static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent
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);
- RNA_boolean_set(op->ptr, "is_add", event->ctrl);
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];
- SceneCollection *scene_collection;
+ Collection *collection;
- scene_collection = BKE_collection_from_index(CTX_data_scene(C), collection_index);
- BKE_collection_new_name_get(&CTX_data_scene(C)->id, scene_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, 10 * UI_UNIT_X, 5 * UI_UNIT_Y);
@@ -1722,7 +2012,7 @@ static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent
return move_to_collection_exec(C, op);
}
- SceneCollection *master_collection = BKE_collection_master(&CTX_data_scene(C)->id);
+ 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
@@ -1742,10 +2032,10 @@ static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent
uiLayout *layout;
/* Build the menus. */
- pup = UI_popup_menu_begin(C, IFACE_("Move to Collection"), ICON_NONE);
+ 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);
- /* We use invoke here so we can read ctrl from event. */
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
move_to_collection_menu_create(C, layout, master_collection_menu);
@@ -1761,13 +2051,13 @@ void OBJECT_OT_move_to_collection(wmOperatorType *ot)
/* identifiers */
ot->name = "Move to Collection";
- ot->description = "Move to a collection only (Ctrl to add)";
+ 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 = ED_operator_object_active_editable;
+ ot->poll = move_to_collection_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1775,8 +2065,6 @@ void OBJECT_OT_move_to_collection(wmOperatorType *ot)
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_add", false, "Add", "Keep object in original collections as well");
- 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",
@@ -1784,4 +2072,29 @@ void OBJECT_OT_move_to_collection(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-#undef COLLECTION_INVALID_INDEX
+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);
+}
diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c
index cb0fbdda970..53cabe3759e 100644
--- a/source/blender/editors/object/object_group.c
+++ b/source/blender/editors/object/object_group.c
@@ -39,14 +39,15 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_group.h"
#include "BKE_library.h"
#include "BKE_library_remap.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_object.h"
+#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "ED_screen.h"
@@ -64,8 +65,9 @@
/********************* 3d view operators ***********************/
/* can be called with C == NULL */
-static const EnumPropertyItem *group_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);
Object *ob;
EnumPropertyItem *item = NULL, item_tmp = {0};
int totitem = 0;
@@ -78,25 +80,25 @@ static const EnumPropertyItem *group_object_active_itemf(bContext *C, PointerRNA
/* check that the object exists */
if (ob) {
- Group *group;
+ Collection *collection;
int i = 0, count = 0;
- /* if 2 or more groups, add option to add to all groups */
- group = NULL;
- while ((group = BKE_group_object_find(group, ob)))
+ /* if 2 or more collections, add option to add to all collections */
+ collection = NULL;
+ while ((collection = BKE_collection_object_find(bmain, collection, ob)))
count++;
if (count >= 2) {
- item_tmp.identifier = item_tmp.name = "All Groups";
+ 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 groups */
- group = NULL;
- while ((group = BKE_group_object_find(group, ob))) {
- item_tmp.identifier = item_tmp.name = group->id.name + 2;
+ /* add collections */
+ collection = NULL;
+ while ((collection = BKE_collection_object_find(bmain, 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);
@@ -110,48 +112,49 @@ static const EnumPropertyItem *group_object_active_itemf(bContext *C, PointerRNA
return item;
}
-/* get the group back from the enum index, quite awkward and UI specific */
-static Group *group_object_active_find_index(Object *ob, const int group_object_index)
+/* get the collection back from the enum index, quite awkward and UI specific */
+static Collection *collection_object_active_find_index(Main *bmain, Object *ob, const int collection_object_index)
{
- Group *group = NULL;
+ Collection *collection = NULL;
int i = 0;
- while ((group = BKE_group_object_find(group, ob))) {
- if (i == group_object_index) {
+ while ((collection = BKE_collection_object_find(bmain, collection, ob))) {
+ if (i == collection_object_index) {
break;
}
i++;
}
- return group;
+ return collection;
}
static int objects_add_active_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
Main *bmain = CTX_data_main(C);
- int single_group_index = RNA_enum_get(op->ptr, "group");
- Group *single_group = group_object_active_find_index(ob, single_group_index);
- Group *group;
+ int single_collection_index = RNA_enum_get(op->ptr, "collection");
+ Collection *single_collection = collection_object_active_find_index(bmain, ob, single_collection_index);
+ Collection *collection;
bool is_cycle = false;
bool updated = false;
if (ob == NULL)
return OPERATOR_CANCELLED;
- /* now add all selected objects to the group(s) */
- for (group = bmain->group.first; group; group = group->id.next) {
- if (single_group && group != single_group)
+ /* now add all selected objects to the collection(s) */
+ for (collection = bmain->collection.first; collection; collection = collection->id.next) {
+ if (single_collection && collection != single_collection)
continue;
- if (!BKE_group_object_exists(group, ob))
+ if (!BKE_collection_has_object(collection, ob))
continue;
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
- if (BKE_group_object_exists(group, base->object))
+ if (BKE_collection_has_object(collection, base->object))
continue;
- if (!BKE_group_object_cyclic_check(bmain, base->object, group)) {
- BKE_group_object_add(group, base->object);
+ if (!BKE_collection_object_cyclic_check(bmain, base->object, collection)) {
+ BKE_collection_object_add(bmain, collection, base->object);
+ DEG_id_tag_update(&collection->id, DEG_TAG_COPY_ON_WRITE);
updated = true;
}
else {
@@ -162,7 +165,7 @@ static int objects_add_active_exec(bContext *C, wmOperator *op)
}
if (is_cycle)
- BKE_report(op->reports, RPT_WARNING, "Skipped some groups because of cycle detected");
+ BKE_report(op->reports, RPT_WARNING, "Skipped some collections because of cycle detected");
if (!updated)
return OPERATOR_CANCELLED;
@@ -173,15 +176,15 @@ static int objects_add_active_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void GROUP_OT_objects_add_active(wmOperatorType *ot)
+void COLLECTION_OT_objects_add_active(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
- ot->name = "Add Selected To Active Group";
- ot->description = "Add the object to an object group that contains the active object";
- ot->idname = "GROUP_OT_objects_add_active";
-
+ 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;
@@ -191,8 +194,8 @@ void GROUP_OT_objects_add_active(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "The group to add other selected objects to");
- RNA_def_enum_funcs(prop, group_object_active_itemf);
+ 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;
}
@@ -202,118 +205,120 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = OBACT(view_layer);
- int single_group_index = RNA_enum_get(op->ptr, "group");
- Group *single_group = group_object_active_find_index(ob, single_group_index);
- Group *group;
+ int single_collection_index = RNA_enum_get(op->ptr, "collection");
+ Collection *single_collection = collection_object_active_find_index(bmain, ob, single_collection_index);
+ Collection *collection;
bool ok = false;
-
+
if (ob == NULL)
return OPERATOR_CANCELLED;
-
- /* linking to same group requires its own loop so we can avoid
- * looking up the active objects groups each time */
- for (group = bmain->group.first; group; group = group->id.next) {
- if (single_group && group != single_group)
+ /* linking to same collection requires its own loop so we can avoid
+ * looking up the active objects collections each time */
+
+ for (collection = bmain->collection.first; collection; collection = collection->id.next) {
+ if (single_collection && collection != single_collection)
continue;
- if (BKE_group_object_exists(group, ob)) {
- /* Remove groups from selected objects */
+ if (BKE_collection_has_object(collection, ob)) {
+ /* Remove collections from selected objects */
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
- BKE_group_object_unlink(group, base->object);
+ BKE_collection_object_remove(bmain, collection, base->object, false);
+ DEG_id_tag_update(&collection->id, DEG_TAG_COPY_ON_WRITE);
ok = 1;
}
CTX_DATA_END;
}
}
-
+
if (!ok)
- BKE_report(op->reports, RPT_ERROR, "Active object contains no groups");
-
+ 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 GROUP_OT_objects_remove_active(wmOperatorType *ot)
+void COLLECTION_OT_objects_remove_active(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
- ot->name = "Remove Selected From Active Group";
- ot->description = "Remove the object from an object group that contains the active object";
- ot->idname = "GROUP_OT_objects_remove_active";
-
+ 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, "group", DummyRNA_NULL_items, 0, "Group", "The group to remove other selected objects from");
- RNA_def_enum_funcs(prop, group_object_active_itemf);
+ 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 group_objects_remove_all_exec(bContext *C, wmOperator *UNUSED(op))
+static int collection_objects_remove_all_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
- BKE_object_groups_clear(base->object);
+ BKE_object_groups_clear(bmain, base->object);
}
CTX_DATA_END;
DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
-void GROUP_OT_objects_remove_all(wmOperatorType *ot)
+void COLLECTION_OT_objects_remove_all(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Remove From All Groups";
- ot->description = "Remove selected objects from all groups";
- ot->idname = "GROUP_OT_objects_remove_all";
-
+ 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 = group_objects_remove_all_exec;
+ ot->exec = collection_objects_remove_all_exec;
ot->poll = ED_operator_objectmode;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int group_objects_remove_exec(bContext *C, wmOperator *op)
+static int collection_objects_remove_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
Main *bmain = CTX_data_main(C);
- int single_group_index = RNA_enum_get(op->ptr, "group");
- Group *single_group = group_object_active_find_index(ob, single_group_index);
- Group *group;
+ int single_collection_index = RNA_enum_get(op->ptr, "collection");
+ Collection *single_collection = collection_object_active_find_index(bmain, ob, single_collection_index);
+ Collection *collection;
bool updated = false;
if (ob == NULL)
return OPERATOR_CANCELLED;
- for (group = bmain->group.first; group; group = group->id.next) {
- if (single_group && group != single_group)
+ for (collection = bmain->collection.first; collection; collection = collection->id.next) {
+ if (single_collection && collection != single_collection)
continue;
- if (!BKE_group_object_exists(group, ob))
+ if (!BKE_collection_has_object(collection, ob))
continue;
- /* now remove all selected objects from the group */
+ /* now remove all selected objects from the collection */
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
- BKE_group_object_unlink(group, base->object);
+ BKE_collection_object_remove(bmain, collection, base->object, false);
+ DEG_id_tag_update(&collection->id, DEG_TAG_COPY_ON_WRITE);
updated = true;
}
CTX_DATA_END;
@@ -328,17 +333,17 @@ static int group_objects_remove_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void GROUP_OT_objects_remove(wmOperatorType *ot)
+void COLLECTION_OT_objects_remove(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
- ot->name = "Remove From Group";
- ot->description = "Remove selected objects from a group";
- ot->idname = "GROUP_OT_objects_remove";
+ ot->name = "Remove From Collection";
+ ot->description = "Remove selected objects from a collection";
+ ot->idname = "COLLECTION_OT_objects_remove";
/* api callbacks */
- ot->exec = group_objects_remove_exec;
+ ot->exec = collection_objects_remove_exec;
ot->invoke = WM_menu_invoke;
ot->poll = ED_operator_objectmode;
@@ -346,130 +351,131 @@ void GROUP_OT_objects_remove(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "The group to remove this object from");
- RNA_def_enum_funcs(prop, group_object_active_itemf);
+ 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 group_create_exec(bContext *C, wmOperator *op)
+static int collection_create_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Group *group = NULL;
char name[MAX_ID_NAME - 2]; /* id name */
-
+
RNA_string_get(op->ptr, "name", name);
-
- group = BKE_group_add(bmain, name);
-
+
+ Collection *collection = BKE_collection_add(bmain, NULL, name);
+ id_fake_user_set(&collection->id);
+
CTX_DATA_BEGIN (C, Base *, base, selected_bases)
{
- BKE_group_object_add(group, base->object);
+ BKE_collection_object_add(bmain, collection, base->object);
+ DEG_id_tag_update(&collection->id, DEG_TAG_COPY_ON_WRITE);
}
CTX_DATA_END;
DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
-void GROUP_OT_create(wmOperatorType *ot)
+void COLLECTION_OT_create(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Create New Group";
- ot->description = "Create an object group from selected objects";
- ot->idname = "GROUP_OT_create";
-
+ ot->name = "Create New Collection";
+ ot->description = "Create an object collection from selected objects";
+ ot->idname = "COLLECTION_OT_create";
+
/* api callbacks */
- ot->exec = group_create_exec;
+ ot->exec = collection_create_exec;
ot->poll = ED_operator_objectmode;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_string(ot->srna, "name", "Group", MAX_ID_NAME - 2, "Name", "Name of the new group");
+
+ RNA_def_string(ot->srna, "name", "Collection", MAX_ID_NAME - 2, "Name", "Name of the new collection");
}
/****************** properties window operators *********************/
-static int group_add_exec(bContext *C, wmOperator *UNUSED(op))
+static int collection_add_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = ED_object_context(C);
Main *bmain = CTX_data_main(C);
- Group *group;
if (ob == NULL)
return OPERATOR_CANCELLED;
- group = BKE_group_add(bmain, "Group");
- BKE_group_object_add(group, ob);
+ Collection *collection = BKE_collection_add(bmain, NULL, "Collection");
+ id_fake_user_set(&collection->id);
+ BKE_collection_object_add(bmain, collection, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
}
-void OBJECT_OT_group_add(wmOperatorType *ot)
+void OBJECT_OT_collection_add(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Add to Group";
- ot->idname = "OBJECT_OT_group_add";
- ot->description = "Add an object to a new group";
-
+ ot->name = "Add to Collection";
+ ot->idname = "OBJECT_OT_collection_add";
+ ot->description = "Add an object to a new collection";
+
/* api callbacks */
- ot->exec = group_add_exec;
+ ot->exec = collection_add_exec;
ot->poll = ED_operator_objectmode;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int group_link_exec(bContext *C, wmOperator *op)
+static int collection_link_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Object *ob = ED_object_context(C);
- Group *group = BLI_findlink(&bmain->group, RNA_enum_get(op->ptr, "group"));
+ Collection *collection = BLI_findlink(&bmain->collection, RNA_enum_get(op->ptr, "collection"));
- if (ELEM(NULL, ob, group))
+ if (ELEM(NULL, ob, collection))
return OPERATOR_CANCELLED;
- /* Early return check, if the object is already in group
+ /* 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_group_object_exists(group, ob)) {
+ if (BKE_collection_has_object(collection, ob)) {
return OPERATOR_FINISHED;
}
- /* Adding object to group which is used as dupligroup for self is bad idea.
+ /* Adding object to collection which is used as duplicollection for self is bad idea.
*
- * It is also bad idea to add object to group which is in group which
+ * It is also bad idea to add object to collection which is in collection which
* contains our current object.
*/
- if (BKE_group_object_cyclic_check(bmain, ob, group)) {
- BKE_report(op->reports, RPT_ERROR, "Could not add the group because of dependency cycle detected");
+ 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_group_object_add(group, ob);
+ BKE_collection_object_add(bmain, collection, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
}
-void OBJECT_OT_group_link(wmOperatorType *ot)
+void OBJECT_OT_collection_link(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
- ot->name = "Link to Group";
- ot->idname = "OBJECT_OT_group_link";
- ot->description = "Add an object to an existing group";
-
+ ot->name = "Link to Collection";
+ ot->idname = "OBJECT_OT_collection_link";
+ ot->description = "Add an object to an existing collection";
+
/* api callbacks */
- ot->exec = group_link_exec;
+ ot->exec = collection_link_exec;
ot->invoke = WM_enum_search_invoke;
ot->poll = ED_operator_objectmode;
@@ -477,36 +483,37 @@ void OBJECT_OT_group_link(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "");
- RNA_def_enum_funcs(prop, RNA_group_local_itemf);
+ 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 group_remove_exec(bContext *C, wmOperator *UNUSED(op))
+static int collection_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
+ Main *bmain = CTX_data_main(C);
Object *ob = ED_object_context(C);
- Group *group = CTX_data_pointer_get_type(C, "group", &RNA_Group).data;
+ Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
- if (!ob || !group)
+ if (!ob || !collection)
return OPERATOR_CANCELLED;
- BKE_group_object_unlink(group, ob);
+ BKE_collection_object_remove(bmain, collection, ob, false);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
+
return OPERATOR_FINISHED;
}
-void OBJECT_OT_group_remove(wmOperatorType *ot)
+void OBJECT_OT_collection_remove(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Remove Group";
- ot->idname = "OBJECT_OT_group_remove";
- ot->description = "Remove the active object from this group";
-
+ ot->name = "Remove Collection";
+ ot->idname = "OBJECT_OT_collection_remove";
+ ot->description = "Remove the active object from this collection";
+
/* api callbacks */
- ot->exec = group_remove_exec;
+ ot->exec = collection_remove_exec;
ot->poll = ED_operator_objectmode;
/* flags */
@@ -514,47 +521,47 @@ void OBJECT_OT_group_remove(wmOperatorType *ot)
}
-static int group_unlink_exec(bContext *C, wmOperator *UNUSED(op))
+static int collection_unlink_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
- Group *group = CTX_data_pointer_get_type(C, "group", &RNA_Group).data;
+ Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
- if (!group)
+ if (!collection)
return OPERATOR_CANCELLED;
- BKE_libblock_delete(bmain, group);
+ BKE_libblock_delete(bmain, collection);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
return OPERATOR_FINISHED;
}
-void OBJECT_OT_group_unlink(wmOperatorType *ot)
+void OBJECT_OT_collection_unlink(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Unlink Group";
- ot->idname = "OBJECT_OT_group_unlink";
- ot->description = "Unlink the group from all objects";
+ ot->name = "Unlink Collection";
+ ot->idname = "OBJECT_OT_collection_unlink";
+ ot->description = "Unlink the collection from all objects";
/* api callbacks */
- ot->exec = group_unlink_exec;
+ ot->exec = collection_unlink_exec;
ot->poll = ED_operator_objectmode;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int select_grouped_exec(bContext *C, wmOperator *UNUSED(op)) /* Select objects in the same group as the active */
+static int select_grouped_exec(bContext *C, wmOperator *UNUSED(op)) /* Select objects in the same collection as the active */
{
- Group *group = CTX_data_pointer_get_type(C, "group", &RNA_Group).data;
+ Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
- if (!group)
+ if (!collection)
return OPERATOR_CANCELLED;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
- if (BKE_group_object_exists(group, base->object)) {
+ 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);
}
}
@@ -566,12 +573,12 @@ static int select_grouped_exec(bContext *C, wmOperator *UNUSED(op)) /* Select o
return OPERATOR_FINISHED;
}
-void OBJECT_OT_grouped_select(wmOperatorType *ot)
+void OBJECT_OT_collection_objects_select(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Select Grouped";
- ot->idname = "OBJECT_OT_grouped_select";
- ot->description = "Select all objects in group";
+ 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;
diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c
index 8c68431c19a..de2c413c690 100644
--- a/source/blender/editors/object/object_hook.c
+++ b/source/blender/editors/object/object_hook.c
@@ -82,17 +82,17 @@ static int return_editmesh_indexar(
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++;
@@ -100,9 +100,9 @@ static int return_editmesh_indexar(
}
nr++;
}
-
+
mul_v3_fl(r_cent, 1.0f / (float)totvert);
-
+
return totvert;
}
@@ -136,9 +136,9 @@ static bool return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *r_name,
return true;
}
}
-
+
return false;
-}
+}
static void select_editbmesh_hook(Object *ob, HookModifierData *hmd)
{
@@ -147,10 +147,10 @@ static void select_editbmesh_hook(Object *ob, HookModifierData *hmd)
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);
@@ -169,7 +169,7 @@ static int return_editlattice_indexar(
{
BPoint *bp;
int *index, nr, totvert = 0, a;
-
+
/* count */
a = editlatt->pntsu * editlatt->pntsv * editlatt->pntsw;
bp = editlatt->def;
@@ -181,12 +181,12 @@ static int return_editlattice_indexar(
}
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--) {
@@ -199,9 +199,9 @@ static int return_editlattice_indexar(
bp++;
nr++;
}
-
+
mul_v3_fl(r_cent, 1.0f / (float)totvert);
-
+
return totvert;
}
@@ -234,7 +234,7 @@ static int return_editcurve_indexar(
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;
@@ -256,12 +256,12 @@ static int return_editcurve_indexar(
}
}
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;
@@ -298,19 +298,19 @@ static int return_editcurve_indexar(
}
}
}
-
+
mul_v3_fl(r_cent, 1.0f / (float)totvert);
-
+
return totvert;
}
-static bool object_hook_index_array(Scene *scene, Object *obedit,
+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:
{
@@ -318,7 +318,7 @@ static bool object_hook_index_array(Scene *scene, Object *obedit,
BMEditMesh *em;
- EDBM_mesh_load(obedit);
+ EDBM_mesh_load(bmain, obedit);
EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true);
DEG_id_tag_update(obedit->data, 0);
@@ -336,7 +336,7 @@ static bool object_hook_index_array(Scene *scene, Object *obedit,
}
case OB_CURVE:
case OB_SURF:
- ED_curve_editnurb_load(obedit);
+ 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:
@@ -356,7 +356,7 @@ static void select_editcurve_hook(Object *obedit, HookModifierData *hmd)
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;
@@ -377,7 +377,7 @@ static void select_editcurve_hook(Object *obedit, HookModifierData *hmd)
if (index < hmd->totindex - 1) index++;
}
nr++;
-
+
bezt++;
}
}
@@ -421,11 +421,11 @@ static void object_hook_from_context(bContext *C, PointerRNA *ptr, const int num
}
}
-static void object_hook_select(Object *ob, HookModifierData *hmd)
+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);
@@ -437,14 +437,14 @@ static void object_hook_select(Object *ob, HookModifierData *hmd)
static int 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;
}
@@ -454,12 +454,12 @@ static Object *add_hook_object_new(Main *bmain, Scene *scene, ViewLayer *view_la
Object *ob;
ob = BKE_object_add(bmain, scene, view_layer, OB_EMPTY, NULL);
-
+
basedit = BKE_view_layer_base_find(view_layer, obedit);
base = view_layer->basact;
base->lay = ob->lay = obedit->lay;
BLI_assert(view_layer->basact->object == ob);
-
+
/* icky, BKE_object_add sets new base as active.
* so set it back to the original edit object */
view_layer->basact = basedit;
@@ -475,8 +475,8 @@ static int add_hook_object(const bContext *C, Main *bmain, Scene *scene, ViewLay
float pose_mat[4][4];
int tot, ok, *indexar;
char name[MAX_NAME];
-
- ok = object_hook_index_array(scene, obedit, &tot, &indexar, name, cent);
+
+ 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");
@@ -484,29 +484,29 @@ static int add_hook_object(const bContext *C, Main *bmain, Scene *scene, ViewLay
}
if (mode == OBJECT_ADDHOOK_NEWOB && !ob) {
-
+
ob = add_hook_object_new(bmain, scene, view_layer, 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);
@@ -545,11 +545,11 @@ static int add_hook_object(const bContext *C, Main *bmain, Scene *scene, ViewLay
/* 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;
@@ -564,7 +564,7 @@ static int object_add_hook_selob_exec(bContext *C, wmOperator *op)
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) {
@@ -573,7 +573,7 @@ static int object_add_hook_selob_exec(bContext *C, wmOperator *op)
}
}
CTX_DATA_END;
-
+
if (!obsel) {
BKE_report(op->reports, RPT_ERROR, "Cannot add hook with no other selected objects");
return OPERATOR_CANCELLED;
@@ -583,7 +583,7 @@ static int object_add_hook_selob_exec(bContext *C, wmOperator *op)
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, obedit, obsel, mode, op->reports)) {
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obedit);
return OPERATOR_FINISHED;
@@ -599,11 +599,11 @@ void OBJECT_OT_hook_add_selob(wmOperatorType *ot)
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;
@@ -619,6 +619,7 @@ static int object_add_hook_newob_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
if (add_hook_object(C, bmain, scene, view_layer, obedit, NULL, OBJECT_ADDHOOK_NEWOB, op->reports)) {
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obedit);
return OPERATOR_FINISHED;
@@ -634,11 +635,11 @@ void OBJECT_OT_hook_add_newob(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -654,29 +655,29 @@ static int object_hook_remove_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
return OPERATOR_CANCELLED;
}
-
+
/* remove functionality */
-
+
BLI_remlink(&ob->modifiers, (ModifierData *)hmd);
modifier_free((ModifierData *)hmd);
-
+
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-
+
return OPERATOR_FINISHED;
}
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;
@@ -686,32 +687,32 @@ static const EnumPropertyItem *hook_mod_itemf(bContext *C, PointerRNA *UNUSED(pt
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);
@@ -736,26 +737,26 @@ static int object_hook_reset_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-
+
return OPERATOR_FINISHED;
}
void OBJECT_OT_hook_reset(wmOperatorType *ot)
{
PropertyRNA *prop;
-
+
/* 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;
-
+
/* 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);
@@ -770,42 +771,42 @@ static int object_hook_recenter_exec(bContext *C, wmOperator *op)
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, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-
+
return OPERATOR_FINISHED;
}
void OBJECT_OT_hook_recenter(wmOperatorType *ot)
{
PropertyRNA *prop;
-
+
/* 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;
-
+
/* 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);
@@ -814,6 +815,7 @@ void OBJECT_OT_hook_recenter(wmOperatorType *ot)
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");
@@ -822,50 +824,50 @@ static int object_hook_assign_exec(bContext *C, wmOperator *op)
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(scene, ob, &tot, &indexar, name, cent)) {
+
+ 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, OB_RECALC_DATA);
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);
@@ -878,40 +880,40 @@ static int object_hook_select_exec(bContext *C, wmOperator *op)
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;
}
-
+
/* select functionality */
object_hook_select(ob, hmd);
-
+
+ DEG_id_tag_update(ob->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
-
+
return OPERATOR_FINISHED;
}
void OBJECT_OT_hook_select(wmOperatorType *ot)
{
PropertyRNA *prop;
-
+
/* 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;
-
+
/* 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);
}
-
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index dbb81be124a..ce3d6eff7b4 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -76,7 +76,11 @@ void OBJECT_OT_drop_named_material(struct wmOperatorType *ot);
void OBJECT_OT_unlink_data(struct wmOperatorType *ot);
/* object_edit.c */
+void OBJECT_OT_hide_view_set(struct wmOperatorType *ot);
+void OBJECT_OT_hide_view_clear(struct wmOperatorType *ot);
+void OBJECT_OT_hide_collection(struct wmOperatorType *ot);
void OBJECT_OT_mode_set(struct wmOperatorType *ot);
+void OBJECT_OT_mode_set_or_submode(struct wmOperatorType *ot);
void OBJECT_OT_editmode_toggle(struct wmOperatorType *ot);
void OBJECT_OT_posemode_toggle(struct wmOperatorType *ot);
void OBJECT_OT_proxy_make(struct wmOperatorType *ot);
@@ -88,6 +92,7 @@ void OBJECT_OT_paths_clear(struct wmOperatorType *ot);
void OBJECT_OT_forcefield_toggle(struct wmOperatorType *ot);
void OBJECT_OT_move_to_collection(struct wmOperatorType *ot);
+void OBJECT_OT_link_to_collection(struct wmOperatorType *ot);
/* object_select.c */
void OBJECT_OT_select_all(struct wmOperatorType *ot);
@@ -99,7 +104,6 @@ void OBJECT_OT_select_grouped(struct wmOperatorType *ot);
void OBJECT_OT_select_mirror(struct wmOperatorType *ot);
void OBJECT_OT_select_more(struct wmOperatorType *ot);
void OBJECT_OT_select_less(struct wmOperatorType *ot);
-void OBJECT_OT_select_same_group(struct wmOperatorType *ot);
void OBJECT_OT_select_same_collection(struct wmOperatorType *ot);
/* object_add.c */
@@ -115,7 +119,7 @@ void OBJECT_OT_lamp_add(struct wmOperatorType *ot);
void OBJECT_OT_effector_add(struct wmOperatorType *ot);
void OBJECT_OT_camera_add(struct wmOperatorType *ot);
void OBJECT_OT_speaker_add(struct wmOperatorType *ot);
-void OBJECT_OT_group_instance_add(struct wmOperatorType *ot);
+void OBJECT_OT_collection_instance_add(struct wmOperatorType *ot);
void OBJECT_OT_duplicates_make_real(struct wmOperatorType *ot);
void OBJECT_OT_duplicate(struct wmOperatorType *ot);
@@ -134,11 +138,11 @@ void OBJECT_OT_hook_reset(struct wmOperatorType *ot);
void OBJECT_OT_hook_recenter(struct wmOperatorType *ot);
/* object_group.c */
-void GROUP_OT_create(struct wmOperatorType *ot);
-void GROUP_OT_objects_remove_all(struct wmOperatorType *ot);
-void GROUP_OT_objects_remove(struct wmOperatorType *ot);
-void GROUP_OT_objects_add_active(struct wmOperatorType *ot);
-void GROUP_OT_objects_remove_active(struct wmOperatorType *ot);
+void COLLECTION_OT_create(struct wmOperatorType *ot);
+void COLLECTION_OT_objects_remove_all(struct wmOperatorType *ot);
+void COLLECTION_OT_objects_remove(struct wmOperatorType *ot);
+void COLLECTION_OT_objects_add_active(struct wmOperatorType *ot);
+void COLLECTION_OT_objects_remove_active(struct wmOperatorType *ot);
/* object_modifier.c */
int edit_modifier_poll_generic(struct bContext *C, struct StructRNA *rna_type, int obtype_flag);
@@ -251,11 +255,11 @@ void OBJECT_OT_shape_key_mirror(struct wmOperatorType *ot);
void OBJECT_OT_shape_key_move(struct wmOperatorType *ot);
/* object_group.c */
-void OBJECT_OT_group_add(struct wmOperatorType *ot);
-void OBJECT_OT_group_link(struct wmOperatorType *ot);
-void OBJECT_OT_group_remove(struct wmOperatorType *ot);
-void OBJECT_OT_group_unlink(struct wmOperatorType *ot);
-void OBJECT_OT_grouped_select(struct wmOperatorType *ot);
+void OBJECT_OT_collection_add(struct wmOperatorType *ot);
+void OBJECT_OT_collection_link(struct wmOperatorType *ot);
+void OBJECT_OT_collection_remove(struct wmOperatorType *ot);
+void OBJECT_OT_collection_unlink(struct wmOperatorType *ot);
+void OBJECT_OT_collection_objects_select(struct wmOperatorType *ot);
/* object_bake.c */
void OBJECT_OT_bake_image(wmOperatorType *ot);
@@ -269,4 +273,3 @@ void OBJECT_OT_data_transfer(struct wmOperatorType *ot);
void OBJECT_OT_datalayout_transfer(struct wmOperatorType *ot);
#endif /* __OBJECT_INTERN_H__ */
-
diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c
index 3fb0e75a01e..e9bd6fbce8f 100644
--- a/source/blender/editors/object/object_modes.c
+++ b/source/blender/editors/object/object_modes.c
@@ -45,6 +45,7 @@
#include "DEG_depsgraph.h"
+#include "ED_armature.h"
#include "ED_screen.h"
#include "ED_object.h" /* own include */
@@ -197,16 +198,18 @@ bool ED_object_mode_generic_enter(
* 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)
{
+ 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(NULL, scene, ob, EM_FREEDATA);
+ ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA);
}
}
else if (ob->mode & OB_MODE_VERTEX_PAINT) {
@@ -233,6 +236,14 @@ static bool ed_object_mode_generic_exit_ex(
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;
@@ -244,17 +255,18 @@ static bool ed_object_mode_generic_exit_ex(
}
void ED_object_mode_generic_exit(
+ struct Main *bmain,
struct Depsgraph *depsgraph,
struct Scene *scene, struct Object *ob)
{
- ed_object_mode_generic_exit_ex(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)
{
- return ed_object_mode_generic_exit_ex(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 43cd65c55cd..d24cc936ec1 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -63,6 +63,7 @@
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
+#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
#include "BKE_multires.h"
#include "BKE_report.h"
@@ -100,7 +101,7 @@ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *sc
{
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);
@@ -113,23 +114,23 @@ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *sc
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
+ * of particle systems which shouldn't have too many duplicates
*/
- new_md = object_add_particle_system(scene, ob, name);
+ 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
@@ -142,7 +143,7 @@ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *sc
/* make sure modifier data has unique name */
modifier_unique_name(&ob->modifiers, new_md);
-
+
/* special cases */
if (type == eModifierType_Softbody) {
if (!ob->soft) {
@@ -153,7 +154,7 @@ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *sc
else if (type == eModifierType_Collision) {
if (!ob->pd)
ob->pd = object_add_collision_fields(0);
-
+
ob->pd->deflect = 1;
}
else if (type == eModifierType_Surface) {
@@ -199,7 +200,7 @@ static bool object_has_modifier(const Object *ob, const ModifierData *exclude,
* each of them.
*
* If include_orig is true, the callback will run on 'orig_ob' too.
- *
+ *
* If the callback ever returns true, iteration will stop and the
* function value will be true. Otherwise the function returns false.
*/
@@ -323,8 +324,6 @@ static bool object_modifier_remove(Main *bmain, Object *ob, ModifierData *md,
ob->mode &= ~OB_MODE_PARTICLE_EDIT;
}
- DEG_relations_tag_update(bmain);
-
BLI_remlink(&ob->modifiers, md);
modifier_free(md);
BKE_object_free_derived_caches(ob);
@@ -468,14 +467,14 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *
/* 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;
@@ -523,13 +522,12 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *
return 1;
}
-static int modifier_apply_shape(ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md)
+static int modifier_apply_shape(
+ Main *bmain, ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md)
{
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- md->scene = scene;
-
- if (mti->isDisabled && mti->isDisabled(md, 0)) {
+ if (mti->isDisabled && mti->isDisabled(scene, md, 0)) {
BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
return 0;
}
@@ -546,35 +544,35 @@ static int modifier_apply_shape(ReportList *reports, Depsgraph *depsgraph, Scene
*/
if (ob->type == OB_MESH) {
- DerivedMesh *dm;
+ 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;
}
-
- dm = mesh_create_derived_for_modifier(depsgraph, scene, ob, md, 0);
- if (!dm) {
+
+ mesh_applied = BKE_mesh_create_derived_for_modifier(depsgraph, scene, ob, md, 0);
+ 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((ID *)me);
+ 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, kb);
+ BKE_keyblock_convert_from_mesh(me, key, kb);
}
kb = BKE_keyblock_add(key, md->name);
- DM_to_meshkey(dm, me, kb);
-
- dm->release(dm);
+ 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");
@@ -587,15 +585,13 @@ static int modifier_apply_obdata(ReportList *reports, Depsgraph *depsgraph, Scen
{
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- md->scene = scene;
-
- if (mti->isDisabled && mti->isDisabled(md, 0)) {
+ 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) {
- DerivedMesh *dm;
+ Mesh *mesh_applied;
Mesh *me = ob->data;
MultiresModifierData *mmd = find_multires_modifier_before(scene, md);
@@ -615,13 +611,13 @@ static int modifier_apply_obdata(ReportList *reports, Depsgraph *depsgraph, Scen
}
}
else {
- dm = mesh_create_derived_for_modifier(depsgraph, scene, ob, md, 1);
- if (!dm) {
+ mesh_applied = BKE_mesh_create_derived_for_modifier(depsgraph, scene, ob, md, 1);
+ if (!mesh_applied) {
BKE_report(reports, RPT_ERROR, "Modifier returned error, skipping apply");
return 0;
}
- DM_to_mesh(dm, me, ob, CD_MASK_MESH, true);
+ BKE_mesh_nomain_to_mesh(mesh_applied, me, ob, CD_MASK_MESH, true);
if (md->type == eModifierType_Multires)
multires_customdata_delete(me);
@@ -642,7 +638,7 @@ static int modifier_apply_obdata(ReportList *reports, Depsgraph *depsgraph, Scen
BKE_report(reports, RPT_INFO, "Applied modifier only changed CV points, not tessellated/bevel vertices");
vertexCos = BKE_curve_nurbs_vertexCos_get(&cu->nurb, &numVerts);
- modifier_deformVerts_DM_deprecated(md, &mectx, NULL, vertexCos, numVerts);
+ modifier_deformVerts(md, &mectx, NULL, vertexCos, numVerts);
BK_curve_nurbs_vertexCos_apply(&cu->nurb, vertexCos);
MEM_freeN(vertexCos);
@@ -660,7 +656,7 @@ static int modifier_apply_obdata(ReportList *reports, Depsgraph *depsgraph, Scen
ParticleSystem *psys = ob->particlesystem.first;
for (; psys; psys = psys->next) {
-
+
if (psys->part->type != PART_HAIR)
continue;
@@ -672,7 +668,7 @@ static int modifier_apply_obdata(ReportList *reports, Depsgraph *depsgraph, Scen
}
int ED_object_modifier_apply(
- ReportList *reports, Depsgraph *depsgraph,
+ Main *bmain, ReportList *reports, Depsgraph *depsgraph,
Scene *scene, Object *ob, ModifierData *md, int mode)
{
int prev_mode;
@@ -701,7 +697,7 @@ int ED_object_modifier_apply(
md->mode |= eModifierMode_Realtime;
if (mode == MODIFIER_APPLY_SHAPE) {
- if (!modifier_apply_shape(reports, depsgraph, scene, ob, md)) {
+ if (!modifier_apply_shape(bmain, reports, depsgraph, scene, ob, md)) {
md->mode = prev_mode;
return 0;
}
@@ -724,7 +720,7 @@ int ED_object_modifier_apply(
int ED_object_modifier_copy(ReportList *UNUSED(reports), Object *ob, ModifierData *md)
{
ModifierData *nmd;
-
+
nmd = modifier_new(md->type);
modifier_copyData(md, nmd);
BLI_insertlinkafter(&ob->modifiers, md, nmd);
@@ -746,19 +742,19 @@ static int modifier_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-
+
return OPERATOR_FINISHED;
}
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;
-
+
if (!ob)
return rna_enum_object_modifier_type_items;
@@ -803,15 +799,15 @@ void OBJECT_OT_modifier_add(wmOperatorType *ot)
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;
-
+
/* 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);
@@ -824,7 +820,7 @@ int 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);
-
+
if (!ptr.data) {
CTX_wm_operator_poll_msg_set(C, "Context missing 'modifier'");
return 0;
@@ -838,7 +834,7 @@ int edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag
CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers comming from static override");
return (((ModifierData *)ptr.data)->flag & eModifierFlag_StaticOverride_Local) != 0;
}
-
+
return 1;
}
@@ -855,7 +851,7 @@ void edit_modifier_properties(wmOperatorType *ot)
int edit_modifier_invoke_properties(bContext *C, wmOperator *op)
{
ModifierData *md;
-
+
if (RNA_struct_property_is_set(op->ptr, "modifier")) {
return true;
}
@@ -876,9 +872,9 @@ 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);
-
+
md = modifiers_findByName(ob, modifier_name);
-
+
if (md && type != 0 && md->type != type)
md = NULL;
@@ -894,7 +890,7 @@ static int modifier_remove_exec(bContext *C, wmOperator *op)
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;
@@ -928,7 +924,7 @@ void OBJECT_OT_modifier_remove(wmOperatorType *ot)
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);
@@ -946,7 +942,7 @@ static int modifier_move_up_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -967,7 +963,7 @@ void OBJECT_OT_modifier_move_up(wmOperatorType *ot)
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);
@@ -985,7 +981,7 @@ static int modifier_move_down_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -1006,7 +1002,7 @@ void OBJECT_OT_modifier_move_down(wmOperatorType *ot)
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);
@@ -1016,19 +1012,20 @@ void OBJECT_OT_modifier_move_down(wmOperatorType *ot)
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");
- if (!md || !ED_object_modifier_apply(op->reports, depsgraph, scene, ob, md, apply_as)) {
+ if (!md || !ED_object_modifier_apply(bmain, op->reports, depsgraph, scene, ob, md, apply_as)) {
return OPERATOR_CANCELLED;
}
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -1055,10 +1052,10 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot)
ot->invoke = modifier_apply_invoke;
ot->exec = modifier_apply_exec;
ot->poll = edit_modifier_poll;
-
+
/* 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);
}
@@ -1072,13 +1069,13 @@ static int modifier_convert_exec(bContext *C, wmOperator *op)
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, scene, view_layer, ob, md))
return OPERATOR_CANCELLED;
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -1099,7 +1096,7 @@ void OBJECT_OT_modifier_convert(wmOperatorType *ot)
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);
@@ -1117,7 +1114,7 @@ static int modifier_copy_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -1138,7 +1135,7 @@ void OBJECT_OT_modifier_copy(wmOperatorType *ot)
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);
@@ -1153,20 +1150,21 @@ static int multires_poll(bContext *C)
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);
-
+
if (!mmd)
return OPERATOR_CANCELLED;
-
- multiresModifier_del_levels(mmd, 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);
-
+
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -1187,7 +1185,7 @@ void OBJECT_OT_multires_higher_levels_delete(wmOperatorType *ot)
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);
@@ -1197,13 +1195,14 @@ void OBJECT_OT_multires_higher_levels_delete(wmOperatorType *ot)
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);
-
+
if (!mmd)
return OPERATOR_CANCELLED;
-
- multiresModifier_subdivide(mmd, 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,
@@ -1216,7 +1215,7 @@ static int multires_subdivide_exec(bContext *C, wmOperator *op)
/* ensure that grid paint mask layer is created */
BKE_sculpt_mask_layers_ensure(ob, mmd);
}
-
+
return OPERATOR_FINISHED;
}
@@ -1237,7 +1236,7 @@ void OBJECT_OT_multires_subdivide(wmOperatorType *ot)
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);
@@ -1302,18 +1301,19 @@ void OBJECT_OT_multires_reshape(wmOperatorType *ot)
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);
}
-
+
/****************** 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];
@@ -1324,15 +1324,15 @@ static int multires_external_save_exec(bContext *C, wmOperator *op)
if (CustomData_external_test(&me->ldata, CD_MDISPS))
return OPERATOR_CANCELLED;
-
+
RNA_string_get(op->ptr, "filepath", path);
if (relative)
- BLI_path_rel(path, G.main->name);
+ 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, me->totloop, 0);
-
+
return OPERATOR_FINISHED;
}
@@ -1345,23 +1345,23 @@ static int multires_external_save_invoke(bContext *C, wmOperator *op, const wmEv
if (!edit_modifier_invoke_properties(C, op))
return OPERATOR_CANCELLED;
-
+
mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
-
+
if (!mmd)
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);
-
+
op->customdata = me;
BLI_snprintf(path, sizeof(path), "//%s.btx", me->id.name + 2);
RNA_string_set(op->ptr, "filepath", path);
-
+
WM_event_add_fileselect(C, op);
return OPERATOR_RUNNING_MODAL;
@@ -1377,7 +1377,7 @@ void OBJECT_OT_multires_external_save(wmOperatorType *ot)
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;
@@ -1399,7 +1399,7 @@ static int multires_external_pack_exec(bContext *C, wmOperator *UNUSED(op))
/* XXX don't remove.. */
CustomData_external_remove(&me->ldata, &me->id, CD_MDISPS, me->totloop);
-
+
return OPERATOR_FINISHED;
}
@@ -1411,7 +1411,7 @@ void OBJECT_OT_multires_external_pack(wmOperatorType *ot)
ot->poll = multires_poll;
ot->exec = multires_external_pack_exec;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1419,17 +1419,18 @@ void OBJECT_OT_multires_external_pack(wmOperatorType *ot)
/********************* 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);
-
+
if (!mmd)
return OPERATOR_CANCELLED;
-
- multiresModifier_base_apply(mmd, ob);
+
+ multiresModifier_base_apply(mmd, scene, ob);
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -1451,7 +1452,7 @@ void OBJECT_OT_multires_base_apply(wmOperatorType *ot)
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);
@@ -1464,7 +1465,7 @@ static void modifier_skin_customdata_delete(Object *ob)
{
Mesh *me = ob->data;
BMEditMesh *em = me->edit_btmesh;
-
+
if (em)
BM_data_layer_free(em->bm, &em->bm->vdata, CD_MVERT_SKIN);
else
@@ -1487,7 +1488,7 @@ static void skin_root_clear(BMVert *bm_vert, GSet *visited, const int cd_vert_sk
{
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);
@@ -1535,7 +1536,7 @@ static int skin_root_mark_exec(bContext *C, wmOperator *UNUSED(op))
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -1547,7 +1548,7 @@ void OBJECT_OT_skin_root_mark(wmOperatorType *ot)
ot->poll = skin_edit_poll;
ot->exec = skin_root_mark_exec;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1590,7 +1591,7 @@ static int skin_loose_mark_clear_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -1608,7 +1609,7 @@ void OBJECT_OT_skin_loose_mark_clear(wmOperatorType *ot)
ot->poll = skin_edit_poll;
ot->exec = skin_loose_mark_clear_exec;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1640,7 +1641,7 @@ static int skin_radii_equalize_exec(bContext *C, wmOperator *UNUSED(op))
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -1652,7 +1653,7 @@ void OBJECT_OT_skin_radii_equalize(wmOperatorType *ot)
ot->poll = skin_edit_poll;
ot->exec = skin_radii_equalize_exec;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1696,7 +1697,7 @@ static void skin_armature_bone_create(Object *skin_ob,
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,
@@ -1729,7 +1730,7 @@ static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain,
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);
@@ -1763,7 +1764,7 @@ static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain,
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,
@@ -1780,7 +1781,7 @@ static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain,
MEM_freeN(emap);
MEM_freeN(emap_mem);
- ED_armature_from_edit(arm);
+ ED_armature_from_edit(bmain, arm);
ED_armature_edit_free(arm);
return arm_ob;
@@ -1838,7 +1839,7 @@ void OBJECT_OT_skin_armature_create(wmOperatorType *ot)
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);
@@ -1924,7 +1925,7 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op)
Object *ob = ED_object_active_context(C);
Depsgraph *depsgraph = CTX_data_depsgraph(C);
MeshDeformModifierData *mmd = (MeshDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_MeshDeform);
-
+
if (!mmd)
return OPERATOR_CANCELLED;
@@ -1949,7 +1950,7 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op)
mmd->totvert = 0;
mmd->totcagevert = 0;
mmd->totinfluence = 0;
-
+
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
}
@@ -1978,7 +1979,7 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op)
mmd->bindfunc = NULL;
mmd->modifier.mode = mode;
}
-
+
return OPERATOR_FINISHED;
}
@@ -1986,7 +1987,7 @@ static int meshdeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UN
{
if (edit_modifier_invoke_properties(C, op))
return meshdeform_bind_exec(C, op);
- else
+ else
return OPERATOR_CANCELLED;
}
@@ -1996,12 +1997,12 @@ void OBJECT_OT_meshdeform_bind(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
@@ -2018,7 +2019,7 @@ 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);
-
+
if (!emd)
return OPERATOR_CANCELLED;
@@ -2026,7 +2027,7 @@ static int explode_refresh_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -2048,7 +2049,7 @@ void OBJECT_OT_explode_refresh(wmOperatorType *ot)
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);
@@ -2066,14 +2067,14 @@ static int ocean_bake_poll(bContext *C)
static void init_ocean_modifier_bake(struct Ocean *oc, struct OceanModifierData *omd)
{
int do_heightfield, do_chop, do_normals, do_jacobian;
-
- if (!omd || !oc) return;
-
+
+ if (!omd || !oc) return;
+
do_heightfield = true;
do_chop = (omd->chop_amount > 0);
do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS);
do_jacobian = (omd->flag & MOD_OCEAN_GENERATE_FOAM);
-
+
BKE_ocean_init(oc, omd->resolution * omd->resolution, omd->resolution * omd->resolution, omd->spatial_size, omd->spatial_size,
omd->wind_velocity, omd->smallest_wave, 1.0, omd->wave_direction, omd->damp, omd->wave_alignment,
omd->depth, omd->time,
@@ -2103,8 +2104,8 @@ static int oceanbake_breakjob(void *UNUSED(customdata))
{
//OceanBakeJob *ob = (OceanBakeJob *)customdata;
//return *(ob->stop);
-
- /* this is not nice yet, need to make the jobs list template better
+
+ /* 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);
@@ -2114,10 +2115,10 @@ static int oceanbake_breakjob(void *UNUSED(customdata))
static void oceanbake_update(void *customdata, float progress, int *cancel)
{
OceanBakeJob *oj = customdata;
-
+
if (oceanbake_breakjob(oj))
*cancel = 1;
-
+
*(oj->do_update) = true;
*(oj->progress) = progress;
}
@@ -2125,15 +2126,15 @@ static void oceanbake_update(void *customdata, float progress, int *cancel)
static void oceanbake_startjob(void *customdata, short *stop, short *do_update, float *progress)
{
OceanBakeJob *oj = customdata;
-
+
oj->stop = stop;
oj->do_update = do_update;
oj->progress = progress;
-
+
G.is_break = false; /* XXX shared with render - replace with job 'stop' switch */
-
+
BKE_ocean_bake(oj->ocean, oj->och, oceanbake_update, (void *)oj);
-
+
*do_update = true;
*stop = 0;
}
@@ -2141,18 +2142,19 @@ static void oceanbake_startjob(void *customdata, short *stop, short *do_update,
static void oceanbake_endjob(void *customdata)
{
OceanBakeJob *oj = customdata;
-
+
if (oj->ocean) {
BKE_ocean_free(oj->ocean);
oj->ocean = NULL;
}
-
+
oj->omd->oceancache = oj->och;
oj->omd->cached = true;
}
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);
@@ -2160,13 +2162,13 @@ static int ocean_bake_exec(bContext *C, wmOperator *op)
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) {
omd->refresh |= MOD_OCEAN_REFRESH_CLEAR_CACHE;
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
@@ -2174,59 +2176,59 @@ static int ocean_bake_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
- och = BKE_ocean_init_cache(omd->cachepath, modifier_path_relbase(ob),
+ 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++) {
/* from physics_fluid.c:
*
* XXX: This can't be used due to an anim sys optimization that ignores recalc object animation,
* leaving it for the depgraph (this ignores object animation such as modifier properties though... :/ )
- * --> BKE_animsys_evaluate_all_animation(G.main, eval_time);
+ * --> BKE_animsys_evaluate_all_animation(bmain, eval_time);
* This doesn't work with drivers:
* --> BKE_animsys_evaluate_animdata(&fsDomain->id, fsDomain->adt, eval_time, ADT_RECALC_ALL);
*/
-
- /* Modifying the global scene isn't nice, but we can do it in
+
+ /* 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 = f;
- //ED_update_for_newframe(CTX_data_main(C), scene);
-
- /* ok, this doesn't work with drivers, but is way faster.
+ //ED_update_for_newframe(bmain, scene);
+
+ /* ok, this doesn't work with drivers, but is way faster.
* let's use this for now and hope nobody wants to drive the time value... */
- BKE_animsys_evaluate_animdata(scene, (ID *)ob, ob->adt, f, ADT_RECALC_ANIM);
-
+ 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();
init_ocean_modifier_bake(ocean, omd);
-
+
#if 0
BKE_ocean_bake(ocean, och);
-
+
omd->oceancache = och;
omd->cached = true;
-
+
scene->r.cfra = cfra;
-
+
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
#endif
-
+
/* job stuff */
-
+
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);
@@ -2234,15 +2236,15 @@ static int ocean_bake_exec(bContext *C, wmOperator *op)
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_start(CTX_wm_manager(C), wm_job);
-
-
-
+
+
+
return OPERATOR_FINISHED;
}
@@ -2260,15 +2262,15 @@ 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->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);
-
+
RNA_def_boolean(ot->srna, "free", false, "Free", "Free the bake, rather than generating it");
}
@@ -2327,7 +2329,7 @@ static int laplaciandeform_bind_invoke(bContext *C, wmOperator *op, const wmEven
{
if (edit_modifier_invoke_properties(C, op))
return laplaciandeform_bind_exec(C, op);
- else
+ else
return OPERATOR_CANCELLED;
}
@@ -2337,12 +2339,12 @@ void OBJECT_OT_laplaciandeform_bind(wmOperatorType *ot)
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;
-
+
/* 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 c4c86b3932d..0dafa8905c8 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -65,8 +65,9 @@ void ED_operatortypes_object(void)
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);
@@ -93,7 +94,6 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_select_random);
WM_operatortype_append(OBJECT_OT_select_all);
- WM_operatortype_append(OBJECT_OT_select_same_group);
WM_operatortype_append(OBJECT_OT_select_same_collection);
WM_operatortype_append(OBJECT_OT_select_by_type);
WM_operatortype_append(OBJECT_OT_select_linked);
@@ -102,11 +102,11 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_select_more);
WM_operatortype_append(OBJECT_OT_select_less);
- WM_operatortype_append(GROUP_OT_create);
- WM_operatortype_append(GROUP_OT_objects_remove_all);
- WM_operatortype_append(GROUP_OT_objects_remove);
- WM_operatortype_append(GROUP_OT_objects_add_active);
- WM_operatortype_append(GROUP_OT_objects_remove_active);
+ 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);
@@ -120,7 +120,7 @@ void ED_operatortypes_object(void)
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_group_instance_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);
@@ -150,7 +150,7 @@ void ED_operatortypes_object(void)
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);
@@ -213,6 +213,7 @@ void ED_operatortypes_object(void)
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);
@@ -221,11 +222,11 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_shape_key_mirror);
WM_operatortype_append(OBJECT_OT_shape_key_move);
- WM_operatortype_append(OBJECT_OT_group_add);
- WM_operatortype_append(OBJECT_OT_group_link);
- WM_operatortype_append(OBJECT_OT_group_remove);
- WM_operatortype_append(OBJECT_OT_group_unlink);
- WM_operatortype_append(OBJECT_OT_grouped_select);
+ 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);
@@ -246,13 +247,17 @@ void ED_operatortypes_object(void)
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) {
@@ -270,7 +275,7 @@ void ED_operatormacros_object(void)
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF);
}
-
+
}
static int object_mode_poll(bContext *C)
@@ -283,35 +288,26 @@ void ED_keymap_object(wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
wmKeyMapItem *kmi;
- int i;
-
+
/* Objects, Regardless of Mode -------------------------------------------------- */
keymap = WM_keymap_find(keyconf, "Object Non-modal", 0, 0);
-
- /* Note: this keymap works disregarding mode */
- kmi = WM_keymap_add_item(keymap, "OBJECT_OT_mode_set", TABKEY, KM_PRESS, 0, 0);
+
+ /* modes */
+ kmi = WM_keymap_add_item(keymap, "OBJECT_OT_mode_set", TABKEY, KM_CLICK, 0, 0);
RNA_enum_set(kmi->ptr, "mode", OB_MODE_EDIT);
RNA_boolean_set(kmi->ptr, "toggle", true);
- kmi = WM_keymap_add_item(keymap, "OBJECT_OT_mode_set", TABKEY, KM_PRESS, KM_CTRL, 0);
- RNA_enum_set(kmi->ptr, "mode", OB_MODE_POSE);
- RNA_boolean_set(kmi->ptr, "toggle", true);
+ kmi = WM_keymap_add_menu_pie(keymap, "VIEW3D_MT_object_mode_pie", TABKEY, KM_CLICK_DRAG, 0, 0);
- kmi = WM_keymap_add_item(keymap, "OBJECT_OT_mode_set", VKEY, KM_PRESS, 0, 0);
- RNA_enum_set(kmi->ptr, "mode", OB_MODE_VERTEX_PAINT);
- RNA_boolean_set(kmi->ptr, "toggle", true);
-
- kmi = WM_keymap_add_item(keymap, "OBJECT_OT_mode_set", TABKEY, KM_PRESS, KM_CTRL, 0);
- RNA_enum_set(kmi->ptr, "mode", OB_MODE_WEIGHT_PAINT);
- RNA_boolean_set(kmi->ptr, "toggle", true);
-
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "OBJECT_OT_origin_set", CKEY, KM_PRESS, KM_ALT | KM_SHIFT | KM_CTRL, 0);
+#endif
/* Object Mode ---------------------------------------------------------------- */
/* Note: this keymap gets disabled in non-objectmode, */
keymap = WM_keymap_find(keyconf, "Object Mode", 0, 0);
keymap->poll = object_mode_poll;
-
+
/* object mode supports PET now */
ED_keymap_proportional_cycle(keyconf, keymap);
ED_keymap_proportional_obmode(keyconf, keymap);
@@ -326,8 +322,10 @@ void ED_keymap_object(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "OBJECT_OT_select_linked", LKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "OBJECT_OT_select_grouped", GKEY, KM_PRESS, KM_SHIFT, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "OBJECT_OT_select_mirror", MKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
-
+#endif
+
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_select_hierarchy", LEFTBRACKETKEY, KM_PRESS, 0, 0);
RNA_enum_set_identifier(NULL, kmi->ptr, "direction", "PARENT");
RNA_boolean_set(kmi->ptr, "extend", false);
@@ -345,29 +343,36 @@ void ED_keymap_object(wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "extend", true);
WM_keymap_verify_item(keymap, "OBJECT_OT_parent_set", PKEY, KM_PRESS, KM_CTRL, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_verify_item(keymap, "OBJECT_OT_parent_no_inverse_set", PKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
+#endif
WM_keymap_verify_item(keymap, "OBJECT_OT_parent_clear", PKEY, KM_PRESS, KM_ALT, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_verify_item(keymap, "OBJECT_OT_track_set", TKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_verify_item(keymap, "OBJECT_OT_track_clear", TKEY, KM_PRESS, KM_ALT, 0);
-
+#endif
+
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_verify_item(keymap, "OBJECT_OT_constraint_add_with_targets", CKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
WM_keymap_verify_item(keymap, "OBJECT_OT_constraints_clear", CKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
-
-
+#endif
+
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_location_clear", GKEY, KM_PRESS, KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "clear_delta", false);
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_rotation_clear", RKEY, KM_PRESS, KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "clear_delta", false);
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_scale_clear", SKEY, KM_PRESS, KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "clear_delta", false);
-
+
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_verify_item(keymap, "OBJECT_OT_origin_clear", OKEY, KM_PRESS, KM_ALT, 0);
-
+
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_delete", XKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "use_global", false);
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_delete", XKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "use_global", true);
+#endif
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_delete", DELKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "use_global", false);
@@ -376,43 +381,65 @@ void ED_keymap_object(wmKeyConfig *keyconf)
WM_keymap_add_menu(keymap, "INFO_MT_add", AKEY, KM_PRESS, KM_SHIFT, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "OBJECT_OT_duplicates_make_real", AKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
+#endif
WM_keymap_add_menu(keymap, "VIEW3D_MT_object_apply", AKEY, KM_PRESS, KM_CTRL, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_menu(keymap, "VIEW3D_MT_make_single_user", UKEY, KM_PRESS, 0, 0);
WM_keymap_add_menu(keymap, "VIEW3D_MT_make_links", LKEY, KM_PRESS, KM_CTRL, 0);
+#endif
WM_keymap_add_item(keymap, "OBJECT_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "OBJECT_OT_duplicate_move_linked", DKEY, KM_PRESS, KM_ALT, 0);
-
+
WM_keymap_add_item(keymap, "OBJECT_OT_join", JKEY, KM_PRESS, KM_CTRL, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "OBJECT_OT_convert", CKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "OBJECT_OT_proxy_make", PKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
WM_keymap_add_item(keymap, "OBJECT_OT_make_local", LKEY, KM_PRESS, 0, 0);
+#endif
/* XXX this should probably be in screen instead... here for testing purposes in the meantime... - Aligorith */
WM_keymap_verify_item(keymap, "ANIM_OT_keyframe_insert_menu", IKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "ANIM_OT_keyframe_delete_v3d", IKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_verify_item(keymap, "ANIM_OT_keying_set_active_set", IKEY, KM_PRESS, KM_CTRL | KM_SHIFT | KM_ALT, 0);
-
- WM_keymap_verify_item(keymap, "GROUP_OT_create", GKEY, KM_PRESS, KM_CTRL, 0);
- WM_keymap_verify_item(keymap, "GROUP_OT_objects_remove", GKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
- WM_keymap_verify_item(keymap, "GROUP_OT_objects_remove_all", GKEY, KM_PRESS, KM_SHIFT | KM_CTRL | KM_ALT, 0);
- WM_keymap_verify_item(keymap, "GROUP_OT_objects_add_active", GKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
- WM_keymap_verify_item(keymap, "GROUP_OT_objects_remove_active", GKEY, KM_PRESS, KM_SHIFT | KM_ALT, 0);
-
+
+ WM_keymap_verify_item(keymap, "COLLECTION_OT_create", GKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_verify_item(keymap, "COLLECTION_OT_objects_remove", GKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
+ WM_keymap_verify_item(keymap, "COLLECTION_OT_objects_remove_all", GKEY, KM_PRESS, KM_SHIFT | KM_CTRL | KM_ALT, 0);
+ WM_keymap_verify_item(keymap, "COLLECTION_OT_objects_add_active", GKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
+ WM_keymap_verify_item(keymap, "COLLECTION_OT_objects_remove_active", GKEY, KM_PRESS, KM_SHIFT | KM_ALT, 0);
+
WM_keymap_add_menu(keymap, "VIEW3D_MT_object_specials", WKEY, KM_PRESS, 0, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_verify_item(keymap, "OBJECT_OT_data_transfer", TKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
+#endif
/* XXX No more available 'T' shortcuts... :/ */
/* WM_keymap_verify_item(keymap, "OBJECT_OT_datalayout_transfer", TKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0); */
- for (i = 0; i <= 5; i++) {
+ for (int i = 0; i <= 5; i++) {
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_subdivision_set", ZEROKEY + i, KM_PRESS, KM_CTRL, 0);
RNA_int_set(kmi->ptr, "level", i);
}
WM_keymap_add_item(keymap, "OBJECT_OT_move_to_collection", MKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "OBJECT_OT_link_to_collection", MKEY, KM_PRESS, KM_SHIFT, 0);
+
+ kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_clear", HKEY, KM_PRESS, KM_ALT, 0);
+ kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "unselected", false);
+ kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "unselected", true);
+ kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_collection", HKEY, KM_PRESS, KM_CTRL, 0);
+
+ /* Collection switching. */
+ for (int i = 0; i < 10; i++) {
+ kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_collection", ZEROKEY + i, KM_PRESS, KM_ANY, 0);
+ RNA_int_set(kmi->ptr, "collection_index", (i == 0) ? 10 : i);
+ }
}
void ED_keymap_proportional_cycle(struct wmKeyConfig *UNUSED(keyconf), struct wmKeyMap *keymap)
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index ee1ef490274..8db58b17520 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -70,7 +70,6 @@
#include "BKE_DerivedMesh.h"
#include "BKE_displist.h"
#include "BKE_global.h"
-#include "BKE_group.h"
#include "BKE_fcurve.h"
#include "BKE_idprop.h"
#include "BKE_lamp.h"
@@ -146,7 +145,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
Mesh *me = obedit->data;
BMEditMesh *em;
- EDBM_mesh_load(obedit);
+ EDBM_mesh_load(bmain, obedit);
EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true);
DEG_id_tag_update(obedit->data, 0);
@@ -329,7 +328,7 @@ static int make_proxy_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
else {
/* error.. cannot continue */
- BKE_report(op->reports, RPT_ERROR, "Can only make proxy for a referenced object or group");
+ BKE_report(op->reports, RPT_ERROR, "Can only make proxy for a referenced object or collection");
return OPERATOR_CANCELLED;
}
@@ -343,7 +342,8 @@ static int make_proxy_exec(bContext *C, wmOperator *op)
ViewLayer *view_layer = CTX_data_view_layer(C);
if (gob->dup_group != NULL) {
- Base *base = BLI_findlink(&gob->dup_group->view_layer->object_bases, RNA_enum_get(op->ptr, "object"));
+ const ListBase dup_group_objects = BKE_collection_object_cache_get(gob->dup_group);
+ Base *base = BLI_findlink(&dup_group_objects, RNA_enum_get(op->ptr, "object"));
ob = base->object;
}
else {
@@ -385,8 +385,8 @@ static int make_proxy_exec(bContext *C, wmOperator *op)
}
/* Generic itemf's for operators that take library args */
-static const EnumPropertyItem *proxy_group_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;
@@ -397,13 +397,13 @@ static const EnumPropertyItem *proxy_group_object_itemf(bContext *C, PointerRNA
return DummyRNA_DEFAULT_items;
/* find the object to affect */
- FOREACH_GROUP_OBJECT_BEGIN(ob->dup_group, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(ob->dup_group, object)
{
item_tmp.identifier = item_tmp.name = object->id.name + 2;
item_tmp.value = i++;
RNA_enum_item_add(&item, &totitem, &item_tmp);
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
RNA_enum_item_end(&item, &totitem);
*r_free = true;
@@ -431,8 +431,8 @@ void OBJECT_OT_proxy_make(wmOperatorType *ot)
/* 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/grouped object to make a proxy for");
- RNA_def_enum_funcs(prop, proxy_group_object_itemf);
+ "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;
}
@@ -640,7 +640,7 @@ bool ED_object_parent_set(ReportList *reports, const bContext *C, Scene *scene,
/* 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(&cu->id, 1);
+ bAction *act = verify_adt_action(bmain, &cu->id, 1);
FCurve *fcu = verify_fcurve(act, NULL, NULL, "eval_time", 0, 1);
/* setup dummy 'generator' modifier here to get 1-1 correspondence still working */
@@ -1343,7 +1343,8 @@ static void link_to_scene(Main *UNUSED(bmain), unsigned short UNUSED(nr))
static int make_links_scene_exec(bContext *C, wmOperator *op)
{
- Scene *scene_to = BLI_findlink(&CTX_data_main(C)->scene, RNA_enum_get(op->ptr, "scene"));
+ Main *bmain = CTX_data_main(C);
+ Scene *scene_to = BLI_findlink(&bmain->scene, RNA_enum_get(op->ptr, "scene"));
if (scene_to == NULL) {
BKE_report(op->reports, RPT_ERROR, "Could not find scene");
@@ -1360,10 +1361,10 @@ static int make_links_scene_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- SceneCollection *sc_to = BKE_collection_master(&scene_to->id);
+ Collection *collection_to = BKE_collection_master(scene_to);
CTX_DATA_BEGIN (C, Base *, base, selected_bases)
{
- BKE_collection_object_add(&scene_to->id, sc_to, base->object);
+ BKE_collection_object_add(bmain, collection_to, base->object);
}
CTX_DATA_END;
@@ -1379,7 +1380,7 @@ enum {
MAKE_LINKS_MATERIALS = 2,
MAKE_LINKS_ANIMDATA = 3,
MAKE_LINKS_GROUP = 4,
- MAKE_LINKS_DUPLIGROUP = 5,
+ MAKE_LINKS_DUPLICOLLECTION = 5,
MAKE_LINKS_MODIFIERS = 6,
MAKE_LINKS_FONTS = 7,
};
@@ -1400,7 +1401,7 @@ static bool allow_make_links_data(const int type, Object *ob_src, Object *ob_dst
break;
case MAKE_LINKS_ANIMDATA:
case MAKE_LINKS_GROUP:
- case MAKE_LINKS_DUPLIGROUP:
+ case MAKE_LINKS_DUPLICOLLECTION:
return true;
case MAKE_LINKS_MODIFIERS:
if (!ELEM(OB_EMPTY, ob_src->type, ob_dst->type)) {
@@ -1418,22 +1419,23 @@ static bool allow_make_links_data(const int type, Object *ob_src, Object *ob_dst
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;
- /* group */
- LinkNode *ob_groups = NULL;
+ /* collection */
+ LinkNode *ob_collections = NULL;
bool is_cycle = false;
bool is_lib = false;
ob_src = ED_object_active_context(C);
- /* avoid searching all groups in source object each time */
+ /* avoid searching all collections in source object each time */
if (type == MAKE_LINKS_GROUP) {
- ob_groups = BKE_object_groups(ob_src);
+ ob_collections = BKE_object_groups(bmain, ob_src);
}
CTX_DATA_BEGIN (C, Base *, base_dst, selected_editable_bases)
@@ -1453,7 +1455,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
ob_dst->data = obdata_id;
/* if amount of material indices changed: */
- test_object_materials(ob_dst, ob_dst->data);
+ test_object_materials(bmain, ob_dst, ob_dst->data);
DEG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
break;
@@ -1461,7 +1463,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
/* new approach, using functions from kernel */
for (a = 0; a < ob_src->totcol; a++) {
Material *ma = give_current_material(ob_src, a + 1);
- assign_material(ob_dst, ma, a + 1, BKE_MAT_ASSIGN_USERPREF); /* also works with ma==NULL */
+ assign_material(bmain, ob_dst, ma, a + 1, BKE_MAT_ASSIGN_USERPREF); /* also works with ma==NULL */
}
DEG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
break;
@@ -1478,15 +1480,15 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
break;
case MAKE_LINKS_GROUP:
{
- LinkNode *group_node;
+ LinkNode *collection_node;
- /* first clear groups */
- BKE_object_groups_clear(ob_dst);
+ /* first clear collections */
+ BKE_object_groups_clear(bmain, ob_dst);
- /* now add in the groups from the link nodes */
- for (group_node = ob_groups; group_node; group_node = group_node->next) {
- if (ob_dst->dup_group != group_node->link) {
- BKE_group_object_add(group_node->link, 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->dup_group != collection_node->link) {
+ BKE_collection_object_add(bmain, collection_node->link, ob_dst);
}
else {
is_cycle = true;
@@ -1494,15 +1496,15 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
}
break;
}
- case MAKE_LINKS_DUPLIGROUP:
+ case MAKE_LINKS_DUPLICOLLECTION:
ob_dst->dup_group = ob_src->dup_group;
if (ob_dst->dup_group) {
id_us_plus(&ob_dst->dup_group->id);
- ob_dst->transflag |= OB_DUPLIGROUP;
+ ob_dst->transflag |= OB_DUPLICOLLECTION;
}
break;
case MAKE_LINKS_MODIFIERS:
- BKE_object_link_modifiers(ob_dst, ob_src);
+ BKE_object_link_modifiers(scene, ob_dst, ob_src);
DEG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
break;
case MAKE_LINKS_FONTS:
@@ -1542,12 +1544,12 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
if (type == MAKE_LINKS_GROUP) {
- if (ob_groups) {
- BLI_linklist_free(ob_groups, NULL);
+ if (ob_collections) {
+ BLI_linklist_free(ob_collections, NULL);
}
if (is_cycle) {
- BKE_report(op->reports, RPT_WARNING, "Skipped some groups because of cycle detected");
+ BKE_report(op->reports, RPT_WARNING, "Skipped some collections because of cycle detected");
}
}
@@ -1595,7 +1597,7 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot)
{MAKE_LINKS_MATERIALS, "MATERIAL", 0, "Materials", ""},
{MAKE_LINKS_ANIMDATA, "ANIMATION", 0, "Animation Data", ""},
{MAKE_LINKS_GROUP, "GROUPS", 0, "Group", ""},
- {MAKE_LINKS_DUPLIGROUP, "DUPLIGROUP", 0, "DupliGroup", ""},
+ {MAKE_LINKS_DUPLICOLLECTION, "DUPLICOLLECTION", 0, "DupliGroup", ""},
{MAKE_LINKS_MODIFIERS, "MODIFIERS", 0, "Modifiers", ""},
{MAKE_LINKS_FONTS, "FONTS", 0, "Fonts", ""},
{0, NULL, 0, NULL, NULL}};
@@ -1619,19 +1621,11 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot)
/**************************** Make Single User ********************************/
-static Object *single_object_users_object(Main *bmain, Scene *scene, Object *ob, const bool copy_groups)
+static Object *single_object_users_object(Main *bmain, Scene *scene, Object *ob)
{
/* base gets copy of object */
Object *obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
- if (copy_groups) {
- if (ob->flag & OB_FROMGROUP) {
- obn->flag |= OB_FROMGROUP;
- }
- }
- else {
- /* copy already clears */
- }
/* remap gpencil parenting */
if (scene->gpd) {
@@ -1643,46 +1637,47 @@ static Object *single_object_users_object(Main *bmain, Scene *scene, Object *ob,
}
}
+ id_us_plus(&obn->id);
id_us_min(&ob->id);
return obn;
}
-static void libblock_relink_scene_collection(SceneCollection *sc)
+static void libblock_relink_collection(Collection *collection)
{
- for (LinkData *link = sc->objects.first; link; link = link->next) {
- BKE_libblock_relink_to_newid(link->data);
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ BKE_libblock_relink_to_newid(&cob->ob->id);
}
- for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
- libblock_relink_scene_collection(nsc);
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ libblock_relink_collection(child->collection);
}
}
-static void single_object_users_scene_collection(Main *bmain, Scene *scene, SceneCollection *sc, const int flag, const bool copy_groups)
+static void single_object_users_collection(Main *bmain, Scene *scene, Collection *collection, const int flag, const bool copy_collections)
{
- for (LinkData *link = sc->objects.first; link; link = link->next) {
- Object *ob = link->data;
+ 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) && ob->id.us > 1) {
- link->data = single_object_users_object(bmain, scene, link->data, copy_groups);
+ cob->ob = single_object_users_object(bmain, scene, cob->ob);
}
}
}
- for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
- single_object_users_scene_collection(bmain, scene, nsc, flag, copy_groups);
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ single_object_users_collection(bmain, scene, child->collection, flag, copy_collections);
}
}
-/* Warning, sets ID->newid pointers of objects and groups, but does not clear them. */
-static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_groups)
+/* 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)
{
- Group *group, *groupn;
+ Collection *collection, *collectionn;
/* duplicate all the objects of the scene */
- SceneCollection *msc = BKE_collection_master(&scene->id);
- single_object_users_scene_collection(bmain, scene, msc, flag, copy_groups);
+ Collection *master_collection = BKE_collection_master(scene);
+ single_object_users_collection(bmain, scene, master_collection, flag, copy_collections);
/* loop over ViewLayers and assign the pointers accordingly */
for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
@@ -1691,40 +1686,39 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
}
}
- /* duplicate groups that consist entirely of duplicated objects */
- for (group = bmain->group.first; group; group = group->id.next) {
- if (copy_groups && group->view_layer->object_bases.first) {
+ /* duplicate collections that consist entirely of duplicated objects */
+ for (collection = bmain->collection.first; collection; collection = collection->id.next) {
+ if (copy_collections) {
bool all_duplicated = true;
+ bool any_duplicated = false;
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
- {
- if (object->id.newid == NULL) {
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ any_duplicated = true;
+ if (cob->ob->id.newid == NULL) {
all_duplicated = false;
break;
}
}
- FOREACH_GROUP_OBJECT_END;
- if (all_duplicated) {
- groupn = ID_NEW_SET(group, BKE_group_copy(bmain, group));
+ if (any_duplicated && all_duplicated) {
+ // TODO: test if this works, with child collections ..
+ collectionn = ID_NEW_SET(collection, BKE_collection_copy(bmain, NULL, collection));
- FOREACH_GROUP_BASE_BEGIN(groupn, base)
- {
- base->object = (Object *)base->object->id.newid;
+ for (CollectionObject *cob = collectionn->gobject.first; cob; cob = cob->next) {
+ cob->ob = (Object *)cob->ob->id.newid;
}
- FOREACH_GROUP_BASE_END
}
}
}
- /* group pointers in scene */
+ /* collection pointers in scene */
BKE_scene_groups_relink(scene);
ID_NEW_REMAP(scene->camera);
if (v3d) ID_NEW_REMAP(v3d->camera);
- /* object and group pointers */
- libblock_relink_scene_collection(msc);
+ /* object and collection pointers */
+ libblock_relink_collection(master_collection);
}
/* not an especially efficient function, only added so the single user
@@ -1793,7 +1787,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer
/* 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((ID *)me->key, false);
+ 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));
@@ -1805,12 +1799,12 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer
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((ID *)cu->key, false);
+ 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((ID *)lat->key, false);
+ BKE_animdata_copy_id_action(bmain, (ID *)lat->key, false);
break;
case OB_ARMATURE:
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
@@ -1837,7 +1831,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer
* AnimData structure, which is not what we want.
* (sergey)
*/
- BKE_animdata_copy_id_action((ID *)ob->data, false);
+ BKE_animdata_copy_id_action(bmain, (ID *)ob->data, false);
id_us_min(id);
}
@@ -1852,13 +1846,13 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer
}
}
-static void single_object_action_users(Scene *scene, ViewLayer *view_layer, const int flag)
+static void single_object_action_users(Main *bmain, Scene *scene, ViewLayer *view_layer, const int flag)
{
FOREACH_OBJECT_FLAG_BEGIN(scene, view_layer, flag, ob)
{
if (!ID_IS_LINKED(ob)) {
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
- BKE_animdata_copy_id_action(&ob->id, false);
+ BKE_animdata_copy_id_action(bmain, &ob->id, false);
}
}
FOREACH_OBJECT_FLAG_END;
@@ -1879,10 +1873,10 @@ static void single_mat_users(Main *bmain, Scene *scene, ViewLayer *view_layer, c
if (ma->id.us > 1) {
man = BKE_material_copy(bmain, ma);
- BKE_animdata_copy_id_action(&man->id, false);
+ BKE_animdata_copy_id_action(bmain, &man->id, false);
man->id.us = 0;
- assign_material(ob, man, a, BKE_MAT_ASSIGN_USERPREF);
+ assign_material(bmain, ob, man, a, BKE_MAT_ASSIGN_USERPREF);
}
}
}
@@ -1917,13 +1911,13 @@ static void single_mat_users_expand(Main *bmain)
}
/* used for copying scenes */
-void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bool copy_groups)
+void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bool copy_collections)
{
- single_object_users(bmain, scene, NULL, 0, copy_groups);
+ single_object_users(bmain, scene, NULL, 0, copy_collections);
if (full) {
single_obdata_users(bmain, scene, NULL, 0);
- single_object_action_users(scene, NULL, 0);
+ single_object_action_users(bmain, scene, NULL, 0);
single_mat_users_expand(bmain);
}
@@ -2038,7 +2032,7 @@ static void tag_localizable_objects(bContext *C, const int mode)
* Instance indirectly referenced zero user objects,
* otherwise they're lost on reload, see T40595.
*/
-static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene, ViewLayer *view_layer, SceneCollection *sc)
+static bool make_local_all__instance_indirect_unused(Main *bmain, ViewLayer *view_layer, Collection *collection)
{
Object *ob;
bool changed = false;
@@ -2049,7 +2043,7 @@ static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene,
id_us_plus(&ob->id);
- BKE_collection_object_add(&scene->id, sc, ob);
+ 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);
@@ -2117,7 +2111,6 @@ static void make_local_material_tag(Material *ma)
static int make_local_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
ParticleSystem *psys;
Material *ma, ***matarar;
const int mode = RNA_enum_get(op->ptr, "type");
@@ -2126,14 +2119,14 @@ static int make_local_exec(bContext *C, wmOperator *op)
/* 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);
- SceneCollection *scene_collection = CTX_data_scene_collection(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, scene, view_layer, scene_collection)) {
+ 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");
}
}
@@ -2282,7 +2275,7 @@ static int make_override_static_invoke(bContext *C, wmOperator *op, const wmEven
}
else {
/* Error.. cannot continue. */
- BKE_report(op->reports, RPT_ERROR, "Can only make static override for a referenced object or group");
+ BKE_report(op->reports, RPT_ERROR, "Can only make static override for a referenced object or collection");
return OPERATOR_CANCELLED;
}
@@ -2296,38 +2289,53 @@ static int make_override_static_exec(bContext *C, wmOperator *op)
bool success = false;
if (!ID_IS_LINKED(obact) && obact->dup_group != NULL && ID_IS_LINKED(obact->dup_group)) {
- Base *base = BLI_findlink(&obact->dup_group->view_layer->object_bases, RNA_enum_get(op->ptr, "object"));
- Object *obgroup = obact;
+ const ListBase dup_collection_objects = BKE_collection_object_cache_get(obact->dup_group);
+ Base *base = BLI_findlink(&dup_collection_objects, RNA_enum_get(op->ptr, "object"));
+ Object *obcollection = obact;
obact = base->object;
- Group *group = obgroup->dup_group;
+ Collection *collection = obcollection->dup_group;
- /* First, we make a static override of the linked group itself. */
- group->id.tag |= LIB_TAG_DOIT;
+ /* First, we make a static override of the linked collection itself. */
+ collection->id.tag |= LIB_TAG_DOIT;
- /* Then, we make static override of the whole set of objects in the group. */
- FOREACH_GROUP_OBJECT_BEGIN(group, ob)
+ /* 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_GROUP_OBJECT_END;
+ 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);
/* Intantiate our newly overridden objects in scene, if not yet done. */
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- Group *new_group = (Group *)group->id.newid;
- FOREACH_GROUP_OBJECT_BEGIN(new_group, new_ob)
+ Collection *new_collection = (Collection *)collection->id.newid;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(new_collection, new_ob)
{
- if (new_ob != NULL && (base = BKE_view_layer_base_find(view_layer, new_ob)) == NULL) {
- BKE_collection_object_add_from(scene, obgroup, new_ob);
- DEG_id_tag_update_ex(bmain, &new_ob->id, OB_RECALC_OB | DEG_TAG_BASE_FLAGS_UPDATE);
- /* parent to 'group' empty */
+ 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);
+ DEG_id_tag_update_ex(bmain, &new_ob->id, DEG_TAG_TRANSFORM | DEG_TAG_BASE_FLAGS_UPDATE);
+ }
+ /* parent to 'collection' empty */
if (new_ob->parent == NULL) {
- new_ob->parent = obgroup;
+ new_ob->parent = obcollection;
}
if (new_ob == (Object *)obact->id.newid) {
- base = BKE_view_layer_base_find(view_layer, new_ob);
BKE_view_layer_base_select(view_layer, base);
}
else {
@@ -2335,13 +2343,13 @@ static int make_override_static_exec(bContext *C, wmOperator *op)
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(&new_ob->id, true);
+ BKE_override_static_operations_create(bmain, &new_ob->id, true);
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- /* obgroup is no more dupligroup-ing, it merely parents whole group of overriding instantiated objects. */
- obgroup->dup_group = NULL;
+ /* obcollection is no more duplicollection-ing, it merely parents whole collection of overriding instantiated objects. */
+ obcollection->dup_group = NULL;
/* Also, we'd likely want to lock by default things like transformations of implicitly overriden objects? */
@@ -2407,8 +2415,8 @@ void OBJECT_OT_make_override_static(wmOperatorType *ot)
/* properties */
PropertyRNA *prop;
prop = RNA_def_enum(ot->srna, "object", DummyRNA_DEFAULT_items, 0, "Override Object",
- "Name of lib-linked/group object to make an override from");
- RNA_def_enum_funcs(prop, proxy_group_object_itemf);
+ "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;
}
@@ -2425,16 +2433,16 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
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_groups = false;
+ 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_groups);
+ single_object_users(bmain, scene, v3d, OB_DONE, copy_collections);
}
else {
- single_object_users(bmain, scene, v3d, 0, copy_groups);
+ single_object_users(bmain, scene, v3d, 0, copy_collections);
}
/* needed since object relationships may have changed */
@@ -2450,7 +2458,7 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
}
if (RNA_boolean_get(op->ptr, "animation")) {
- single_object_action_users(scene, view_layer, flag);
+ single_object_action_users(bmain, scene, view_layer, flag);
}
BKE_main_id_clear_newpoins(bmain);
@@ -2495,16 +2503,17 @@ void OBJECT_OT_make_single_user(wmOperatorType *ot)
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];
RNA_string_get(op->ptr, "name", name);
- ma = (Material *)BKE_libblock_find_name(ID_MA, name);
+ ma = (Material *)BKE_libblock_find_name(bmain, ID_MA, name);
if (base == NULL || ma == NULL)
return OPERATOR_CANCELLED;
- assign_material(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, OB_RECALC_OB);
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index d0d0418c861..7d7871c0326 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -50,8 +50,8 @@
#include "BLT_translation.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_group.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_material.h"
@@ -88,7 +88,7 @@
* this takes into account the 'restrict selection in 3d view' flag.
* deselect works always, the restriction just prevents selection */
-/* Note: send a NC_SCENE|ND_OB_SELECT notifier yourself! (or
+/* Note: send a NC_SCENE|ND_OB_SELECT notifier yourself! (or
* or a NC_SCENE|ND_OB_VISIBLE in case of visibility toggling */
void ED_object_base_select(Base *base, eObjectSelect_Mode mode)
@@ -100,7 +100,7 @@ void ED_object_base_select(Base *base, eObjectSelect_Mode mode)
if (base) {
switch (mode) {
case BA_SELECT:
- if ((base->flag & BASE_SELECTABLED) != 0) {
+ if ((base->flag & BASE_SELECTABLE) != 0) {
base->flag |= BASE_SELECTED;
}
break;
@@ -129,6 +129,7 @@ void ED_object_base_activate(bContext *C, Base *base)
else {
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, NULL);
}
+ DEG_id_tag_update(&CTX_data_scene(C)->id, DEG_TAG_SELECT_UPDATE);
}
/********************** Selection Operators **********************/
@@ -143,7 +144,7 @@ static int objects_selectable_poll(bContext *C)
return 0;
if (obact && obact->mode)
return 0;
-
+
return 1;
}
@@ -152,10 +153,10 @@ static int objects_selectable_poll(bContext *C)
static int object_select_by_type_exec(bContext *C, wmOperator *op)
{
short obtype, extend;
-
+
obtype = RNA_enum_get(op->ptr, "type");
extend = RNA_boolean_get(op->ptr, "extend");
-
+
if (extend == 0) {
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
@@ -163,7 +164,7 @@ static int object_select_by_type_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
}
-
+
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
if (base->object->type == obtype) {
@@ -171,9 +172,11 @@ static int object_select_by_type_exec(bContext *C, wmOperator *op)
}
}
CTX_DATA_END;
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
-
+
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+
return OPERATOR_FINISHED;
}
@@ -183,15 +186,15 @@ void OBJECT_OT_select_by_type(wmOperatorType *ot)
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", "");
@@ -226,7 +229,7 @@ static bool object_select_all_by_obdata(bContext *C, void *obdata)
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
+ 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;
@@ -244,7 +247,7 @@ static bool object_select_all_by_material(bContext *C, Material *mat)
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
Object *ob = base->object;
Material *mat1;
int a;
@@ -267,12 +270,12 @@ static bool object_select_all_by_material(bContext *C, Material *mat)
static bool object_select_all_by_dup_group(bContext *C, Object *ob)
{
bool changed = false;
- Group *dup_group = (ob->transflag & OB_DUPLIGROUP) ? ob->dup_group : NULL;
+ Collection *dup_group = (ob->transflag & OB_DUPLICOLLECTION) ? ob->dup_group : NULL;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
- Group *dup_group_other = (base->object->transflag & OB_DUPLIGROUP) ? base->object->dup_group : NULL;
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
+ Collection *dup_group_other = (base->object->transflag & OB_DUPLICOLLECTION) ? base->object->dup_group : NULL;
if (dup_group == dup_group_other) {
ED_object_base_select(base, BA_SELECT);
changed = true;
@@ -291,10 +294,10 @@ static bool object_select_all_by_particle(bContext *C, Object *ob)
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
+ 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);
@@ -319,7 +322,7 @@ static bool object_select_all_by_library(bContext *C, Library *lib)
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
+ 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;
@@ -337,7 +340,7 @@ static bool object_select_all_by_library_obdata(bContext *C, Library *lib)
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
+ 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;
@@ -365,7 +368,9 @@ void ED_object_select_linked_by_id(bContext *C, ID *id)
}
if (changed) {
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
}
@@ -378,7 +383,7 @@ static int object_select_linked_exec(bContext *C, wmOperator *op)
bool changed = false, extend;
extend = RNA_boolean_get(op->ptr, "extend");
-
+
if (extend == 0) {
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
@@ -386,13 +391,13 @@ static int object_select_linked_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
}
-
+
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;
@@ -439,10 +444,11 @@ static int object_select_linked_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
if (changed) {
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
return OPERATOR_FINISHED;
}
-
+
return OPERATOR_CANCELLED;
}
@@ -452,15 +458,15 @@ void OBJECT_OT_select_linked(wmOperatorType *ot)
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", "");
@@ -475,7 +481,6 @@ enum {
OBJECT_GRPSEL_SIBLINGS = 3,
OBJECT_GRPSEL_TYPE = 4,
OBJECT_GRPSEL_COLLECTION = 5,
- OBJECT_GRPSEL_GROUP = 6,
OBJECT_GRPSEL_HOOK = 7,
OBJECT_GRPSEL_PASS = 8,
OBJECT_GRPSEL_COLOR = 9,
@@ -490,7 +495,6 @@ static const EnumPropertyItem prop_select_grouped_types[] = {
{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_GROUP, "GROUP", 0, "Group", "Shared group"},
{OBJECT_GRPSEL_HOOK, "HOOK", 0, "Hook", ""},
{OBJECT_GRPSEL_PASS, "PASS", 0, "Pass", "Render pass Index"},
{OBJECT_GRPSEL_COLOR, "COLOR", 0, "Color", "Object Color"},
@@ -542,30 +546,30 @@ static bool select_grouped_parent(bContext *C) /* Makes parent active and de-sel
}
-#define GROUP_MENU_MAX 24
-static bool select_grouped_group(bContext *C, Object *ob) /* Select objects in the same group as the active */
+#define COLLECTION_MENU_MAX 24
+static bool select_grouped_collection(bContext *C, Object *ob) /* Select objects in the same group as the active */
{
bool changed = false;
- Group *group, *ob_groups[GROUP_MENU_MAX];
- int group_count = 0, i;
+ Collection *collection, *ob_collections[COLLECTION_MENU_MAX];
+ int collection_count = 0, i;
uiPopupMenu *pup;
uiLayout *layout;
- for (group = CTX_data_main(C)->group.first; group && group_count < GROUP_MENU_MAX; group = group->id.next) {
- if (BKE_group_object_exists(group, ob)) {
- ob_groups[group_count] = group;
- group_count++;
+ for (collection = CTX_data_main(C)->collection.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 (!group_count)
+ if (!collection_count)
return 0;
- else if (group_count == 1) {
- group = ob_groups[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_SELECTABLED) != 0)) {
- if (BKE_group_object_exists(group, base->object)) {
+ 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;
}
@@ -576,12 +580,12 @@ static bool select_grouped_group(bContext *C, Object *ob) /* Select objects in
}
/* build the menu. */
- pup = UI_popup_menu_begin(C, IFACE_("Select Group"), ICON_NONE);
+ pup = UI_popup_menu_begin(C, IFACE_("Select Collection"), ICON_NONE);
layout = UI_popup_menu_layout(pup);
- for (i = 0; i < group_count; i++) {
- group = ob_groups[i];
- uiItemStringO(layout, group->id.name + 2, 0, "OBJECT_OT_select_same_group", "group", group->id.name + 2);
+ 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);
@@ -662,60 +666,6 @@ static bool select_grouped_type(bContext *C, Object *ob)
return changed;
}
-#define COLLECTION_MENU_MAX 24
-static bool select_grouped_collection(bContext *C, Object *ob) /* Select objects in the same collection as the active */
-{
- typedef struct EnumeratedCollection {
- struct SceneCollection *collection;
- int index;
- } EnumeratedCollection;
-
- bool changed = false;
- SceneCollection *collection;
- EnumeratedCollection ob_collections[COLLECTION_MENU_MAX];
- int collection_count = 0, i;
- uiPopupMenu *pup;
- uiLayout *layout;
-
- i = 0;
- FOREACH_SCENE_COLLECTION_BEGIN(CTX_data_scene(C), scene_collection)
- {
- if (BKE_collection_object_exists(scene_collection, ob)) {
- ob_collections[collection_count].index = i;
- ob_collections[collection_count].collection = scene_collection;
- if (++collection_count >= COLLECTION_MENU_MAX) {
- break;
- }
- }
- i++;
- }
- FOREACH_SCENE_COLLECTION_END;
-
- if (!collection_count) {
- return 0;
- }
- else if (collection_count == 1) {
- collection = ob_collections[0].collection;
- return BKE_collection_objects_select(CTX_data_view_layer(C), collection);
- }
-
- /* 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++) {
- uiItemIntO(layout,
- ob_collections[i].collection->name,
- ICON_NONE,
- "OBJECT_OT_select_same_collection",
- "collection_index",
- ob_collections[i].index);
- }
-
- UI_popup_menu_end(C, pup);
- return changed; /* The operator already handle this! */
-}
-
static bool select_grouped_index_object(bContext *C, Object *ob)
{
bool changed = false;
@@ -750,7 +700,7 @@ static bool select_grouped_keyingset(bContext *C, Object *UNUSED(ob), ReportList
{
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");
@@ -759,7 +709,7 @@ static bool select_grouped_keyingset(bContext *C, Object *UNUSED(ob), ReportList
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,
+ 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");
}
@@ -769,7 +719,7 @@ static bool select_grouped_keyingset(bContext *C, Object *UNUSED(ob), ReportList
}
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 */
@@ -778,8 +728,8 @@ static bool select_grouped_keyingset(bContext *C, Object *UNUSED(ob), ReportList
/* 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,
+
+ /* 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) {
@@ -793,7 +743,7 @@ static bool select_grouped_keyingset(bContext *C, Object *UNUSED(ob), ReportList
}
}
CTX_DATA_END;
-
+
return changed;
}
@@ -841,9 +791,6 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op)
case OBJECT_GRPSEL_COLLECTION:
changed |= select_grouped_collection(C, ob);
break;
- case OBJECT_GRPSEL_GROUP:
- changed |= select_grouped_group(C, ob);
- break;
case OBJECT_GRPSEL_HOOK:
changed |= select_grouped_object_hooks(C, ob);
break;
@@ -868,6 +815,7 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op)
}
if (changed) {
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
return OPERATOR_FINISHED;
}
@@ -881,15 +829,15 @@ void OBJECT_OT_select_grouped(wmOperatorType *ot)
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", "");
@@ -900,7 +848,7 @@ void OBJECT_OT_select_grouped(wmOperatorType *ot)
static int object_select_all_exec(bContext *C, wmOperator *op)
{
int action = RNA_enum_get(op->ptr, "action");
-
+
/* passthrough if no objects are visible */
if (CTX_DATA_COUNT(C, visible_bases) == 0) return OPERATOR_PASS_THROUGH;
@@ -936,107 +884,70 @@ static int object_select_all_exec(bContext *C, wmOperator *op)
}
}
CTX_DATA_END;
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
-
+
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+
return OPERATOR_FINISHED;
}
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";
-
+
/* api callbacks */
ot->exec = object_select_all_exec;
ot->poll = objects_selectable_poll;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
WM_operator_properties_select_all(ot);
}
-/**************************** Select In The Same Group ****************************/
+/**************************** Select In The Same Collection ****************************/
-static int object_select_same_group_exec(bContext *C, wmOperator *op)
+static int object_select_same_collection_exec(bContext *C, wmOperator *op)
{
- Group *group;
- char group_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;
- RNA_string_get(op->ptr, "group", group_name);
+ RNA_string_get(op->ptr, "collection", collection_name);
- group = (Group *)BKE_libblock_find_name(ID_GR, group_name);
+ collection = (Collection *)BKE_libblock_find_name(bmain, ID_GR, collection_name);
- if (!group) {
+ if (!collection) {
return OPERATOR_PASS_THROUGH;
}
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
- if (BKE_group_object_exists(group, base->object)) {
+ 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;
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
-
- return OPERATOR_FINISHED;
-}
-
-void OBJECT_OT_select_same_group(wmOperatorType *ot)
-{
-
- /* identifiers */
- ot->name = "Select Same Group";
- ot->description = "Select object in the same group";
- ot->idname = "OBJECT_OT_select_same_group";
-
- /* api callbacks */
- ot->exec = object_select_same_group_exec;
- ot->poll = objects_selectable_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_string(ot->srna, "group", NULL, MAX_ID_NAME, "Group", "Name of the group to select");
-}
-
-/**************************** Select In The Same Collection ****************************/
-
-static int object_select_same_collection_exec(bContext *C, wmOperator *op)
-{
- SceneCollection *collection;
-
- /* passthrough if no objects are visible */
- if (CTX_DATA_COUNT(C, visible_bases) == 0) return OPERATOR_PASS_THROUGH;
-
- int collection_index = RNA_int_get(op->ptr, "collection_index");
- collection = BKE_collection_from_index(CTX_data_scene(C), collection_index);
-
- if (!collection) {
- return OPERATOR_PASS_THROUGH;
- }
-
- if (BKE_collection_objects_select(CTX_data_view_layer(C), collection)) {
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
- }
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
return OPERATOR_FINISHED;
}
void OBJECT_OT_select_same_collection(wmOperatorType *ot)
{
- PropertyRNA *prop;
/* identifiers */
ot->name = "Select Same Collection";
@@ -1050,27 +961,27 @@ void OBJECT_OT_select_same_collection(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- prop = RNA_def_int(ot->srna, "collection_index", -1, -1, INT_MAX,
- "Collection Index", "Index of the collection to select", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_string(ot->srna, "collection", NULL, MAX_ID_NAME, "Collection", "Name of the collection to select");
}
+
/**************************** Select Mirror ****************************/
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");
-
+
CTX_DATA_BEGIN (C, Base *, primbase, selected_bases)
{
char name_flip[MAXBONENAME];
BLI_string_flip_side_name(name_flip, primbase->object->id.name + 2, true, sizeof(name_flip));
-
+
if (!STREQ(name_flip, primbase->object->id.name + 2)) {
- Object *ob = (Object *)BKE_libblock_find_name(ID_OB, name_flip);
+ Object *ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, name_flip);
if (ob) {
Base *secbase = BKE_view_layer_base_find(view_layer, ob);
@@ -1079,33 +990,34 @@ static int object_select_mirror_exec(bContext *C, wmOperator *op)
}
}
}
-
+
if (extend == false) ED_object_base_select(primbase, BA_DESELECT);
-
+
}
CTX_DATA_END;
-
+
/* undo? */
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
-
+
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";
-
+
/* api callbacks */
ot->exec = object_select_mirror_exec;
ot->poll = objects_selectable_poll;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first");
}
@@ -1173,7 +1085,9 @@ static int object_select_more_exec(bContext *C, wmOperator *UNUSED(op))
bool changed = object_select_more_less(C, true);
if (changed) {
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
return OPERATOR_FINISHED;
}
else {
@@ -1201,7 +1115,9 @@ static int object_select_less_exec(bContext *C, wmOperator *UNUSED(op))
bool changed = object_select_more_less(C, false);
if (changed) {
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
return OPERATOR_FINISHED;
}
else {
@@ -1230,7 +1146,7 @@ void OBJECT_OT_select_less(wmOperatorType *ot)
/**************************** Select Random ****************************/
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);
@@ -1247,8 +1163,10 @@ static int object_select_random_exec(bContext *C, wmOperator *op)
BLI_rng_free(rng);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
-
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+
return OPERATOR_FINISHED;
}
@@ -1258,15 +1176,15 @@ void OBJECT_OT_select_random(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
WM_operator_properties_select_random(ot);
}
diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c
index 1f80cb5f0bc..f2cdb0d124f 100644
--- a/source/blender/editors/object/object_shapekey.c
+++ b/source/blender/editors/object/object_shapekey.c
@@ -35,7 +35,7 @@
#include <unistd.h>
#else
#include <io.h>
-#endif
+#endif
#include "MEM_guardedalloc.h"
@@ -78,8 +78,9 @@
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(ob, NULL, from_mix))) {
+ 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;
@@ -119,7 +120,7 @@ static bool object_shape_key_mirror(bContext *C, Object *ob,
key = BKE_key_from_object(ob);
if (key == NULL)
return 0;
-
+
kb = BLI_findlink(&key->block, ob->shapenr - 1);
if (kb) {
@@ -211,7 +212,7 @@ static bool object_shape_key_mirror(bContext *C, Object *ob,
MEM_freeN(tag_elem);
}
-
+
*r_totmirr = totmirr;
*r_totfail = totfail;
@@ -278,7 +279,7 @@ void OBJECT_OT_shape_key_add(wmOperatorType *ot)
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;
@@ -321,7 +322,7 @@ void OBJECT_OT_shape_key_remove(wmOperatorType *ot)
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;
@@ -341,13 +342,13 @@ static int shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op))
if (!key || !kb)
return OPERATOR_CANCELLED;
-
+
for (kb = key->block.first; kb; kb = kb->next)
kb->curval = 0.0f;
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -357,7 +358,7 @@ void OBJECT_OT_shape_key_clear(wmOperatorType *ot)
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;
@@ -501,4 +502,3 @@ void OBJECT_OT_shape_key_move(wmOperatorType *ot)
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 a862ef718d2..721d248ae4c 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -122,7 +122,7 @@ static void object_clear_rot(Object *ob, const bool clear_delta)
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;
@@ -168,7 +168,7 @@ static void object_clear_rot(Object *ob, const bool clear_delta)
/* 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);
@@ -179,16 +179,16 @@ static void object_clear_rot(Object *ob, const bool clear_delta)
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 */
@@ -241,24 +241,24 @@ static void object_clear_scale(Object *ob, const bool clear_delta)
/* --------------- */
/* 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
+
+ /* 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)
@@ -266,15 +266,15 @@ static int object_clear_transform_generic_exec(bContext *C, wmOperator *op,
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, OB_RECALC_OB);
}
}
CTX_DATA_END;
-
+
/* this is needed so children are also updated */
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
@@ -295,15 +295,15 @@ void OBJECT_OT_location_clear(wmOperatorType *ot)
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");
@@ -320,14 +320,14 @@ void OBJECT_OT_rotation_clear(wmOperatorType *ot)
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");
@@ -344,14 +344,14 @@ void OBJECT_OT_scale_clear(wmOperatorType *ot)
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");
@@ -370,7 +370,7 @@ static int object_origin_clear_exec(bContext *C, wmOperator *UNUSED(op))
/* 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);
@@ -381,7 +381,7 @@ static int object_origin_clear_exec(bContext *C, wmOperator *UNUSED(op))
CTX_DATA_END;
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -391,11 +391,11 @@ void OBJECT_OT_origin_clear(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -409,7 +409,7 @@ static void ignore_parent_tx(const bContext *C, Main *bmain, Scene *scene, Objec
Object workob;
Object *ob_child;
Depsgraph *depsgraph = CTX_data_depsgraph(C);
-
+
/* a change was made, adjust the children to compensate */
for (ob_child = bmain->object.first; ob_child; ob_child = ob_child->id.next) {
if (ob_child->parent == ob) {
@@ -493,7 +493,7 @@ static int apply_objects_internal(
}
}
CTX_DATA_END;
-
+
if (!changed)
return OPERATOR_CANCELLED;
@@ -545,15 +545,15 @@ static int apply_objects_internal(
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(ob, mat, do_props);
+ ED_armature_transform_apply(bmain, ob, mat, do_props);
}
else if (ob->type == OB_LATTICE) {
Lattice *lt = ob->data;
@@ -600,12 +600,12 @@ static int apply_objects_internal(
BKE_tracking_reconstruction_scale(&clip->tracking, ob->size);
}
else if (ob->type == OB_EMPTY) {
- /* It's possible for empties too, even though they don't
+ /* 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
+ * 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
@@ -631,6 +631,10 @@ static int apply_objects_internal(
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];
@@ -686,7 +690,7 @@ static int visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op))
/* update for any children that may get moved */
DEG_id_tag_update(&ob->id, OB_RECALC_OB);
-
+
changed = true;
}
CTX_DATA_END;
@@ -704,11 +708,11 @@ void OBJECT_OT_visual_transform_apply(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -799,7 +803,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
BMEditMesh *em = me->edit_btmesh;
BMVert *eve;
BMIter iter;
-
+
if (centermode == ORIGIN_TO_CURSOR) {
copy_v3_v3(cent, cursor);
invert_m4_m4(obedit->imat, obedit->obmat);
@@ -823,7 +827,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
mid_v3_v3v3(cent, min, max);
}
}
-
+
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
sub_v3_v3(eve->co, cent);
}
@@ -876,10 +880,10 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
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_DUPLIGROUP) && ob->dup_group && (ob->dup_group->id.tag & LIB_TAG_DOIT) == 0) {
+ if ((ob->transflag & OB_DUPLICOLLECTION) && ob->dup_group && (ob->dup_group->id.tag & LIB_TAG_DOIT) == 0) {
if (ID_IS_LINKED(ob->dup_group)) {
tot_lib_error++;
}
@@ -896,7 +900,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
invert_m4_m4(ob->imat, ob->obmat);
mul_m4_v3(ob->imat, cent);
}
-
+
add_v3_v3(ob->dup_group->dupli_ofs, cent);
tot_change++;
@@ -1002,7 +1006,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
/* Function to recenter armatures in editarmature.c
* Bone + object locations are handled there.
*/
- ED_armature_origin_set(ob, cursor, centermode, around);
+ ED_armature_origin_set(bmain, ob, cursor, centermode, around);
tot_change++;
arm->id.tag |= LIB_TAG_DOIT;
@@ -1073,7 +1077,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
}
ignore_parent_tx(C, bmain, scene, ob);
-
+
/* other users? */
//CTX_DATA_BEGIN (C, Object *, ob_other, selected_editable_objects)
//{
@@ -1088,7 +1092,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
if ((ob_other->flag & OB_DONE) == 0 &&
((ob->data && (ob->data == ob_other->data)) ||
(ob->dup_group == ob_other->dup_group &&
- (ob->transflag | ob_other->transflag) & OB_DUPLIGROUP)))
+ (ob->transflag | ob_other->transflag) & OB_DUPLICOLLECTION)))
{
ob_other->flag |= OB_DONE;
DEG_id_tag_update(&ob_other->id, OB_RECALC_OB | OB_RECALC_DATA);
@@ -1147,27 +1151,27 @@ void OBJECT_OT_origin_set(wmOperatorType *ot)
"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_MEAN, "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_MEAN, "Center", "");
}
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index ff40aa07cd2..1c1c67c9da4 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -58,11 +58,11 @@
#include "BKE_customdata.h"
#include "BKE_deform.h"
#include "BKE_mesh_mapping.h"
+#include "BKE_mesh_runtime.h"
#include "BKE_editmesh.h"
#include "BKE_layer.h"
#include "BKE_modifier.h"
#include "BKE_report.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_object_deform.h"
#include "BKE_object.h"
#include "BKE_lattice.h"
@@ -772,7 +772,7 @@ static void ED_vgroup_nr_vert_add(
/* get the vert */
BKE_object_defgroup_array_get(ob->data, &dvert, &tot);
-
+
if (dvert == NULL)
return;
@@ -937,7 +937,7 @@ static float get_vert_def_nr(Object *ob, const int def_nr, const int vertnum)
dv = &lt->dvert[vertnum];
}
}
-
+
if (dv) {
MDeformWeight *dw = defvert_find_index(dv, def_nr);
if (dw) {
@@ -1024,12 +1024,12 @@ static void vgroup_select_verts(Object *ob, int select)
}
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;
@@ -1057,7 +1057,7 @@ static void vgroup_duplicate(Object *ob)
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);
}
@@ -1127,7 +1127,7 @@ static bool vgroup_normalize(Object *ob)
if (weight_max > 0.0f) {
for (i = 0; i < dvert_tot; i++) {
-
+
/* in case its not selected */
if (!(dv = dvert_array[i])) {
continue;
@@ -1136,7 +1136,7 @@ static bool vgroup_normalize(Object *ob)
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);
}
@@ -1257,27 +1257,6 @@ static void getVerticalAndHorizontalChange(
changes[index][1] = len_v3v3(projA, projB);
}
-/* I need the derived mesh to be forgotten so the positions are recalculated
- * with weight changes (see dm_deform_recalc) */
-static void dm_deform_clear(DerivedMesh *dm, Object *ob)
-{
- if (ob->derivedDeform && (ob->derivedDeform) == dm) {
- ob->derivedDeform->needsFree = 1;
- ob->derivedDeform->release(ob->derivedDeform);
- ob->derivedDeform = NULL;
- }
- else if (dm) {
- dm->needsFree = 1;
- dm->release(dm);
- }
-}
-
-/* recalculate the deformation */
-static DerivedMesh *dm_deform_recalc(Depsgraph *depsgraph, Scene *scene, Object *ob)
-{
- return mesh_get_derived_deform(depsgraph, scene, ob, CD_MASK_BAREMESH);
-}
-
/* by changing nonzero weights, try to move a vertex in me->mverts with index 'index' to
* distToBe distance away from the provided plane strength can change distToBe so that it moves
* towards distToBe by that percentage cp changes how much the weights are adjusted
@@ -1291,7 +1270,7 @@ 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)
{
- DerivedMesh *dm;
+ Mesh *me_deform;
MDeformWeight *dw;
MVert m;
MDeformVert *dvert = me->dvert + index;
@@ -1315,8 +1294,8 @@ static void moveCloserToDistanceFromPlane(
float originalDistToBe = distToBe;
do {
wasChange = false;
- dm = dm_deform_recalc(depsgraph, scene, ob);
- dm->getVert(dm, index, &m);
+ 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;
@@ -1334,8 +1313,10 @@ static void moveCloserToDistanceFromPlane(
continue;
}
for (k = 0; k < 2; k++) {
- if (dm) {
- dm_deform_clear(dm, ob); dm = NULL;
+ 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) {
@@ -1353,8 +1334,8 @@ static void moveCloserToDistanceFromPlane(
if (dw->weight > 1) {
dw->weight = 1;
}
- dm = dm_deform_recalc(depsgraph, scene, ob);
- dm->getVert(dm, index, &m);
+ 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) {
@@ -1448,8 +1429,10 @@ static void moveCloserToDistanceFromPlane(
if (oldw == dw->weight) {
wasChange = false;
}
- if (dm) {
- dm_deform_clear(dm, ob); dm = NULL;
+ 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) ==
@@ -1461,7 +1444,7 @@ static void moveCloserToDistanceFromPlane(
MEM_freeN(dwIndices);
}
-/* this is used to try to smooth a surface by only adjusting the nonzero weights of a vertex
+/* 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)
{
@@ -1481,19 +1464,18 @@ static void vgroup_fix(const bContext *C, Scene *scene, Object *ob, float distTo
MVert *p = MEM_callocN(sizeof(MVert) * (count), "deformedPoints");
int k;
- DerivedMesh *dm = mesh_get_derived_deform(depsgraph, scene, ob, CD_MASK_BAREMESH);
+ Mesh *me_deform = mesh_get_eval_deform(depsgraph, scene, ob, CD_MASK_BAREMESH);
k = count;
while (k--) {
- dm->getVert(dm, verts[k], &m);
- p[k] = m;
+ 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);
- dm->getVert(dm, i, &m);
+ m = me_deform->mvert[i];
sub_v3_v3v3(norm, m.co, coord);
mag = normalize_v3(norm);
if (mag) { /* zeros fix */
@@ -2642,7 +2624,7 @@ static int vertex_group_add_exec(bContext *C, wmOperator *UNUSED(op))
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
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;
}
@@ -2652,7 +2634,7 @@ void OBJECT_OT_vertex_group_add(wmOperatorType *ot)
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;
@@ -2675,7 +2657,7 @@ static int vertex_group_remove_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
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;
}
@@ -2685,7 +2667,7 @@ void OBJECT_OT_vertex_group_remove(wmOperatorType *ot)
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;
@@ -2705,11 +2687,11 @@ static int vertex_group_assign_exec(bContext *C, wmOperator *UNUSED(op))
{
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, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
-
+
return OPERATOR_FINISHED;
}
@@ -2719,7 +2701,7 @@ void OBJECT_OT_vertex_group_assign(wmOperatorType *ot)
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;
@@ -2737,7 +2719,7 @@ 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);
-
+
/* assign selection to new group */
return vertex_group_assign_exec(C, op);
}
@@ -2748,11 +2730,11 @@ void OBJECT_OT_vertex_group_assign_new(wmOperatorType *ot)
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
@@ -2819,6 +2801,7 @@ static int vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
vgroup_select_verts(ob, 1);
+ DEG_id_tag_update(ob->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
return OPERATOR_FINISHED;
@@ -2844,6 +2827,7 @@ static int vertex_group_deselect_exec(bContext *C, wmOperator *UNUSED(op))
Object *ob = ED_object_context(C);
vgroup_select_verts(ob, 0);
+ DEG_id_tag_update(ob->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
return OPERATOR_FINISHED;
@@ -2894,7 +2878,7 @@ void OBJECT_OT_vertex_group_copy(wmOperatorType *ot)
static int vertex_group_levels_exec(bContext *C, wmOperator *op)
{
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");
@@ -2904,11 +2888,11 @@ static int vertex_group_levels_exec(bContext *C, wmOperator *op)
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, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
-
+
return OPERATOR_FINISHED;
}
@@ -2918,14 +2902,14 @@ void OBJECT_OT_vertex_group_levels(wmOperatorType *ot)
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);
@@ -3014,7 +2998,7 @@ 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");
@@ -3026,17 +3010,17 @@ static int vertex_group_fix_exec(bContext *C, wmOperator *op)
}
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, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
-
+
return OPERATOR_FINISHED;
}
@@ -3047,11 +3031,11 @@ void OBJECT_OT_vertex_group_fix(wmOperatorType *ot)
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);
@@ -3449,16 +3433,16 @@ static int set_active_group_exec(bContext *C, wmOperator *op)
}
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;
@@ -3583,7 +3567,7 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op)
BLI_assert(sort_map_update[ob->actdef] >= 0);
ob->actdef = sort_map_update[ob->actdef];
-
+
MEM_freeN(sort_map_update);
return OPERATOR_FINISHED;
@@ -3651,7 +3635,7 @@ static int vertex_group_sort_exec(bContext *C, wmOperator *op)
vgroup_sort_bone_hierarchy(ob, NULL);
break;
}
-
+
/*remap vgroup data to map to correct names*/
ret = vgroup_do_remap(ob, name_array, op);
diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c
index 6dee6825b31..7f74dd4666a 100644
--- a/source/blender/editors/physics/dynamicpaint_ops.c
+++ b/source/blender/editors/physics/dynamicpaint_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -102,7 +102,7 @@ void DPAINT_OT_surface_slot_add(wmOperatorType *ot)
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;
@@ -150,7 +150,7 @@ void DPAINT_OT_surface_slot_remove(wmOperatorType *ot)
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;
@@ -181,7 +181,7 @@ static int type_toggle_exec(bContext *C, wmOperator *op)
if (!dynamicPaint_createType(pmd, type, scene))
return OPERATOR_CANCELLED;
}
-
+
/* update dependency */
DEG_id_tag_update(&cObject->id, OB_RECALC_DATA);
DEG_relations_tag_update(CTX_data_main(C));
@@ -198,14 +198,14 @@ void DPAINT_OT_type_toggle(wmOperatorType *ot)
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;
@@ -225,7 +225,7 @@ static int output_toggle_exec(bContext *C, wmOperator *op)
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
@@ -235,7 +235,7 @@ static int output_toggle_exec(bContext *C, wmOperator *op)
if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
if (!exists)
ED_mesh_color_add(ob->data, name, true);
- else
+ else
ED_mesh_color_remove_named(ob->data, name);
}
/* Vertex Weight Layer */
@@ -265,14 +265,14 @@ void DPAINT_OT_output_toggle(wmOperatorType *ot)
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", "");
}
@@ -316,7 +316,7 @@ static void dpaint_bake_endjob(void *customdata)
G.is_rendering = false;
BKE_spacedata_draw_locks(false);
- WM_set_locked_interface(G.main->wm.first, false);
+ WM_set_locked_interface(G_MAIN->wm.first, false);
/* Bake was successful:
* Report for ended bake and how long it took */
@@ -509,7 +509,7 @@ void DPAINT_OT_bake(wmOperatorType *ot)
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 681ac75e847..ac031079434 100644
--- a/source/blender/editors/physics/particle_boids.c
+++ b/source/blender/editors/physics/particle_boids.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -78,7 +78,7 @@ static int rule_add_exec(bContext *C, wmOperator *op)
BLI_addtail(&state->rules, rule);
DEG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
-
+
return OPERATOR_FINISHED;
}
@@ -88,14 +88,14 @@ void BOID_OT_rule_add(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-
+
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))
@@ -135,7 +135,7 @@ void BOID_OT_rule_del(wmOperatorType *ot)
ot->name = "Remove Boid Rule";
ot->idname = "BOID_OT_rule_del";
ot->description = "Delete current boid rule";
-
+
/* api callbacks */
ot->exec = rule_del_exec;
@@ -153,7 +153,7 @@ static int rule_move_up_exec(bContext *C, wmOperator *UNUSED(op))
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) {
@@ -164,7 +164,7 @@ static int rule_move_up_exec(bContext *C, wmOperator *UNUSED(op))
break;
}
}
-
+
return OPERATOR_FINISHED;
}
@@ -175,7 +175,7 @@ void BOID_OT_rule_move_up(wmOperatorType *ot)
ot->idname = "BOID_OT_rule_move_up";
ot->exec = rule_move_up_exec;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
}
@@ -189,7 +189,7 @@ static int rule_move_down_exec(bContext *C, wmOperator *UNUSED(op))
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) {
@@ -200,7 +200,7 @@ static int rule_move_down_exec(bContext *C, wmOperator *UNUSED(op))
break;
}
}
-
+
return OPERATOR_FINISHED;
}
@@ -211,7 +211,7 @@ void BOID_OT_rule_move_down(wmOperatorType *ot)
ot->idname = "BOID_OT_rule_move_down";
ot->exec = rule_move_down_exec;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
}
@@ -244,10 +244,10 @@ void BOID_OT_state_add(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
}
@@ -281,7 +281,7 @@ static int state_del_exec(bContext *C, wmOperator *UNUSED(op))
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
-
+
return OPERATOR_FINISHED;
}
@@ -291,7 +291,7 @@ void BOID_OT_state_del(wmOperatorType *ot)
ot->name = "Remove Boid State";
ot->idname = "BOID_OT_state_del";
ot->description = "Delete current boid state";
-
+
/* api callbacks */
ot->exec = state_del_exec;
@@ -311,7 +311,7 @@ static int state_move_up_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
boids = part->boids;
-
+
for (state = boids->states.first; state; state=state->next) {
if (state->flag & BOIDSTATE_CURRENT && state->prev) {
BLI_remlink(&boids->states, state);
@@ -319,7 +319,7 @@ static int state_move_up_exec(bContext *C, wmOperator *UNUSED(op))
break;
}
}
-
+
return OPERATOR_FINISHED;
}
@@ -330,7 +330,7 @@ void BOID_OT_state_move_up(wmOperatorType *ot)
ot->idname = "BOID_OT_state_move_up";
ot->exec = state_move_up_exec;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
}
@@ -346,7 +346,7 @@ static int state_move_down_exec(bContext *C, wmOperator *UNUSED(op))
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);
@@ -355,7 +355,7 @@ static int state_move_down_exec(bContext *C, wmOperator *UNUSED(op))
break;
}
}
-
+
return OPERATOR_FINISHED;
}
@@ -366,8 +366,7 @@ void BOID_OT_state_move_down(wmOperatorType *ot)
ot->idname = "BOID_OT_state_move_down";
ot->exec = state_move_down_exec;
-
+
/* 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 f65e598e204..f4777eea999 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -49,16 +49,20 @@
#include "BLI_string.h"
#include "BLI_kdtree.h"
#include "BLI_rand.h"
+#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
#include "BKE_object.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
#include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
#include "BKE_particle.h"
#include "BKE_report.h"
+#include "BKE_scene.h"
#include "BKE_bvhutils.h"
#include "BKE_pointcache.h"
@@ -75,18 +79,22 @@
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
+#include "GPU_state.h"
#include "UI_resources.h"
#include "WM_api.h"
#include "WM_types.h"
#include "WM_message.h"
+#include "WM_toolsystem.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "DEG_depsgraph_query.h"
+#include "PIL_time_utildefines.h"
+
#include "physics_intern.h"
#include "particle_edit_utildefines.h"
@@ -113,7 +121,7 @@ int PE_hair_poll(bContext *C)
if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT)) {
return 0;
}
- edit= PE_get_current(scene, ob);
+ edit = PE_get_current(scene, ob);
return (edit && edit->psys);
}
@@ -187,7 +195,7 @@ static float pe_brush_size_get(const Scene *UNUSED(scene), ParticleBrushData *br
// 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;
}
@@ -209,6 +217,31 @@ PTCacheEdit *PE_get_current_from_psys(ParticleSystem *psys)
return NULL;
}
+/* NOTE: Similar to creation of edit, but only updates pointers in the
+ * existing struct.
+ */
+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++;
+ }
+}
+
/* 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
@@ -257,8 +290,11 @@ static PTCacheEdit *pe_get_current(
edit = pid->cache->edit;
}
else {
- if (create && !psys->edit && psys->flag & PSYS_HAIR_DONE)
- PE_create_particle_edit(depsgraph, scene, ob, NULL, psys);
+ if (create && !psys->edit) {
+ if (psys->flag & PSYS_HAIR_DONE) {
+ PE_create_particle_edit(depsgraph, scene, ob, NULL, psys);
+ }
+ }
edit = psys->edit;
}
}
@@ -291,8 +327,16 @@ static PTCacheEdit *pe_get_current(
}
}
- if (edit)
+ 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);
@@ -347,7 +391,7 @@ static int pe_x_mirror(Object *ob)
{
if (ob->type == OB_MESH)
return (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X);
-
+
return 0;
}
@@ -355,16 +399,19 @@ static int pe_x_mirror(Object *ob)
typedef struct PEData {
ViewContext vc;
-
+
const bContext *context;
+ Main *bmain;
Scene *scene;
ViewLayer *view_layer;
Object *ob;
- DerivedMesh *dm;
+ Mesh *mesh;
PTCacheEdit *edit;
BVHTreeFromMesh shape_bvh;
Depsgraph *depsgraph;
+ RNG *rng;
+
const int *mval;
rcti *rect;
float rad;
@@ -393,6 +440,7 @@ static void PE_set_data(bContext *C, PEData *data)
{
memset(data, 0, sizeof(*data));
+ 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);
@@ -422,15 +470,15 @@ static void PE_set_view3d_data(bContext *C, PEData *data)
static bool PE_create_shape_tree(PEData *data, Object *shapeob)
{
- DerivedMesh *dm = shapeob->derivedFinal;
-
+ Mesh *mesh = BKE_object_get_evaluated_mesh(data->depsgraph, shapeob);
+
memset(&data->shape_bvh, 0, sizeof(data->shape_bvh));
-
- if (!dm) {
+
+ if (!mesh) {
return false;
}
-
- return (bvhtree_from_mesh_get(&data->shape_bvh, dm, 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)
@@ -438,6 +486,22 @@ static void PE_free_shape_tree(PEData *data)
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 ^= GET_UINT_FROM_POINTER(data->ob);
+ rng_seed ^= GET_UINT_FROM_POINTER(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;
+ }
+}
+
/*************************** selection utilities *******************************/
static bool key_test_depth(PEData *data, const float co[3], const int screen_co[2])
@@ -500,7 +564,7 @@ static bool key_inside_circle(PEData *data, float rad, const float co[3], float
return 1;
}
-
+
return 0;
}
@@ -539,7 +603,7 @@ static bool point_is_selected(PTCacheEditPoint *point)
LOOP_SELECTED_KEYS {
return 1;
}
-
+
return 0;
}
@@ -635,61 +699,87 @@ static void foreach_mouse_hit_point(PEData *data, ForPointFunc func, int selecte
}
}
-static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected)
+typedef struct KeyIterData {
+ PEData *data;
+ PTCacheEdit *edit;
+ int selected;
+ ForKeyMatFunc 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 = NULL;
- ParticleEditSettings *pset= PE_settings(data->scene);
- POINT_P; KEY_K;
+ 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 (edit->psys)
- psmd= psys_get_modifier(data->ob, edit->psys);
-
- /* 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) {
- if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) {
- if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) {
- psys_mat_hair_to_global(data->ob, psmd->dm_final, psys->part->from, psys->particles + p, mat);
- invert_m4_m4(imat, mat);
- }
-
- func(data, mat, imat, p, point->totkey-1, key);
+ 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) {
+ if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) {
+ 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);
}
}
}
- else {
- /* do all keys */
- LOOP_VISIBLE_KEYS {
- if (selected==0 || key->flag & PEK_SELECT) {
- if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) {
- if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) {
- psys_mat_hair_to_global(data->ob, psmd->dm_final, psys->part->from, psys->particles + p, mat);
- invert_m4_m4(imat, mat);
- }
-
- func(data, mat, imat, p, k, key);
+ }
+ else {
+ /* do all keys */
+ PTCacheEditKey *key;
+ int k;
+ LOOP_VISIBLE_KEYS {
+ if (selected==0 || key->flag & PEK_SELECT) {
+ if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) {
+ 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);
}
}
}
}
}
+static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc 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;
+ }
+
+ 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);
+}
+
static void foreach_selected_point(PEData *data, ForPointFunc func)
{
PTCacheEdit *edit = data->edit;
@@ -753,7 +843,7 @@ static int count_selected_keys(Scene *scene, PTCacheEdit *edit)
static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
{
PTCacheEdit *edit;
- ParticleSystemModifierData *psmd;
+ ParticleSystemModifierData *psmd_eval;
KDTree *tree;
KDTreeNearest nearest;
HairKey *key;
@@ -762,10 +852,10 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
int index, totpart;
edit= psys->edit;
- psmd= psys_get_modifier(ob, psys);
+ psmd_eval = edit->psmd_eval;
totpart= psys->totpart;
- if (!psmd->dm_final)
+ if (!psmd_eval->mesh_final)
return;
tree= BLI_kdtree_new(totpart);
@@ -773,7 +863,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
/* insert particles into kd tree */
LOOP_PARTICLES {
key = pa->hair;
- psys_mat_hair_to_orco(ob, psmd->dm_final, psys->part->from, pa, mat);
+ 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_insert(tree, p, co);
@@ -784,10 +874,10 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
/* 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->dm_final, psys->part->from, pa, mat);
+ 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];
@@ -813,7 +903,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
BLI_kdtree_free(tree);
}
-static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys, ParticleData *pa, ParticleData *mpa)
+static void PE_mirror_particle(Object *ob, Mesh *mesh, ParticleSystem *psys, ParticleData *pa, ParticleData *mpa)
{
HairKey *hkey, *mhkey;
PTCacheEditPoint *point, *mpoint;
@@ -829,7 +919,7 @@ static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys
if (!mpa) {
if (!edit->mirror_cache)
PE_update_mirror_cache(ob, psys);
-
+
if (!edit->mirror_cache)
return; /* something went wrong! */
@@ -864,8 +954,8 @@ static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys
}
/* mirror positions and tags */
- psys_mat_hair_to_orco(ob, dm, psys->part->from, pa, mat);
- psys_mat_hair_to_orco(ob, dm, psys->part->from, mpa, mmat);
+ 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;
@@ -893,16 +983,16 @@ static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys
static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
{
PTCacheEdit *edit;
- ParticleSystemModifierData *psmd;
+ ParticleSystemModifierData *psmd_eval;
POINT_P;
if (!psys)
return;
edit= psys->edit;
- psmd= psys_get_modifier(ob, psys);
+ psmd_eval= edit->psmd_eval;
- if (!psmd->dm_final)
+ if (!psmd_eval->mesh_final)
return;
if (!edit->mirror_cache)
@@ -915,7 +1005,7 @@ static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
* to avoid doing mirror twice */
LOOP_POINTS {
if (point->flag & PEP_EDIT_RECALC) {
- PE_mirror_particle(ob, psmd->dm_final, psys, psys->particles + p, NULL);
+ 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;
@@ -932,110 +1022,152 @@ static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
/************************************************/
/* Edit Calculation */
/************************************************/
-/* 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);
+
+typedef struct DeflectEmitterIter {
+ Object *object;
ParticleSystem *psys;
- ParticleSystemModifierData *psmd;
- POINT_P; KEY_K;
+ 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;
- float hairimat[4][4], hairmat[4][4];
- 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;
+ 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);
- psys = edit->psys;
- psmd = psys_get_modifier(ob, psys);
-
- if (!psmd->dm_final)
- return;
+ LOOP_KEYS {
+ mul_m4_v3(hairmat, key->co);
+ }
- LOOP_EDITED_POINTS {
- psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles + p, 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_find_nearest(edit->emitter_field, key->co, NULL);
- LOOP_KEYS {
- if (k==0) {
- dist_1st = len_v3v3((key+1)->co, key->co);
- dist_1st *= dist * pset->emitterdist;
- }
- else {
- index= BLI_kdtree_find_nearest(edit->emitter_field, key->co, NULL);
-
- vec=edit->emitter_cosnos +index*6;
- nor=vec+3;
+ vec = edit->emitter_cosnos + index * 6;
+ nor = vec + 3;
- sub_v3_v3v3(dvec, key->co, vec);
+ sub_v3_v3v3(dvec, key->co, vec);
- dot=dot_v3v3(dvec, nor);
- copy_v3_v3(dvec, nor);
+ 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 {
+ if (dot > 0.0f) {
+ if (dot < dist_1st) {
normalize_v3(dvec);
- mul_v3_fl(dvec, dist_1st-dot);
+ mul_v3_fl(dvec, dist_1st - dot);
add_v3_v3(key->co, dvec);
}
- if (k==1)
- dist_1st*=1.3333f;
+ }
+ 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);
- }
+ invert_m4_m4(hairimat, hairmat);
+
+ LOOP_KEYS {
+ mul_m4_v3(hairimat, key->co);
}
}
-/* force set distances between neighboring keys */
-static void PE_apply_lengths(Scene *scene, PTCacheEdit *edit)
+
+/* 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);
- POINT_P; KEY_K;
- float dv1[3];
+ ParticleEditSettings *pset = PE_settings(scene);
+ ParticleSystem *psys;
+ const float dist = ED_view3d_select_dist_px() * 0.01f;
- if (edit==0 || (pset->flag & PE_KEEP_LENGTHS)==0)
+ if (edit == NULL || edit->psys == NULL ||
+ (pset->flag & PE_DEFLECT_EMITTER) == 0 ||
+ (edit->psys->flag & PSYS_GLOBAL_HAIR))
+ {
return;
+ }
- if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR)
+ psys = edit->psys;
+
+ if (!edit->psmd_eval->mesh_final) {
return;
+ }
- LOOP_EDITED_POINTS {
- LOOP_KEYS {
- if (k) {
- 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);
- }
+ 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);
+}
+
+typedef struct ApplyLengthsIterData {
+ 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);
}
}
}
-/* try to find a nice solution to keep distances between neighboring keys */
-static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit)
+
+/* force set distances between neighboring keys */
+static void PE_apply_lengths(Scene *scene, PTCacheEdit *edit)
{
ParticleEditSettings *pset=PE_settings(scene);
- POINT_P;
- PTCacheEditKey *key;
- int j, k;
- 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};
if (edit==0 || (pset->flag & PE_KEEP_LENGTHS)==0)
return;
@@ -1043,43 +1175,91 @@ static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit)
if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR)
return;
- LOOP_EDITED_POINTS {
- for (j=1; j<point->totkey; j++) {
- 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)));
- }
+ ApplyLengthsIterData iter_data;
+ iter_data.edit = edit;
- 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));
- }
+ 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);
+}
- if (k) {
- add_v3_v3((key-1)->co, dv1);
- }
+typedef struct IterateLengthsIterData {
+ 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;
+ }
- add_v3_v3v3(dv1, dv0, dv2);
+ 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;
+ }
+
+ 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);
+}
+
/* set current distances to be kept between neighbouting keys */
void recalc_lengths(PTCacheEdit *edit)
{
@@ -1097,14 +1277,14 @@ void recalc_lengths(PTCacheEdit *edit)
}
/* calculate a tree for finding nearest emitter's vertice */
-void recalc_emitter_field(Object *ob, ParticleSystem *psys)
+void recalc_emitter_field(Depsgraph *UNUSED(depsgraph), Object *UNUSED(ob), ParticleSystem *psys)
{
- DerivedMesh *dm=psys_get_modifier(ob, psys)->dm_final;
- PTCacheEdit *edit= psys->edit;
+ PTCacheEdit *edit = psys->edit;
+ Mesh *mesh = edit->psmd_eval->mesh_final;
float *vec, *nor;
int i, totface /*, totvert*/;
- if (!dm)
+ if (!mesh)
return;
if (edit->emitter_cosnos)
@@ -1112,7 +1292,7 @@ void recalc_emitter_field(Object *ob, ParticleSystem *psys)
BLI_kdtree_free(edit->emitter_field);
- totface=dm->getNumTessFaces(dm);
+ totface = mesh->totface;
/*totvert=dm->getNumVerts(dm);*/ /*UNSUED*/
edit->emitter_cosnos=MEM_callocN(totface*6*sizeof(float), "emitter cosnos");
@@ -1123,26 +1303,26 @@ void recalc_emitter_field(Object *ob, ParticleSystem *psys)
nor=vec+3;
for (i=0; i<totface; i++, vec+=6, nor+=6) {
- MFace *mface=dm->getTessFaceData(dm, i, CD_MFACE);
+ MFace *mface = &mesh->mface[i];
MVert *mvert;
- mvert=dm->getVertData(dm, mface->v1, CD_MVERT);
+ mvert = &mesh->mvert[mface->v1];
copy_v3_v3(vec, mvert->co);
VECCOPY(nor, mvert->no);
- mvert=dm->getVertData(dm, mface->v2, CD_MVERT);
+ mvert = &mesh->mvert[mface->v2];
add_v3_v3v3(vec, vec, mvert->co);
VECADD(nor, nor, mvert->no);
- mvert=dm->getVertData(dm, mface->v3, CD_MVERT);
+ mvert = &mesh->mvert[mface->v3];
add_v3_v3v3(vec, vec, mvert->co);
VECADD(nor, nor, mvert->no);
if (mface->v4) {
- mvert=dm->getVertData(dm, mface->v4, CD_MVERT);
+ mvert = &mesh->mvert[mface->v4];
add_v3_v3v3(vec, vec, mvert->co);
VECADD(nor, nor, mvert->no);
-
+
mul_v3_fl(vec, 0.25);
}
else
@@ -1167,7 +1347,7 @@ static void PE_update_selection(Depsgraph *depsgraph, Scene *scene, Object *ob,
LOOP_POINTS
point->flag |= PEP_EDIT_RECALC;
- /* flush edit key flag to hair key flag to preserve selection
+ /* flush edit key flag to hair key flag to preserve selection
* on save */
if (edit->psys) LOOP_POINTS {
hkey = edit->psys->particles[p].hair;
@@ -1187,27 +1367,19 @@ static void PE_update_selection(Depsgraph *depsgraph, Scene *scene, Object *ob,
DEG_id_tag_update(&ob->id, DEG_TAG_SELECT_UPDATE);
}
-void update_world_cos(Depsgraph *depsgraph, Object *ob, PTCacheEdit *edit)
+void update_world_cos(Depsgraph *UNUSED(depsgraph), Object *ob, PTCacheEdit *edit)
{
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
ParticleSystem *psys = edit->psys;
- ParticleSystem *psys_eval = NULL;
- ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
- ParticleSystemModifierData *psmd_eval = NULL;
+ ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
POINT_P; KEY_K;
float hairmat[4][4];
- if (psmd != NULL) {
- psmd_eval = (ParticleSystemModifierData *)modifiers_findByName(ob_eval, psmd->modifier.name);
- psys_eval = psmd_eval->psys;
- }
-
- if (psys == 0 || psys->edit == 0 || psmd_eval->dm_final == NULL)
+ 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_eval, psmd_eval->dm_final, psys->part->from, psys_eval->particles+p, hairmat);
+ 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);
@@ -1262,7 +1434,7 @@ static void update_velocities(PTCacheEdit *edit)
}
else {
dfra = *(key+1)->time - *(key-1)->time;
-
+
if (dfra <= 0.0f)
continue;
@@ -1312,8 +1484,6 @@ void PE_update_object(Depsgraph *depsgraph, Scene *scene, Object *ob, int usefla
if (edit->psys)
edit->psys->flag &= ~PSYS_HAIR_UPDATED;
-
- DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
/************************************************/
@@ -1452,7 +1622,7 @@ void PARTICLE_OT_select_all(wmOperatorType *ot)
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;
@@ -1512,7 +1682,7 @@ static void select_root(PEData *data, int point_index)
if (point->flag & PEP_HIDE)
return;
-
+
if (data->select_action != SEL_TOGGLE)
select_action_apply(point, key, data->select_action);
else if (key->flag & PEK_SELECT)
@@ -1550,7 +1720,7 @@ void PARTICLE_OT_select_roots(wmOperatorType *ot)
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;
@@ -1574,10 +1744,10 @@ static void select_tip(PEData *data, int point_index)
}
key = &point->keys[point->totkey - 1];
-
+
if (point->flag & PEP_HIDE)
return;
-
+
if (data->select_action != SEL_TOGGLE)
select_action_apply(point, key, data->select_action);
else if (key->flag & PEK_SELECT)
@@ -1641,8 +1811,6 @@ static int select_random_exec(bContext *C, wmOperator *op)
{
PEData data;
int type;
- Scene *scene;
- Object *ob;
/* used by LOOP_VISIBLE_POINTS, LOOP_VISIBLE_KEYS and LOOP_KEYS */
PTCacheEdit *edit;
@@ -1660,9 +1828,7 @@ static int select_random_exec(bContext *C, wmOperator *op)
PE_set_data(C, &data);
data.select_action = SEL_SELECT;
- scene = CTX_data_scene(C);
- ob = CTX_data_active_object(C);
- edit = PE_get_current(scene, ob);
+ edit = PE_get_current(data.scene, data.ob);
rng = BLI_rng_new_srandom(seed);
@@ -1749,7 +1915,7 @@ void PARTICLE_OT_select_linked(wmOperatorType *ot)
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;
@@ -1836,7 +2002,7 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, bool
ParticleEditSettings *pset= PE_settings(scene);
PTCacheEdit *edit = PE_get_current(scene, ob);
ParticleSystem *psys = edit->psys;
- ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
+ ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
POINT_P; KEY_K;
float co[3], mat[4][4];
int screen_co[2];
@@ -1856,7 +2022,7 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, bool
LOOP_VISIBLE_POINTS {
if (edit->psys && !(psys->flag & PSYS_GLOBAL_HAIR))
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles + p, mat);
+ 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 {
@@ -1957,7 +2123,7 @@ void PARTICLE_OT_hide(wmOperatorType *ot)
ot->name = "Hide Selected";
ot->idname = "PARTICLE_OT_hide";
ot->description = "Hide selected particles";
-
+
/* api callbacks */
ot->exec = hide_exec;
ot->poll = PE_poll;
@@ -2003,7 +2169,7 @@ void PARTICLE_OT_reveal(wmOperatorType *ot)
ot->name = "Reveal";
ot->idname = "PARTICLE_OT_reveal";
ot->description = "Show hidden particles";
-
+
/* api callbacks */
ot->exec = reveal_exec;
ot->poll = PE_poll;
@@ -2065,7 +2231,7 @@ void PARTICLE_OT_select_less(wmOperatorType *ot)
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;
@@ -2127,7 +2293,7 @@ void PARTICLE_OT_select_more(wmOperatorType *ot)
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;
@@ -2188,7 +2354,7 @@ static void rekey_particle(PEData *data, int pa_index)
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;
@@ -2211,7 +2377,7 @@ static int rekey_exec(bContext *C, wmOperator *op)
data.totrekey= RNA_int_get(op->ptr, "keys_number");
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);
@@ -2225,7 +2391,7 @@ void PARTICLE_OT_rekey(wmOperatorType *ot)
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;
@@ -2263,7 +2429,7 @@ static void rekey_particle_to_time(const bContext *C, Scene *scene, Object *ob,
pa->flag |= PARS_REKEY;
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);
@@ -2293,15 +2459,15 @@ static int remove_tagged_particles(Object *ob, ParticleSystem *psys, int mirror)
ParticleData *pa, *npa=0, *new_pars=0;
POINT_P;
PTCacheEditPoint *npoint=0, *new_points=0;
- ParticleSystemModifierData *psmd;
+ ParticleSystemModifierData *psmd_eval;
int i, new_totpart= psys->totpart, removed= 0;
if (mirror) {
/* mirror tags */
- psmd= psys_get_modifier(ob, psys);
+ psmd_eval = edit->psmd_eval;
LOOP_TAGGED_POINTS {
- PE_mirror_particle(ob, psmd->dm_final, psys, psys->particles + p, NULL);
+ PE_mirror_particle(ob, psmd_eval->mesh_final, psys, psys->particles + p, NULL);
}
}
@@ -2372,16 +2538,16 @@ static void remove_tagged_keys(Object *ob, ParticleSystem *psys)
HairKey *hkey, *nhkey, *new_hkeys=0;
POINT_P; KEY_K;
PTCacheEditKey *nkey, *new_keys;
- ParticleSystemModifierData *psmd;
+ ParticleSystemModifierData *psmd_eval;
short new_totkey;
if (pe_x_mirror(ob)) {
/* mirror key tags */
- psmd= psys_get_modifier(ob, psys);
+ psmd_eval = psys_get_modifier(ob, psys);
LOOP_POINTS {
LOOP_TAGGED_KEYS {
- PE_mirror_particle(ob, psmd->dm_final, psys, psys->particles + p, NULL);
+ PE_mirror_particle(ob, psmd_eval->mesh_final, psys, psys->particles + p, NULL);
break;
}
}
@@ -2422,7 +2588,7 @@ static void remove_tagged_keys(Object *ob, ParticleSystem *psys)
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 */
@@ -2441,7 +2607,7 @@ static void remove_tagged_keys(Object *ob, ParticleSystem *psys)
if (point->keys)
MEM_freeN(point->keys);
-
+
pa->hair= new_hkeys;
point->keys= new_keys;
@@ -2487,7 +2653,7 @@ static void subdivide_particle(PEData *data, int pa_index)
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;
@@ -2544,7 +2710,7 @@ static int subdivide_exec(bContext *C, wmOperator *UNUSED(op))
PE_set_data(C, &data);
foreach_point(&data, subdivide_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);
@@ -2558,7 +2724,7 @@ void PARTICLE_OT_subdivide(wmOperatorType *ot)
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;
@@ -2575,7 +2741,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
Object *ob= CTX_data_active_object(C);
PTCacheEdit *edit= PE_get_current(scene, ob);
ParticleSystem *psys = edit->psys;
- ParticleSystemModifierData *psmd;
+ ParticleSystemModifierData *psmd_eval;
KDTree *tree;
KDTreeNearest nearest[10];
POINT_P;
@@ -2586,17 +2752,17 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
edit= psys->edit;
- psmd= psys_get_modifier(ob, psys);
+ psmd_eval = edit->psmd_eval;
totremoved= 0;
do {
removed= 0;
tree=BLI_kdtree_new(psys->totpart);
-
+
/* insert particles into kd tree */
LOOP_SELECTED_POINTS {
- psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles+p, mat);
+ 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_insert(tree, p, co);
@@ -2606,7 +2772,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
/* tag particles to be removed */
LOOP_SELECTED_POINTS {
- psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles+p, mat);
+ 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);
@@ -2647,7 +2813,7 @@ void PARTICLE_OT_remove_doubles(wmOperatorType *ot)
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;
@@ -2731,13 +2897,13 @@ static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata)
immUniformColor4ub(255, 255, 255, 128);
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
+ GPU_line_smooth(true);
+ GPU_blend(true);
imm_draw_circle_wire_2d(pos, (float)x, (float)y, pe_brush_size_get(scene, brush), 40);
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
+ GPU_blend(false);
+ GPU_line_smooth(false);
immUnbindProgram();
}
@@ -2808,7 +2974,7 @@ void PARTICLE_OT_delete(wmOperatorType *ot)
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;
@@ -2827,7 +2993,7 @@ static void PE_mirror_x(
Scene *scene, Object *ob, int tagged)
{
Mesh *me= (Mesh *)(ob->data);
- ParticleSystemModifierData *psmd;
+ ParticleSystemModifierData *psmd_eval;
PTCacheEdit *edit = PE_get_current(scene, ob);
ParticleSystem *psys = edit->psys;
ParticleData *pa, *newpa, *new_pars;
@@ -2840,18 +3006,18 @@ static void PE_mirror_x(
if (psys->flag & PSYS_GLOBAL_HAIR)
return;
- psmd= psys_get_modifier(ob, psys);
- if (!psmd->dm_final)
+ psmd_eval = edit->psmd_eval;
+ if (!psmd_eval->mesh_final)
return;
- const bool use_dm_final_indices = (psys->part->use_modifier_stack && !psmd->dm_final->deformedOnly);
+ 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 DM tessface indices, we mirror final DM itself, not orig mesh. Avoids an (impossible)
- * dm -> orig -> dm tessface indices conversion... */
- mirrorfaces = mesh_get_x_mirror_faces(ob, NULL, use_dm_final_indices ? psmd->dm_final : NULL);
+ /* 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);
@@ -2865,7 +3031,7 @@ static void PE_mirror_x(
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->dm_final, psys, pa, NULL);
+ PE_mirror_particle(ob, psmd_eval->mesh_final, psys, pa, NULL);
continue;
}
else
@@ -2878,7 +3044,7 @@ static void PE_mirror_x(
}
if (newtotpart != psys->totpart) {
- MFace *mtessface = use_dm_final_indices ? psmd->dm_final->getTessFaceArray(psmd->dm_final) : me->mface;
+ 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");
@@ -2902,7 +3068,7 @@ static void PE_mirror_x(
}
edit->totpoint= psys->totpart= newtotpart;
-
+
/* create new elements */
newpa= psys->particles + totpart;
newpoint= edit->points + totpart;
@@ -2947,7 +3113,7 @@ static void PE_mirror_x(
}
else {
newpa->num_dmcache = psys_particle_dm_face_lookup(
- psmd->dm_final, psmd->dm_deformed, newpa->num, newpa->fuv, NULL);
+ psmd_eval->mesh_final, psmd_eval->mesh_original, newpa->num, newpa->fuv, NULL);
}
/* update edit key pointers */
@@ -2958,7 +3124,7 @@ static void PE_mirror_x(
}
/* map key positions as mirror over x axis */
- PE_mirror_particle(ob, psmd->dm_final, psys, pa, newpa);
+ PE_mirror_particle(ob, psmd_eval->mesh_final, psys, pa, newpa);
newpa++;
newpoint++;
@@ -2977,7 +3143,7 @@ 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);
-
+
PE_mirror_x(scene, ob, 0);
update_world_cos(CTX_data_depsgraph(C), ob, edit);
@@ -2993,7 +3159,7 @@ void PARTICLE_OT_mirror(wmOperatorType *ot)
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;
@@ -3033,8 +3199,11 @@ static void brush_cut(PEData *data, int pa_index)
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_frand() > data->cutfac) return;
+ if (BLI_rng_get_float(data->rng) > data->cutfac) {
+ return;
+ }
/* don't cut hidden */
if (edit->points[pa_index].flag & PEP_HIDE)
@@ -3052,7 +3221,7 @@ static void brush_cut(PEData *data, int pa_index)
o0= (float)data->mval[0];
o1= (float)data->mval[1];
-
+
xo0= x0 - o0;
xo1= x1 - o1;
@@ -3082,7 +3251,7 @@ static void brush_cut(PEData *data, int pa_index)
dv= v0*v0 + v1*v1;
d= (v0*xo1 - v1*xo0);
-
+
d= dv * rad2 - d*d;
if (d > 0.0f) {
@@ -3168,7 +3337,7 @@ static void brush_puff(PEData *data, int point_index)
}
if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
- psys_mat_hair_to_global(data->ob, data->dm, psys->part->from, psys->particles + point_index, mat);
+ psys_mat_hair_to_global(data->ob, data->mesh, psys->part->from, psys->particles + point_index, mat);
invert_m4_m4(imat, mat);
}
else {
@@ -3315,7 +3484,7 @@ static void BKE_brush_weight_get(PEData *data, float UNUSED(mat[4][4]), float UN
}
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)
-{
+{
if (key_index) {
float dvec[3];
@@ -3329,7 +3498,7 @@ static void brush_smooth_get(PEData *data, float mat[4][4], float UNUSED(imat[4]
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 vec[3], dvec[3];
-
+
if (key_index) {
copy_v3_v3(vec, data->vec);
mul_mat3_m4_v3(imat, vec);
@@ -3338,7 +3507,7 @@ static void brush_smooth_do(PEData *data, float UNUSED(mat[4][4]), float imat[4]
sub_v3_v3v3(dvec, vec, dvec);
mul_v3_fl(dvec, data->smoothfac);
-
+
add_v3_v3(key->co, dvec);
}
@@ -3362,37 +3531,38 @@ static void intersect_dm_quad_weights(const float v1[3], const float v2[3], cons
interp_weights_poly_v3(w, vert, 4, co);
}
-/* check intersection with a derivedmesh */
-static int particle_intersect_dm(const bContext *C, Scene *scene, Object *ob, DerivedMesh *dm,
- 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)
+/** Check intersection with an evaluated mesh. */
+static int particle_intersect_mesh(Depsgraph *depsgraph, Scene *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)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
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 (dm == NULL) {
+
+ if (mesh == NULL) {
psys_disable_all(ob);
- dm = mesh_get_derived_final(depsgraph, scene, ob, 0);
- if (dm == NULL)
- dm = mesh_get_derived_deform(depsgraph, scene, ob, 0);
+ mesh = mesh_get_eval_final(depsgraph, scene, ob, CD_MASK_BAREMESH);
+ if (mesh == NULL) {
+ mesh = mesh_get_eval_deform(depsgraph, scene, ob, CD_MASK_BAREMESH);
+ }
psys_enable_all(ob);
- if (dm == NULL)
+ if (mesh == NULL) {
return 0;
+ }
}
/* BMESH_ONLY, deform dm may not have tessface */
- DM_ensure_tessface(dm);
-
+ BKE_mesh_tessface_ensure(mesh);
+
if (pa_minmax==0) {
INIT_MINMAX(p_min, p_max);
@@ -3404,9 +3574,9 @@ static int particle_intersect_dm(const bContext *C, Scene *scene, Object *ob, De
copy_v3_v3(p_max, pa_minmax+3);
}
- totface=dm->getNumTessFaces(dm);
- mface=dm->getTessFaceDataArray(dm, CD_MFACE);
- mvert=dm->getVertDataArray(dm, CD_MVERT);
+ totface = mesh->totface;
+ mface = mesh->mface;
+ mvert = mesh->mvert;
/* lets intersect the faces */
for (i=0; i<totface; i++, mface++) {
@@ -3495,25 +3665,125 @@ static int particle_intersect_dm(const bContext *C, Scene *scene, Object *ob, De
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;
+} BrushAddCountIterData;
+
+typedef struct BrushAddCountIterTLSData {
+ 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(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);
+ }
+}
+
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;
- DerivedMesh *dm;
+ Mesh *mesh;
PTCacheEdit *edit = data->edit;
ParticleSystem *psys= edit->psys;
ParticleData *add_pars;
- ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
+ ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
ParticleSimulationData sim= {0};
ParticleEditSettings *pset= PE_settings(scene);
int i, k, n= 0, totpart= psys->totpart;
- float mco[2];
- float dmx, dmy;
- float co1[3], co2[3], min_d, imat[4][4];
+ float co1[3], imat[4][4];
float framestep, timestep;
short size= pset->brush[PE_BRUSH_ADD].size;
- short size2= size*size;
RNG *rng;
invert_m4_m4(imat, ob->obmat);
@@ -3526,67 +3796,65 @@ static int brush_add(const bContext *C, PEData *data, short number)
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;
+ sim.scene = scene;
+ sim.ob = ob;
+ sim.psys = psys;
+ sim.psmd = psmd_eval;
- timestep= psys_get_timestep(&sim);
+ timestep = psys_get_timestep(&sim);
- if (psys->part->use_modifier_stack || psmd->dm_final->deformedOnly) {
- dm = psmd->dm_final;
+ if (psys->part->use_modifier_stack || psmd_eval->mesh_final->runtime.deformed_only) {
+ mesh = psmd_eval->mesh_final;
}
else {
- dm = psmd->dm_deformed;
- }
- BLI_assert(dm);
-
- for (i=0; i<number; i++) {
- if (number>1) {
- dmx = size;
- dmy = size;
-
- /* rejection sampling to get points in circle */
- while (dmx*dmx + dmy*dmy > size2) {
- dmx= (2.0f*BLI_rng_get_float(rng) - 1.0f)*size;
- dmy= (2.0f*BLI_rng_get_float(rng) - 1.0f)*size;
- }
+ mesh = psmd_eval->mesh_original;
+ }
+ BLI_assert(mesh);
+
+ /* Calculate positions of new particles to add, based on brush interseciton
+ * with object. New particle data is assigned to a correponding 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
+ * beginnign 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;
}
- else {
- dmx = 0.0f;
- dmy = 0.0f;
- }
-
- mco[0] = data->mval[0] + dmx;
- mco[1] = data->mval[1] + dmy;
- ED_view3d_win_to_segment(depsgraph, data->vc.ar, data->vc.v3d, mco, co1, co2, true);
-
- mul_m4_v3(imat, co1);
- mul_m4_v3(imat, co2);
- min_d=2.0;
-
- /* warning, returns the derived mesh face */
- if (particle_intersect_dm(C, scene, ob, dm, 0, co1, co2, &min_d, &add_pars[n].num_dmcache, add_pars[n].fuv, 0, 0, 0, 0)) {
- if (psys->part->use_modifier_stack && !psmd->dm_final->deformedOnly) {
- add_pars[n].num = add_pars[n].num_dmcache;
- add_pars[n].num_dmcache = DMCACHE_ISCHILD;
- }
- else if (dm == psmd->dm_deformed) {
- /* Final DM is not same topology as orig mesh, we have to map num_dmcache to real final dm. */
- add_pars[n].num = add_pars[n].num_dmcache;
- add_pars[n].num_dmcache = psys_particle_dm_face_lookup(
- psmd->dm_final, psmd->dm_deformed,
- add_pars[n].num, add_pars[n].fuv, NULL);
- }
- else {
- add_pars[n].num = add_pars[n].num_dmcache;
- }
-
- if (add_pars[n].num != DMCACHE_NOTFOUND) {
- n++;
- }
+ 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];
@@ -3615,9 +3883,9 @@ static int brush_add(const bContext *C, PEData *data, short number)
/* create tree for interpolation */
if (pset->flag & PE_INTERPOLATE_ADDED && psys->totpart) {
tree=BLI_kdtree_new(psys->totpart);
-
+
for (i=0, pa=psys->particles; i<totpart; i++, pa++) {
- psys_particle_on_dm(psmd->dm_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, cur_co, 0, 0, 0, 0);
+ 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_insert(tree, i, cur_co);
}
@@ -3643,14 +3911,14 @@ static int brush_add(const bContext *C, PEData *data, short number)
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) {
@@ -3661,11 +3929,11 @@ static int brush_add(const bContext *C, PEData *data, short number)
int w, maxw;
float maxd, totw=0.0, weight[3];
- psys_particle_on_dm(psmd->dm_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, 0);
+ 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_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];
@@ -3692,10 +3960,10 @@ static int brush_add(const bContext *C, PEData *data, short number)
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);
@@ -3726,7 +3994,7 @@ static int brush_add(const bContext *C, PEData *data, short number)
}
}
for (k=0, hkey=pa->hair; k<pset->totaddkey; k++, hkey++) {
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, pa, hairmat);
+ 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);
}
@@ -3739,7 +4007,7 @@ static int brush_add(const bContext *C, PEData *data, short number)
MEM_freeN(add_pars);
BLI_rng_free(rng);
-
+
return n;
}
@@ -3769,7 +4037,7 @@ static int brush_edit_init(bContext *C, wmOperator *op)
ARegion *ar= CTX_wm_region(C);
BrushEdit *bedit;
float min[3], max[3];
-
+
if (pset->brushtype < 0)
return 0;
@@ -3791,6 +4059,7 @@ static int brush_edit_init(bContext *C, wmOperator *op)
/* cache view depths and settings for re-use */
PE_set_view3d_data(C, &bedit->data);
+ PE_create_random_generator(&bedit->data);
return 1;
}
@@ -3803,7 +4072,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
Object *ob= bedit->ob;
PTCacheEdit *edit= bedit->edit;
ParticleEditSettings *pset= PE_settings(scene);
- ParticleSystemModifierData *psmd= edit->psys ? psys_get_modifier(ob, edit->psys) : NULL;
+ ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
ParticleBrushData *brush= &pset->brush[pset->brushtype];
ARegion *ar= CTX_wm_region(C);
float vec[3], mousef[2];
@@ -3839,7 +4108,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
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;
+ PEData data = bedit->data;
data.context = C; // TODO(mai): why isnt this set in bedit->data?
view3d_operator_needs_opengl(C);
@@ -3900,7 +4169,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
case PE_BRUSH_LENGTH:
{
data.mval= mval;
-
+
data.rad= pe_brush_size_get(scene, brush);
data.growfac= brush->strength / 50.0f;
@@ -3918,7 +4187,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
case PE_BRUSH_PUFF:
{
if (edit->psys) {
- data.dm= psmd->dm_final;
+ data.mesh = psmd_eval->mesh_final;
data.mval= mval;
data.rad= pe_brush_size_get(scene, brush);
data.select= selected;
@@ -3974,7 +4243,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
case PE_BRUSH_WEIGHT:
{
if (edit->psys) {
- data.dm= psmd->dm_final;
+ data.mesh = psmd_eval->mesh_final;
data.mval= mval;
data.rad= pe_brush_size_get(scene, brush);
@@ -4004,6 +4273,8 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
if (edit->psys) {
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
+ BKE_particle_batch_cache_dirty(edit->psys, BKE_PARTICLE_BATCH_DIRTY_ALL);
+ DEG_id_tag_update(&ob->id, DEG_TAG_SELECT_UPDATE);
}
else {
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
@@ -4022,6 +4293,7 @@ static void brush_edit_exit(wmOperator *op)
{
BrushEdit *bedit= op->customdata;
+ PE_free_random_generator(&bedit->data);
MEM_freeN(bedit);
}
@@ -4062,7 +4334,7 @@ static int brush_edit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (!brush_edit_init(C, op))
return OPERATOR_CANCELLED;
-
+
brush_edit_apply_event(C, op, event);
WM_event_add_modal_handler(C, op);
@@ -4076,8 +4348,11 @@ static int brush_edit_modal(bContext *C, wmOperator *op, const wmEvent *event)
case LEFTMOUSE:
case MIDDLEMOUSE:
case RIGHTMOUSE: // XXX hardcoded
- brush_edit_exit(op);
- return OPERATOR_FINISHED;
+ if (event->val == KM_RELEASE) {
+ brush_edit_exit(op);
+ return OPERATOR_FINISHED;
+ }
+ break;
case MOUSEMOVE:
brush_edit_apply_event(C, op, event);
break;
@@ -4097,7 +4372,7 @@ void PARTICLE_OT_brush_edit(wmOperatorType *ot)
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;
@@ -4121,12 +4396,12 @@ static int shape_cut_poll(bContext *C)
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;
}
}
-
+
return false;
}
@@ -4138,9 +4413,9 @@ typedef struct PointInsideBVH {
static void point_inside_bvh_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
PointInsideBVH *data = userdata;
-
+
data->bvhdata.raycast_callback(&data->bvhdata, index, ray, hit);
-
+
if (hit->index != -1)
++data->num_hits;
}
@@ -4151,14 +4426,14 @@ 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;
-
+
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);
-
+
/* for any point inside a watertight mesh the number of hits is uneven */
return (userdata.num_hits % 2) == 1;
}
@@ -4169,17 +4444,17 @@ static void shape_cut(PEData *data, int pa_index)
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)) {
@@ -4191,10 +4466,10 @@ static void shape_cut(PEData *data, int pa_index)
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;
@@ -4230,32 +4505,32 @@ static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op))
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);
@@ -4264,20 +4539,22 @@ static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op))
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(edit->psys, BKE_PARTICLE_BATCH_DIRTY_ALL);
+ DEG_id_tag_update(&ob->id, DEG_TAG_SELECT_UPDATE);
}
else {
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
}
-
+
PE_free_shape_tree(&data);
}
-
+
pset->flag |= lock_root;
-
+
return OPERATOR_FINISHED;
}
@@ -4287,7 +4564,7 @@ void PARTICLE_OT_shape_cut(wmOperatorType *ot)
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;
@@ -4303,7 +4580,7 @@ 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 = NULL;
+ ParticleSystemModifierData *psmd_eval = NULL;
POINT_P; KEY_K;
float co[3], mat[4][4];
int ok= 0;
@@ -4311,13 +4588,13 @@ int PE_minmax(Scene *scene, ViewLayer *view_layer, float min[3], float max[3])
if (!edit) return ok;
if ((psys = edit->psys))
- psmd= psys_get_modifier(ob, psys);
+ psmd_eval = edit->psmd_eval;
else
unit_m4(mat);
LOOP_VISIBLE_POINTS {
if (psys)
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles+p, mat);
+ 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);
@@ -4337,12 +4614,30 @@ int PE_minmax(Scene *scene, ViewLayer *view_layer, float min[3], float max[3])
/************************ particle edit toggle operator ************************/
+static struct ParticleSystem *psys_eval_get(Depsgraph *depsgraph,
+ Object *object,
+ ParticleSystem *psys)
+{
+ Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
+ if (object_eval == object) {
+ return psys;
+ }
+ ParticleSystem *psys_eval = object_eval->particlesystem.first;
+ while (psys_eval != NULL) {
+ if (psys_eval->orig_psys == psys) {
+ return psys_eval;
+ }
+ psys_eval = psys_eval->next;
+ }
+ return psys_eval;
+}
+
/* initialize needed data for bake edit */
void PE_create_particle_edit(
Depsgraph *depsgraph, Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys)
{
- PTCacheEdit *edit;
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;
@@ -4355,7 +4650,7 @@ void PE_create_particle_edit(
}
/* no psmd->dm happens in case particle system modifier is not enabled */
- if (!(psys && psmd_eval && psmd_eval->dm_final) && !cache)
+ if (!(psys && psmd && psmd_eval->mesh_final) && !cache)
return;
if (cache && cache->flag & PTCACHE_DISK_CACHE)
@@ -4367,6 +4662,9 @@ void PE_create_particle_edit(
edit = (psys) ? psys->edit : cache->edit;
if (!edit) {
+ ParticleSystem *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");
@@ -4374,8 +4672,11 @@ void PE_create_particle_edit(
edit->totpoint = totpoint;
if (psys && !cache) {
- psys->edit= edit;
+ 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;
@@ -4440,12 +4741,17 @@ void PE_create_particle_edit(
psys = NULL;
}
+ /* Causes assert on startup. */
+#if 0
UI_GetThemeColor3ubv(TH_EDGE_SELECT, edit->sel_col);
UI_GetThemeColor3ubv(TH_WIRE, edit->nosel_col);
-
+#else
+ memset(edit->sel_col, 0xff, sizeof(edit->sel_col));
+ memset(edit->nosel_col, 0x00, sizeof(edit->nosel_col));
+#endif
recalc_lengths(edit);
if (psys && !cache)
- recalc_emitter_field(ob, psys);
+ recalc_emitter_field(depsgraph, ob, psys);
PE_update_object(depsgraph, scene, ob, 1);
}
@@ -4486,13 +4792,14 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *op)
PTCacheEdit *edit;
ob->mode |= mode_flag;
+
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)
- recalc_emitter_field(ob, edit->psys);
-
+ 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);
}
@@ -4508,6 +4815,8 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *op)
WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
+ WM_toolsystem_update_from_context_view3d(C);
+
return OPERATOR_FINISHED;
}
@@ -4517,7 +4826,7 @@ void PARTICLE_OT_particle_edit_toggle(wmOperatorType *ot)
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;
@@ -4533,7 +4842,7 @@ static int clear_edited_exec(bContext *C, wmOperator *UNUSED(op))
{
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);
@@ -4572,7 +4881,7 @@ void PARTICLE_OT_edited_clear(wmOperatorType *ot)
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;
@@ -4668,7 +4977,6 @@ static int unify_length_exec(bContext *C, wmOperator *UNUSED(op))
}
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);
@@ -4695,4 +5003,3 @@ void PARTICLE_OT_unify_length(struct wmOperatorType *ot)
/* 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 5199b1c54fa..fdf765e4557 100644
--- a/source/blender/editors/physics/particle_edit_undo.c
+++ b/source/blender/editors/physics/particle_edit_undo.c
@@ -44,9 +44,9 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "BKE_context.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
-#include "BKE_context.h"
#include "BKE_undo_system.h"
#include "DEG_depsgraph.h"
@@ -233,7 +233,7 @@ static bool particle_undosys_poll(struct bContext *C)
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = OBACT(view_layer);
PTCacheEdit *edit = PE_get_current(scene, ob);
-
+
return (edit != NULL);
}
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index 76308fe1fd7..2f96f4e78e6 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -33,6 +33,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_scene_types.h"
@@ -42,12 +43,13 @@
#include "BLI_utildefines.h"
#include "BLI_string.h"
+#include "BKE_bvhutils.h"
#include "BKE_context.h"
-#include "BKE_DerivedMesh.h"
-#include "BKE_cdderivedmesh.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_particle.h"
@@ -79,17 +81,18 @@ static float I[4][4] = {{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, {0.0
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);
if (!scene || !ob)
return OPERATOR_CANCELLED;
- object_add_particle_system(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);
-
+
return OPERATOR_FINISHED;
}
@@ -99,17 +102,18 @@ void OBJECT_OT_particle_system_add(wmOperatorType *ot)
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;
-
+
/* 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);
@@ -119,7 +123,7 @@ static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
mode_orig = ob->mode;
- object_remove_particle_system(scene, ob);
+ 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
@@ -134,7 +138,7 @@ static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op))
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -144,7 +148,7 @@ void OBJECT_OT_particle_system_remove(wmOperatorType *ot)
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;
@@ -192,7 +196,7 @@ static int new_particle_settings_exec(bContext *C, wmOperator *UNUSED(op))
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -202,7 +206,7 @@ void PARTICLE_OT_new(wmOperatorType *ot)
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;
@@ -240,7 +244,7 @@ static int new_particle_target_exec(bContext *C, wmOperator *UNUSED(op))
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -250,7 +254,7 @@ void PARTICLE_OT_new_target(wmOperatorType *ot)
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;
@@ -288,7 +292,7 @@ static int remove_particle_target_exec(bContext *C, wmOperator *UNUSED(op))
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
-
+
return OPERATOR_FINISHED;
}
@@ -298,7 +302,7 @@ void PARTICLE_OT_target_remove(wmOperatorType *ot)
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;
@@ -317,7 +321,7 @@ static int target_move_up_exec(bContext *C, wmOperator *UNUSED(op))
if (!psys)
return OPERATOR_CANCELLED;
-
+
pt = psys->targets.first;
for (; pt; pt=pt->next) {
if (pt->flag & PTARGET_CURRENT && pt->prev) {
@@ -329,7 +333,7 @@ static int target_move_up_exec(bContext *C, wmOperator *UNUSED(op))
break;
}
}
-
+
return OPERATOR_FINISHED;
}
@@ -338,9 +342,9 @@ 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->exec = target_move_up_exec;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
}
@@ -367,7 +371,7 @@ static int target_move_down_exec(bContext *C, wmOperator *UNUSED(op))
break;
}
}
-
+
return OPERATOR_FINISHED;
}
@@ -376,9 +380,38 @@ 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->exec = target_move_down_exec;
-
+
+ /* 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;
+
+ if (!psys)
+ return OPERATOR_CANCELLED;
+
+ psys_check_group_weights(psys->part);
+ DEG_id_tag_update(&psys->part->id, OB_RECALC_DATA | PSYS_RECALC_REDO);
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
+
+ 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->exec = dupliob_refresh_exec;
+
/* flags */
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
}
@@ -401,11 +434,12 @@ static int dupliob_move_up_exec(bContext *C, wmOperator *UNUSED(op))
BLI_remlink(&part->dupliweights, dw);
BLI_insertlinkbefore(&part->dupliweights, dw->prev, dw);
+ DEG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_REDO);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
break;
}
}
-
+
return OPERATOR_FINISHED;
}
@@ -414,9 +448,9 @@ 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->exec = dupliob_move_up_exec;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
}
@@ -440,11 +474,12 @@ static int copy_particle_dupliob_exec(bContext *C, wmOperator *UNUSED(op))
dw->flag |= PART_DUPLIW_CURRENT;
BLI_addhead(&part->dupliweights, dw);
+ DEG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_REDO);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
break;
}
}
-
+
return OPERATOR_FINISHED;
}
@@ -454,7 +489,7 @@ void PARTICLE_OT_dupliob_copy(wmOperatorType *ot)
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;
@@ -486,8 +521,9 @@ static int remove_particle_dupliob_exec(bContext *C, wmOperator *UNUSED(op))
if (dw)
dw->flag |= PART_DUPLIW_CURRENT;
+ DEG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_REDO);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -497,7 +533,7 @@ void PARTICLE_OT_dupliob_remove(wmOperatorType *ot)
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;
@@ -523,11 +559,12 @@ static int dupliob_move_down_exec(bContext *C, wmOperator *UNUSED(op))
BLI_remlink(&part->dupliweights, dw);
BLI_insertlinkafter(&part->dupliweights, dw->next, dw);
+ DEG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_REDO);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
break;
}
}
-
+
return OPERATOR_FINISHED;
}
@@ -536,9 +573,9 @@ 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->exec = dupliob_move_down_exec;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
}
@@ -564,7 +601,7 @@ static void disconnect_hair(
if (!psys->part || psys->part->type != PART_HAIR)
return;
-
+
edit = psys->edit;
point= edit ? edit->points : NULL;
@@ -574,11 +611,11 @@ static void disconnect_hair(
point++;
}
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, pa, hairmat);
+ psys_mat_hair_to_global(ob, psmd->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++;
@@ -628,9 +665,9 @@ 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->exec = disconnect_hair_exec;
-
+
/* flags */
ot->flag = OPTYPE_UNDO; /* No REGISTER, redo does not work due to missing update, see T47750. */
@@ -653,60 +690,66 @@ static bool remap_hair_emitter(
MFace *mface = NULL, *mf;
MEdge *medge = NULL, *me;
MVert *mvert;
- DerivedMesh *dm, *target_dm;
+ 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->dm_final)
+ 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->dm_final->deformedOnly) {
+
+ if (target_psmd->mesh_final->runtime.deformed_only) {
/* we don't want to mess up target_psmd->dm when converting to global coordinates below */
- dm = target_psmd->dm_final;
+ mesh = target_psmd->mesh_final;
}
else {
- dm = target_psmd->dm_deformed;
+ mesh = target_psmd->mesh_original;
}
- target_dm = target_psmd->dm_final;
- if (dm == NULL) {
+ target_mesh = target_psmd->mesh_final;
+ if (mesh == NULL) {
return false;
}
/* don't modify the original vertices */
- dm = CDDM_copy(dm);
+ BKE_id_copy_ex(
+ NULL, &mesh->id, (ID **)&mesh,
+ LIB_ID_CREATE_NO_MAIN |
+ LIB_ID_CREATE_NO_USER_REFCOUNT |
+ LIB_ID_CREATE_NO_DEG_TAG |
+ LIB_ID_COPY_NO_PREVIEW,
+ false);
/* BMESH_ONLY, deform dm may not have tessface */
- DM_ensure_tessface(dm);
+ BKE_mesh_tessface_ensure(mesh);
- numverts = dm->getNumVerts(dm);
- mvert = dm->getVertArray(dm);
+ 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 (dm->getNumTessFaces(dm) != 0) {
- mface = dm->getTessFaceArray(dm);
- bvhtree_from_mesh_get(&bvhtree, dm, BVHTREE_FROM_FACES, 2);
+ if (mesh->totface != 0) {
+ mface = mesh->mface;
+ BKE_bvhtree_from_mesh_get(&bvhtree, mesh, BVHTREE_FROM_FACES, 2);
}
- else if (dm->getNumEdges(dm) != 0) {
- medge = dm->getEdgeArray(dm);
- bvhtree_from_mesh_get(&bvhtree, dm, BVHTREE_FROM_EDGES, 2);
+ else if (mesh->totedge != 0) {
+ medge = mesh->medge;
+ BKE_bvhtree_from_mesh_get(&bvhtree, mesh, BVHTREE_FROM_EDGES, 2);
}
else {
- dm->release(dm);
+ BKE_id_free(NULL, mesh);
return false;
}
@@ -736,7 +779,7 @@ static bool remap_hair_emitter(
if (mface) {
float v[4][3];
-
+
mf = &mface[nearest.index];
copy_v3_v3(v[0], mvert[mf->v1].co);
@@ -751,7 +794,7 @@ static bool remap_hair_emitter(
tpa->foffset = 0.0f;
tpa->num = nearest.index;
- tpa->num_dmcache = psys_particle_dm_face_lookup(target_dm, dm, tpa->num, tpa->fuv, NULL);
+ tpa->num_dmcache = psys_particle_dm_face_lookup(target_mesh, mesh, tpa->num, tpa->fuv, NULL);
}
else {
me = &medge[nearest.index];
@@ -772,50 +815,50 @@ static bool remap_hair_emitter(
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_dm, target_psys->part->from, tpa, hairmat);
+ 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);
}
}
@@ -823,7 +866,7 @@ static bool remap_hair_emitter(
}
free_bvhtree_from_mesh(&bvhtree);
- dm->release(dm);
+ BKE_id_free(NULL, mesh);
psys_free_path_cache(target_psys, target_edit);
@@ -837,15 +880,15 @@ static bool connect_hair(
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;
}
@@ -888,9 +931,9 @@ 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->exec = connect_hair_exec;
-
+
/* flags */
ot->flag = OPTYPE_UNDO; /* No REGISTER, redo does not work due to missing update, see T47750. */
@@ -912,17 +955,17 @@ static void copy_particle_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;
@@ -930,7 +973,7 @@ static void copy_particle_edit(
pa = psys->particles;
LOOP_POINTS {
HairKey *hkey = pa->hair;
-
+
point->keys= MEM_dupallocN(point->keys);
LOOP_KEYS {
key->co = hkey->co;
@@ -940,34 +983,34 @@ static void copy_particle_edit(
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(ob, psys);
+ 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
*/
@@ -976,7 +1019,7 @@ static void remove_particle_systems_from_object(Object *ob_to)
modifier_free(md);
}
}
-
+
BKE_object_free_particlesystems(ob_to);
}
@@ -994,7 +1037,7 @@ static bool copy_particle_systems_to_object(const bContext *C,
ModifierData *md;
ParticleSystem *psys_start = NULL, *psys, *psys_from;
ParticleSystem **tmp_psys;
- DerivedMesh *final_dm;
+ Mesh *final_mesh;
CustomDataMask cdmask;
int i, totpsys;
@@ -1002,7 +1045,7 @@ static bool copy_particle_systems_to_object(const bContext *C,
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.
@@ -1014,9 +1057,9 @@ static bool copy_particle_systems_to_object(const bContext *C,
#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");
-
+
cdmask = 0;
for (psys_from = PSYS_FROM_FIRST, i = 0;
psys_from;
@@ -1024,46 +1067,53 @@ static bool copy_particle_systems_to_object(const bContext *C,
{
psys = BKE_object_copy_particlesystem(psys_from, 0);
tmp_psys[i] = psys;
-
+
if (psys_start == NULL)
psys_start = psys;
-
+
cdmask |= psys_emitter_customdata_mask(psys);
}
/* 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 DM (psys and their modifiers have not been appended yet) */
- final_dm = mesh_get_derived_final(depsgraph, scene, ob_to, cdmask);
-
+
+ /* 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;
- psmd->dm_final = CDDM_copy(final_dm);
- CDDM_calc_normals(psmd->dm_final);
- DM_ensure_tessface(psmd->dm_final);
-
+ BKE_id_copy_ex(
+ NULL, &final_mesh->id, (ID **)&psmd->mesh_final,
+ LIB_ID_CREATE_NO_MAIN |
+ LIB_ID_CREATE_NO_USER_REFCOUNT |
+ LIB_ID_CREATE_NO_DEG_TAG |
+ LIB_ID_COPY_NO_PREVIEW,
+ false);
+
+ 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);
}
@@ -1074,7 +1124,7 @@ static bool copy_particle_systems_to_object(const bContext *C,
}
}
MEM_freeN(tmp_psys);
-
+
/* note: do this after creating DM copies for all the particle system modifiers,
* the remapping otherwise makes final_dm invalid!
*/
@@ -1083,7 +1133,7 @@ static bool copy_particle_systems_to_object(const bContext *C,
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;
@@ -1104,14 +1154,14 @@ static bool copy_particle_systems_to_object(const bContext *C,
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 |= PSYS_RECALC_RESET;
}
-
+
#undef PSYS_FROM_FIRST
#undef PSYS_FROM_NEXT
-
+
DEG_id_tag_update(&ob_to->id, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, ob_to);
return true;
@@ -1122,11 +1172,11 @@ static int copy_particle_systems_poll(bContext *C)
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;
-
+
return true;
}
@@ -1138,10 +1188,10 @@ static int copy_particle_systems_exec(bContext *C, wmOperator *op)
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) {
@@ -1154,19 +1204,19 @@ static int copy_particle_systems_exec(bContext *C, wmOperator *op)
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;
}
@@ -1177,17 +1227,17 @@ void PARTICLE_OT_copy_particle_systems(wmOperatorType *ot)
{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");
diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c
index 541242fdc09..6cc9b9b8e4d 100644
--- a/source/blender/editors/physics/physics_fluid.c
+++ b/source/blender/editors/physics/physics_fluid.c
@@ -39,7 +39,7 @@
/* types */
#include "DNA_action_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_fluidsim_types.h"
+#include "DNA_object_fluidsim_types.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
@@ -48,6 +48,7 @@
#include "BKE_context.h"
#include "BKE_customdata.h"
#include "BKE_fluidsim.h"
+#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_report.h"
@@ -83,12 +84,12 @@ static float get_fluid_viscosity(FluidsimSettings *settings)
static float get_fluid_rate(FluidsimSettings *settings)
{
float rate = 1.0f; /* default rate if not animated... */
-
+
rate = settings->animRate;
-
+
if (rate < 0.0f)
rate = 0.0f;
-
+
return rate;
}
@@ -110,10 +111,10 @@ static float get_fluid_size_m(Scene *scene, Object *domainob, FluidsimSettings *
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;
}
}
@@ -139,9 +140,9 @@ void fluidsimGetGeometryObjFilename(Object *ob, char *dst) //, char *srcname)
typedef struct FluidAnimChannels {
int length;
-
+
double aniFrameTime;
-
+
float *timeAtFrame;
float *DomainTime;
float *DomainGravity;
@@ -150,21 +151,21 @@ typedef struct FluidAnimChannels {
typedef struct FluidObject {
struct FluidObject *next, *prev;
-
+
struct Object *object;
-
+
float *Translation;
float *Rotation;
float *Scale;
float *Active;
-
+
float *InitialVelocity;
-
+
float *AttractforceStrength;
float *AttractforceRadius;
float *VelocityforceStrength;
float *VelocityforceRadius;
-
+
float *VertexCache;
int numVerts, numTris;
} FluidObject;
@@ -176,10 +177,10 @@ typedef struct FluidObject {
// simplify channels before printing
// for API this is done anyway upon init
#if 0
-static void fluidsimPrintChannel(FILE *file, float *channel, int paramsize, char *str, int entries)
-{
+static void fluidsimPrintChannel(FILE *file, float *channel, int paramsize, char *str, int entries)
+{
int i, j;
- int channelSize = paramsize;
+ int channelSize = paramsize;
if (entries == 3) {
elbeemSimplifyChannelVec3(channel, &channelSize);
@@ -221,11 +222,11 @@ static void fluidsimPrintChannel(FILE *file, float *channel, int paramsize, char
static void init_time(FluidsimSettings *domainSettings, FluidAnimChannels *channels)
{
int i;
-
+
channels->timeAtFrame = MEM_callocN((channels->length + 1) * sizeof(float), "timeAtFrame channel");
-
+
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;
}
@@ -255,25 +256,25 @@ static void set_vertex_channel(Depsgraph *depsgraph, float *channel, float time,
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);
}
@@ -295,7 +296,7 @@ static void free_domain_channels(FluidAnimChannels *channels)
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);
@@ -309,7 +310,7 @@ static void free_all_fluidobject_channels(ListBase *fobjects)
MEM_freeN(fobj->InitialVelocity);
fobj->InitialVelocity = NULL;
}
-
+
if (fobj->AttractforceStrength) {
MEM_freeN(fobj->AttractforceStrength);
fobj->AttractforceStrength = NULL;
@@ -320,7 +321,7 @@ static void free_all_fluidobject_channels(ListBase *fobjects)
MEM_freeN(fobj->VelocityforceRadius);
fobj->VelocityforceRadius = NULL;
}
-
+
if (fobj->VertexCache) {
MEM_freeN(fobj->VertexCache);
fobj->VertexCache = NULL;
@@ -340,105 +341,105 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid
/* 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;
-
+
/* XXX: This can't be used due to an anim sys optimization that ignores recalc object animation,
* leaving it for the depgraph (this ignores object animation such as modifier properties though... :/ )
- * --> BKE_animsys_evaluate_all_animation(G.main, eval_time);
+ * --> BKE_animsys_evaluate_all_animation(CTX_data_main(C), eval_time);
* This doesn't work with drivers:
* --> BKE_animsys_evaluate_animdata(&fsDomain->id, fsDomain->adt, eval_time, ADT_RECALC_ALL);
*/
-
- /* Modifying the global scene isn't nice, but we can do it in
+
+ /* 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) > 0 ? 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) {
@@ -448,7 +449,7 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid
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->size, i, CHANNEL_VEC);
@@ -456,14 +457,14 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid
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);
}
@@ -475,72 +476,72 @@ static void export_fluid_objects(const bContext *C, ListBase *fobjects, Scene *s
{
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.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.channelSizeAttractforceRadius =
+ fsmesh.channelSizeVelocityforceStrength =
+ fsmesh.channelSizeVelocityforceRadius =
fsmesh.channelSizeAttractforceStrength = length;
-
+
fsmesh.channelAttractforceStrength = fobj->AttractforceStrength;
fsmesh.channelAttractforceRadius = fobj->AttractforceRadius;
fsmesh.channelVelocityforceStrength = fobj->VelocityforceStrength;
@@ -548,28 +549,28 @@ static void export_fluid_objects(const bContext *C, ListBase *fobjects, Scene *s
}
else {
fsmesh.channelAttractforceStrength =
- fsmesh.channelAttractforceRadius =
- fsmesh.channelVelocityforceStrength =
- fsmesh.channelVelocityforceRadius = NULL;
+ 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.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);
}
@@ -588,7 +589,7 @@ static int fluid_validate_scene(ReportList *reports, ViewLayer *view_layer, Obje
/* 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) {
@@ -600,11 +601,11 @@ static int fluid_validate_scene(ReportList *reports, ViewLayer *view_layer, Obje
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++;
@@ -612,22 +613,22 @@ static int fluid_validate_scene(ReportList *reports, ViewLayer *view_layer, Obje
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;
}
@@ -637,13 +638,13 @@ static int fluid_validate_scene(ReportList *reports, ViewLayer *view_layer, Obje
#define FLUID_SUFFIX_SURFACE "fluidsurface"
static bool fluid_init_filepaths(
- ReportList *reports, FluidsimSettings *domainSettings, Object *fsDomain,
+ 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(fsDomain);
+ 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') {
@@ -721,8 +722,8 @@ static int fluidbake_breakjob(void *customdata)
if (fb->stop && *(fb->stop))
return 1;
-
- /* this is not nice yet, need to make the jobs list template better
+
+ /* 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);
@@ -732,7 +733,7 @@ static int fluidbake_breakjob(void *customdata)
static void fluidbake_updatejob(void *customdata, float progress)
{
FluidBakeJob *fb= (FluidBakeJob *)customdata;
-
+
*(fb->do_update) = true;
*(fb->progress) = progress;
}
@@ -740,13 +741,13 @@ static void fluidbake_updatejob(void *customdata, float progress)
static void fluidbake_startjob(void *customdata, short *stop, short *do_update, float *progress)
{
FluidBakeJob *fb= (FluidBakeJob *)customdata;
-
+
fb->stop= stop;
fb->do_update = do_update;
fb->progress = progress;
-
+
G.is_break = false; /* XXX shared with render - replace with job 'stop' switch */
-
+
elbeemSimulate();
*do_update = true;
*stop = 0;
@@ -755,7 +756,7 @@ static void fluidbake_startjob(void *customdata, short *stop, short *do_update,
static void fluidbake_endjob(void *customdata)
{
FluidBakeJob *fb= (FluidBakeJob *)customdata;
-
+
if (fb->settings) {
MEM_freeN(fb->settings);
fb->settings = NULL;
@@ -766,16 +767,16 @@ static int runSimulationCallback(void *data, int status, int frame)
{
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 (fluidbake_breakjob(fb)) {
return FLUIDSIM_CBRET_ABORT;
}
-
+
return FLUIDSIM_CBRET_CONTINUE;
}
@@ -789,12 +790,12 @@ static void fluidbake_free_data(FluidAnimChannels *channels, ListBase *fobjects,
BLI_freelistN(fobjects);
MEM_freeN(fobjects);
fobjects = NULL;
-
+
if (fsset) {
MEM_freeN(fsset);
fsset = NULL;
}
-
+
if (fb) {
MEM_freeN(fb);
fb = NULL;
@@ -840,6 +841,7 @@ static void fluidsim_delete_until_lastframe(FluidsimSettings *fss, const char *r
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);
@@ -847,9 +849,9 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor
FluidsimSettings *domainSettings;
char debugStrBuffer[256];
-
+
int gridlevels = 0;
- const char *relbase= modifier_path_relbase(fsDomain);
+ 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;
@@ -862,7 +864,7 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor
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;
@@ -872,14 +874,14 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor
elbeemSimulationSettings *fsset= MEM_callocN(sizeof(elbeemSimulationSettings), "Fluid sim settings");
fb= MEM_callocN(sizeof(FluidBakeJob), "fluid bake job");
-
+
if (getenv(strEnvName)) {
int dlevel = atoi(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) {
@@ -887,30 +889,30 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor
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);
@@ -937,31 +939,31 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor
}
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(reports, domainSettings, fsDomain, targetDir, targetFile)) {
+ 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");
+ BKE_report(reports, RPT_ERROR, "Invalid object matrix");
fluidbake_free_data(channels, fobjects, fsset, fb);
return 0;
@@ -978,7 +980,7 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor
// 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;
@@ -997,21 +999,21 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor
// 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;
+ 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->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;
@@ -1039,13 +1041,13 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor
/* ******** 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);
@@ -1117,10 +1119,9 @@ void FLUID_OT_bake(wmOperatorType *ot)
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 108c033a87c..df688d90e44 100644
--- a/source/blender/editors/physics/physics_intern.h
+++ b/source/blender/editors/physics/physics_intern.h
@@ -74,7 +74,7 @@ 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 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 */
@@ -95,6 +95,7 @@ void PARTICLE_OT_dupliob_copy(struct wmOperatorType *ot);
void PARTICLE_OT_dupliob_remove(struct wmOperatorType *ot);
void PARTICLE_OT_dupliob_move_up(struct wmOperatorType *ot);
void PARTICLE_OT_dupliob_move_down(struct wmOperatorType *ot);
+void PARTICLE_OT_dupliob_refresh(struct wmOperatorType *ot);
/* particle_boids.c */
void BOID_OT_rule_add(struct wmOperatorType *ot);
diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c
index 758ef43590e..db64aa8811c 100644
--- a/source/blender/editors/physics/physics_ops.c
+++ b/source/blender/editors/physics/physics_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -85,6 +85,7 @@ static void operatortypes_particle(void)
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);
@@ -111,10 +112,10 @@ static void keymap_particle(wmKeyConfig *keyconf)
{
wmKeyMapItem *kmi;
wmKeyMap *keymap;
-
+
keymap = WM_keymap_find(keyconf, "Particle", 0, 0);
keymap->poll = PE_poll;
-
+
kmi = WM_keymap_add_item(keymap, "PARTICLE_OT_select_all", AKEY, KM_PRESS, 0, 0);
RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE);
kmi = WM_keymap_add_item(keymap, "PARTICLE_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0);
@@ -128,7 +129,9 @@ static void keymap_particle(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "PARTICLE_OT_select_linked", LKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "deselect", true);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "PARTICLE_OT_delete", XKEY, KM_PRESS, 0, 0);
+#endif
WM_keymap_add_item(keymap, "PARTICLE_OT_delete", DELKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "PARTICLE_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0);
@@ -149,7 +152,7 @@ static void keymap_particle(wmKeyConfig *keyconf)
RNA_string_set(kmi->ptr, "data_path_primary", "tool_settings.particle_edit.brush.strength");
WM_keymap_add_menu(keymap, "VIEW3D_MT_particle_specials", WKEY, KM_PRESS, 0, 0);
-
+
WM_keymap_add_item(keymap, "PARTICLE_OT_weight_set", KKEY, KM_PRESS, KM_SHIFT, 0);
ED_keymap_proportional_cycle(keyconf, keymap);
@@ -205,7 +208,7 @@ static void operatortypes_dynamicpaint(void)
//static void keymap_pointcache(wmWindowManager *wm)
//{
// wmKeyMap *keymap = WM_keymap_find(wm, "Pointcache", 0, 0);
-//
+//
// WM_keymap_add_item(keymap, "PHYSICS_OT_bake_all", AKEY, KM_PRESS, 0, 0);
// WM_keymap_add_item(keymap, "PHYSICS_OT_free_all", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
// WM_keymap_add_item(keymap, "PHYSICS_OT_bake_particle_system", PADMINUS, KM_PRESS, KM_CTRL, 0);
@@ -228,6 +231,3 @@ void ED_keymap_physics(wmKeyConfig *keyconf)
keymap_particle(keyconf);
//keymap_pointcache(keyconf);
}
-
-
-
diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c
index fdafd6c28ed..c103a2ed8fb 100644
--- a/source/blender/editors/physics/physics_pointcache.c
+++ b/source/blender/editors/physics/physics_pointcache.c
@@ -140,7 +140,7 @@ static void ptcache_job_endjob(void *customdata)
G.is_rendering = false;
BKE_spacedata_draw_locks(false);
- WM_set_locked_interface(G.main->wm.first, false);
+ WM_set_locked_interface(G_MAIN->wm.first, false);
WM_main_add_notifier(NC_SCENE | ND_FRAME, scene);
WM_main_add_notifier(NC_OBJECT | ND_POINTCACHE, job->baker->pid.ob);
@@ -164,7 +164,7 @@ static PTCacheBaker *ptcache_baker_create(bContext *C, wmOperator *op, bool all)
{
PTCacheBaker *baker = MEM_callocN(sizeof(PTCacheBaker), "PTCacheBaker");
- baker->main = CTX_data_main(C);
+ 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);
@@ -256,9 +256,9 @@ static int ptcache_free_bake_all_exec(bContext *C, wmOperator *UNUSED(op))
for (pid = pidlist.first; pid; pid = pid->next) {
ptcache_free_bake(pid->cache);
}
-
+
BLI_freelistN(&pidlist);
-
+
WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
}
FOREACH_SCENE_OBJECT_END;
@@ -274,7 +274,7 @@ void PTCACHE_OT_bake_all(wmOperatorType *ot)
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;
@@ -293,7 +293,7 @@ void PTCACHE_OT_free_bake_all(wmOperatorType *ot)
ot->name = "Free All Physics Bakes";
ot->idname = "PTCACHE_OT_free_bake_all";
ot->description = "Free 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;
@@ -309,7 +309,7 @@ static int ptcache_free_bake_exec(bContext *C, wmOperator *UNUSED(op))
Object *ob= ptr.id.data;
ptcache_free_bake(cache);
-
+
WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
return OPERATOR_FINISHED;
@@ -319,9 +319,9 @@ 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;
-
+
cache->flag |= PTCACHE_BAKED;
-
+
WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
return OPERATOR_FINISHED;
@@ -332,7 +332,7 @@ void PTCACHE_OT_bake(wmOperatorType *ot)
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;
@@ -351,7 +351,7 @@ void PTCACHE_OT_free_bake(wmOperatorType *ot)
ot->name = "Free Physics Bake";
ot->description = "Free physics bake";
ot->idname = "PTCACHE_OT_free_bake";
-
+
/* api callbacks */
ot->exec = ptcache_free_bake_exec;
ot->poll = ptcache_poll;
@@ -365,7 +365,7 @@ void PTCACHE_OT_bake_from_cache(wmOperatorType *ot)
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;
@@ -418,7 +418,7 @@ void PTCACHE_OT_add(wmOperatorType *ot)
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;
@@ -432,7 +432,7 @@ void PTCACHE_OT_remove(wmOperatorType *ot)
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;
@@ -440,4 +440,3 @@ void PTCACHE_OT_remove(wmOperatorType *ot)
/* 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 3bcc047bf5b..5704cb8fc0c 100644
--- a/source/blender/editors/physics/rigidbody_constraint.c
+++ b/source/blender/editors/physics/rigidbody_constraint.c
@@ -37,8 +37,8 @@
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_group.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_rigidbody.h"
@@ -83,17 +83,20 @@ bool ED_rigidbody_constraint_add(Main *bmain, Scene *scene, Object *ob, int type
}
/* create constraint group if it doesn't already exits */
if (rbw->constraints == NULL) {
- rbw->constraints = BKE_group_add(bmain, "RigidBodyConstraints");
+ 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);
ob->rigidbody_constraint->flag |= RBC_FLAG_NEEDS_VALIDATE;
/* add constraint to rigid body constraint group */
- BKE_group_object_add(rbw->constraints, ob);
+ BKE_collection_object_add(bmain, rbw->constraints, ob);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&rbw->constraints->id, DEG_TAG_COPY_ON_WRITE);
+
return true;
}
@@ -102,8 +105,10 @@ void ED_rigidbody_constraint_remove(Main *bmain, Scene *scene, Object *ob)
RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
BKE_rigidbody_remove_constraint(scene, ob);
- if (rbw)
- BKE_group_object_unlink(rbw->constraints, ob);
+ if (rbw) {
+ BKE_collection_object_remove(bmain, rbw->constraints, ob, false);
+ DEG_id_tag_update(&rbw->constraints->id, DEG_TAG_COPY_ON_WRITE);
+ }
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&ob->id, OB_RECALC_OB);
diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c
index 3553ffa5033..6ea0212199e 100644
--- a/source/blender/editors/physics/rigidbody_object.c
+++ b/source/blender/editors/physics/rigidbody_object.c
@@ -42,8 +42,8 @@
#include "BLT_translation.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_group.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_rigidbody.h"
@@ -109,7 +109,8 @@ bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, Re
scene->rigidbody_world = rbw;
}
if (rbw->group == NULL) {
- rbw->group = BKE_group_add(bmain, "RigidBodyWorld");
+ rbw->group = BKE_collection_add(bmain, NULL, "RigidBodyWorld");
+ id_fake_user_set(&rbw->group->id);
}
/* make rigidbody object settings */
@@ -120,21 +121,18 @@ bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, Re
ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_VALIDATE;
/* add object to rigid body group */
- BKE_group_object_add(rbw->group, ob);
+ BKE_collection_object_add(bmain, rbw->group, ob);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&rbw->group->id, DEG_TAG_COPY_ON_WRITE);
return true;
}
void ED_rigidbody_object_remove(Main *bmain, Scene *scene, Object *ob)
{
- RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
-
- BKE_rigidbody_remove_object(scene, ob);
- if (rbw)
- BKE_group_object_unlink(rbw->group, ob);
+ BKE_rigidbody_remove_object(bmain, scene, ob);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&ob->id, OB_RECALC_OB);
diff --git a/source/blender/editors/physics/rigidbody_world.c b/source/blender/editors/physics/rigidbody_world.c
index bd8505fcf15..52a20ed7cf7 100644
--- a/source/blender/editors/physics/rigidbody_world.c
+++ b/source/blender/editors/physics/rigidbody_world.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -24,7 +24,7 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
-
+
/** \file rigidbody_world.c
* \ingroup editor_physics
* \brief Rigid Body world editing operators
@@ -114,8 +114,7 @@ static int rigidbody_world_remove_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- BKE_rigidbody_free_world(rbw);
- scene->rigidbody_world = NULL;
+ BKE_rigidbody_free_world(scene);
/* done */
return OPERATOR_FINISHED;
@@ -152,14 +151,14 @@ static int rigidbody_world_export_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "No Rigid Body World to export");
return OPERATOR_CANCELLED;
}
- if (rbw->physics_world == NULL) {
+ 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->physics_world, path);
+ RB_dworld_export(rbw->shared->physics_world, path);
#endif
return OPERATOR_FINISHED;
}
@@ -174,7 +173,7 @@ static int rigidbody_world_export_invoke(bContext *C, wmOperator *op, const wmEv
// 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);
+ WM_event_add_fileselect(C, op);
return OPERATOR_RUNNING_MODAL;
}
diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h
index a1f646aefc1..77bf16f5e22 100644
--- a/source/blender/editors/render/render_intern.h
+++ b/source/blender/editors/render/render_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -98,4 +98,3 @@ void RENDER_OT_view_cancel(struct wmOperatorType *ot);
void RENDER_OT_opengl(struct wmOperatorType *ot);
#endif /* __RENDER_INTERN_H__ */
-
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 4e44c9b1185..1385baa51ad 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -272,7 +272,7 @@ static void screen_render_single_layer_set(wmOperator *op, Main *mainp, WorkSpac
RNA_string_get(op->ptr, "scene", scene_name);
scn = (Scene *)BLI_findstring(&mainp->scene, scene_name, offsetof(ID, name) + 2);
-
+
if (scn) {
/* camera switch wont have updated */
scn->r.cfra = (*scene)->r.cfra;
@@ -288,7 +288,7 @@ static void screen_render_single_layer_set(wmOperator *op, Main *mainp, WorkSpac
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;
}
@@ -314,7 +314,7 @@ static int screen_render_exec(bContext *C, wmOperator *op)
struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL;
/* Cannot do render if there is not this function. */
- if (re_type->render_to_image == NULL) {
+ if (re_type->render == NULL) {
return OPERATOR_CANCELLED;
}
@@ -332,8 +332,8 @@ static int screen_render_exec(bContext *C, wmOperator *op)
G.is_break = false;
RE_test_break_cb(re, NULL, render_break);
- ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
- BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
+ 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.
@@ -445,7 +445,7 @@ static void make_renderinfo_string(const RenderStats *rs,
/* 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);
@@ -487,7 +487,7 @@ static void image_renderinfo_cb(void *rjv, RenderStats *rs)
static void render_progress_update(void *rjv, float progress)
{
RenderJob *rj = rjv;
-
+
if (rj->progress && *rj->progress != progress) {
*rj->progress = progress;
@@ -570,14 +570,14 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec
else if (rj->image_outdated) {
/* update entire render */
rj->image_outdated = false;
- BKE_image_signal(ima, NULL, IMA_SIGNAL_COLORMANAGE);
+ 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);
@@ -596,7 +596,7 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec
{
image_buffer_rect_update(rj, rr, ibuf, &rj->iuser, renrect, viewname);
}
-
+
/* make jobs timer to send notifier */
*(rj->do_update) = true;
}
@@ -673,23 +673,23 @@ static void render_endjob(void *rjv)
* would be re-assigned. assign dummy callbacks to avoid referencing freed renderjobs bug [#24508] */
RE_InitRenderCB(rj->re);
- if (rj->main != G.main)
+ 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);
+ 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);
@@ -741,7 +741,7 @@ static void render_endjob(void *rjv)
* 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);
+ WM_set_locked_interface(G_MAIN->wm.first, false);
/* We've freed all the derived caches before rendering, which is
* effectively the same as if we re-loaded the file.
@@ -749,11 +749,11 @@ static void render_endjob(void *rjv)
* So let's not try being smart here and just reset all updated
* scene layers and use generic DAG_on_visible_update.
*/
- for (scene = G.main->scene.first; scene; scene = scene->id.next) {
+ for (scene = G_MAIN->scene.first; scene; scene = scene->id.next) {
scene->lay_updated = 0;
}
- DEG_on_visible_update(G.main, false);
+ DEG_on_visible_update(G_MAIN, false);
}
}
@@ -819,7 +819,7 @@ static void screen_render_cancel(bContext *C, wmOperator *op)
static void clean_viewport_memory_base(Base *base)
{
- if ((base->flag & BASE_VISIBLED) == 0) {
+ if ((base->flag & BASE_VISIBLE) == 0) {
return;
}
@@ -883,7 +883,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
ScrArea *sa;
/* Cannot do render if there is not this function. */
- if (re_type->render_to_image == NULL) {
+ if (re_type->render == NULL) {
return OPERATOR_CANCELLED;
}
@@ -902,14 +902,14 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
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);
@@ -930,7 +930,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
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;
@@ -1002,8 +1002,8 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
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(IMA_TYPE_R_RESULT, "Render Result");
- BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
+ 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;
@@ -1015,6 +1015,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
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;
@@ -1075,10 +1076,10 @@ 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);
-
+
if (rj)
return rj->scene;
-
+
return NULL;
}
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index bf6aa9c9675..b5c1ffc64dd 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -322,8 +322,8 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
DRW_opengl_context_enable();
GPU_offscreen_bind(oglrender->ofs, true);
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f);
+ GPU_clear(GPU_COLOR_BIT | GPU_DEPTH_BIT);
wmOrtho2(0, sizex, 0, sizey);
gpuTranslate2f(sizex / 2, sizey / 2);
@@ -404,7 +404,7 @@ static void screen_opengl_render_write(OGLRender *oglrender)
rr = RE_AcquireResultRead(oglrender->re);
BKE_image_path_from_imformat(
- name, scene->r.pic, oglrender->bmain->name, scene->r.cfra,
+ 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 */
@@ -455,7 +455,7 @@ static void add_gpencil_renderpass(const bContext *C, OGLRender *oglrender, Rend
short oldalphamode = scene->r.alphamode;
/* set alpha transparent for gp */
scene->r.alphamode = R_ALPHAPREMUL;
-
+
/* saves layer status */
short *oldsts = MEM_mallocN(BLI_listbase_count(&gpd->layers) * sizeof(short), "temp_gplayers_flag");
int i = 0;
@@ -477,7 +477,7 @@ static void add_gpencil_renderpass(const bContext *C, OGLRender *oglrender, Rend
/* render this gp layer */
screen_opengl_render_doit(C, oglrender, rr);
-
+
/* add RendePass composite */
RenderPass *rp = RE_create_gp_pass(rr, gpl->info, rv->name);
@@ -532,7 +532,7 @@ static void screen_opengl_render_apply(const bContext *C, OGLRender *oglrender)
int chanshown = sseq ? sseq->chanshown : 0;
BKE_sequencer_new_render_data(
- oglrender->bmain, scene,
+ oglrender->bmain, oglrender->depsgraph, scene,
oglrender->sizex, oglrender->sizey, 100.0f, false,
&context);
@@ -705,8 +705,8 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
oglrender->re = RE_NewSceneRender(scene);
/* create image and image user */
- oglrender->ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
- BKE_image_signal(oglrender->ima, NULL, IMA_SIGNAL_FREE);
+ 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;
@@ -943,7 +943,7 @@ static void write_result_func(TaskPool * __restrict pool,
char name[FILE_MAX];
BKE_image_path_from_imformat(name,
scene->r.pic,
- oglrender->bmain->name,
+ BKE_main_blendfile_path(oglrender->bmain),
cfra,
&scene->r.im_format,
(scene->r.scemode & R_EXTENSION) != 0,
@@ -1030,7 +1030,7 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
if (!is_movie) {
BKE_image_path_from_imformat(
- name, scene->r.pic, oglrender->bmain->name, scene->r.cfra,
+ 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)) {
@@ -1108,7 +1108,7 @@ static int screen_opengl_render_modal(bContext *C, wmOperator *op, const wmEvent
/* 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);
@@ -1138,16 +1138,16 @@ static int screen_opengl_render_invoke(bContext *C, wmOperator *op, const wmEven
if (!screen_opengl_render_anim_initialize(C, op))
return OPERATOR_CANCELLED;
}
-
+
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);
WM_event_add_modal_handler(C, op);
oglrender->timer = WM_event_add_timer(oglrender->wm, oglrender->win, TIMER, 0.01f);
-
+
return OPERATOR_RUNNING_MODAL;
}
diff --git a/source/blender/editors/render/render_ops.c b/source/blender/editors/render/render_ops.c
index 13fe40e768a..fd534dd9129 100644
--- a/source/blender/editors/render/render_ops.c
+++ b/source/blender/editors/render/render_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -52,7 +52,7 @@ void ED_operatortypes_render(void)
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);
@@ -95,4 +95,3 @@ void ED_operatortypes_render(void)
/* 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 d0390985181..04632838cf3 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -40,7 +40,7 @@
#include <unistd.h>
#else
#include <io.h>
-#endif
+#endif
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
@@ -51,6 +51,7 @@
#include "DNA_world_types.h"
#include "DNA_camera_types.h"
+#include "DNA_group_types.h"
#include "DNA_material_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
@@ -121,7 +122,7 @@ ImBuf *get_brush_icon(Brush *brush)
// 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, G.main->name);
+ BLI_path_abs(path, BKE_main_blendfile_path_from_global());
/* use default colorspaces for brushes */
brush->icon_imbuf = IMB_loadiffname(path, flags, NULL);
@@ -130,7 +131,7 @@ ImBuf *get_brush_icon(Brush *brush)
if (!(brush->icon_imbuf)) {
folder = BKE_appdir_folder_id(BLENDER_DATAFILES, "brushicons");
- BLI_make_file_string(G.main->name, 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 */
@@ -154,21 +155,21 @@ typedef struct ShaderPreview {
/* from wmJob */
void *owner;
short *stop, *do_update;
-
+
Scene *scene;
Depsgraph *depsgraph;
ID *id;
ID *parent;
MTex *slot;
-
+
/* datablocks with nodes need full copy during preview render, glsl uses it too */
Material *matcopy;
Tex *texcopy;
Lamp *lampcopy;
World *worldcopy;
-
+
float col[4]; /* active object color */
-
+
int sizex, sizey;
unsigned int *pr_rect;
int pr_method;
@@ -248,11 +249,11 @@ void ED_preview_free_dbase(void)
static Scene *preview_get_scene(Main *pr_main)
{
if (pr_main == NULL) return NULL;
-
+
return pr_main->scene.first;
}
-static const char *preview_layer_name(const char pr_type)
+static const char *preview_collection_name(const char pr_type)
{
switch (pr_type) {
case MA_FLAT:
@@ -281,19 +282,21 @@ static const char *preview_layer_name(const char pr_type)
}
}
-static void set_preview_layer(ViewLayer *view_layer, char pr_type)
+static void set_preview_collection(Scene *scene, ViewLayer *view_layer, char pr_type)
{
- LayerCollection *lc;
- const char *collection_name = preview_layer_name(pr_type);
+ LayerCollection *lc = view_layer->layer_collections.first;
+ const char *collection_name = preview_collection_name(pr_type);
- for (lc = view_layer->layer_collections.first; lc; lc = lc->next) {
- if (STREQ(lc->scene_collection->name, collection_name)) {
- lc->flag = COLLECTION_VIEWPORT | COLLECTION_RENDER;
+ 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->flag = COLLECTION_DISABLED;
+ lc->collection->flag |= COLLECTION_RESTRICT_RENDER;
}
}
+
+ BKE_layer_collection_sync(scene, view_layer);
}
static World *preview_get_localized_world(ShaderPreview *sp, World *world)
@@ -316,7 +319,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
Scene *sce;
Main *pr_main = sp->pr_main;
- memcpy(pr_main->name, bmain->name, sizeof(pr_main->name));
+ memcpy(pr_main->name, BKE_main_blendfile_path(bmain), sizeof(pr_main->name));
sce = preview_get_scene(pr_main);
if (sce) {
@@ -331,13 +334,13 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
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;
@@ -346,7 +349,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
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
@@ -364,16 +367,16 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
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 */
mat = BKE_material_localize(origmat);
sp->matcopy = mat;
BLI_addtail(&pr_main->mat, mat);
-
+
/* use current scene world to light sphere */
if (mat->pr_type == MA_SPHERE_A && sp->pr_method == PR_BUTS_RENDER) {
/* Use current scene world to light sphere. */
@@ -387,12 +390,12 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
sce->world->horg = 0.5f;
sce->world->horb = 0.5f;
}
-
+
if (sp->pr_method == PR_ICON_RENDER) {
- set_preview_layer(view_layer, MA_SPHERE_A);
+ set_preview_collection(sce, view_layer, MA_SPHERE_A);
}
else {
- set_preview_layer(view_layer, mat->pr_type);
+ set_preview_collection(sce, view_layer, mat->pr_type);
if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
@@ -403,14 +406,14 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
}
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->col, sp->col);
-
+
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);
@@ -420,21 +423,21 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
(*matar)[actcol] = mat;
}
else if (base->object->type == OB_LAMP) {
- base->flag |= BASE_VISIBLED;
+ base->flag |= BASE_VISIBLE;
}
}
}
}
else if (id_type == ID_TE) {
Tex *tex = NULL, *origtex = (Tex *)id;
-
+
if (origtex) {
tex = BKE_texture_localize(origtex);
sp->texcopy = tex;
BLI_addtail(&pr_main->tex, tex);
}
- set_preview_layer(view_layer, MA_TEXTURE);
-
+ set_preview_collection(sce, view_layer, MA_TEXTURE);
+
if (tex && tex->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
BKE_node_preview_init_tree(origtex->nodetree, sp->sizex, sp->sizey, true);
@@ -451,7 +454,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
BLI_addtail(&pr_main->lamp, la);
}
- set_preview_layer(view_layer, MA_LAMP);
+ set_preview_collection(sce, view_layer, MA_LAMP);
if (sce->world) {
/* Only use lighting from the lamp. */
@@ -460,7 +463,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
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)
@@ -483,7 +486,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
BLI_addtail(&pr_main->world, wrld);
}
- set_preview_layer(view_layer, MA_SKY);
+ set_preview_collection(sce, view_layer, MA_SKY);
sce->world = wrld;
if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) {
@@ -495,7 +498,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
return sce;
}
-
+
return NULL;
}
@@ -544,7 +547,7 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect,
}
if (rv && rv->rectf) {
-
+
if (ABS(rres.rectx - newx) < 2 && ABS(rres.recty - newy) < 2) {
newrect->xmax = max_ii(newrect->xmax, rect->xmin + rres.rectx + offx);
@@ -562,9 +565,9 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect,
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;
}
}
@@ -626,7 +629,7 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r
static void shader_preview_update(void *spv, RenderResult *UNUSED(rr), volatile struct rcti *UNUSED(rect))
{
ShaderPreview *sp = spv;
-
+
*(sp->do_update) = true;
}
@@ -642,30 +645,30 @@ static int shader_preview_break(void *spv)
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) {
Lamp *la = (Lamp *)sp->id;
-
+
if (sp->lampcopy && la->nodetree && sp->lampcopy->nodetree)
ntreeLocalSync(sp->lampcopy->nodetree, la->nodetree);
}
@@ -683,7 +686,7 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs
int sizex;
Main *pr_main = sp->pr_main;
ID *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;
@@ -700,19 +703,19 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs
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;
@@ -737,7 +740,7 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs
}
/* 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)
@@ -751,14 +754,14 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs
/* 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;
@@ -790,16 +793,16 @@ static void shader_preview_free(void *customdata)
{
ShaderPreview *sp = customdata;
Main *pr_main = sp->pr_main;
-
+
if (sp->matcopy) {
struct IDProperty *properties;
-
+
/* node previews */
shader_preview_updatejob(sp);
-
+
/* get rid of copied material */
BLI_remlink(&pr_main->mat, sp->matcopy);
-
+
BKE_material_free(sp->matcopy);
properties = IDP_GetProperties((ID *)sp->matcopy, false);
@@ -813,11 +816,11 @@ static void shader_preview_free(void *customdata)
struct IDProperty *properties;
/* node previews */
shader_preview_updatejob(sp);
-
+
/* get rid of copied texture */
BLI_remlink(&pr_main->tex, sp->texcopy);
BKE_texture_free(sp->texcopy);
-
+
properties = IDP_GetProperties((ID *)sp->texcopy, false);
if (properties) {
IDP_FreeProperty(properties);
@@ -829,11 +832,11 @@ static void shader_preview_free(void *customdata)
struct IDProperty *properties;
/* node previews */
shader_preview_updatejob(sp);
-
+
/* get rid of copied world */
BLI_remlink(&pr_main->world, sp->worldcopy);
BKE_world_free(sp->worldcopy);
-
+
properties = IDP_GetProperties((ID *)sp->worldcopy, false);
if (properties) {
IDP_FreeProperty(properties);
@@ -845,11 +848,11 @@ static void shader_preview_free(void *customdata)
struct IDProperty *properties;
/* node previews */
shader_preview_updatejob(sp);
-
+
/* get rid of copied lamp */
BLI_remlink(&pr_main->lamp, sp->lampcopy);
BKE_lamp_free(sp->lampcopy);
-
+
properties = IDP_GetProperties((ID *)sp->lampcopy, false);
if (properties) {
IDP_FreeProperty(properties);
@@ -857,7 +860,7 @@ static void shader_preview_free(void *customdata)
}
MEM_freeN(sp->lampcopy);
}
-
+
MEM_freeN(sp);
}
@@ -873,13 +876,13 @@ static void icon_copy_rect(ImBuf *ibuf, unsigned int w, unsigned int h, unsigned
/* 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);
-
- if (!ima)
+
+ if (!ima)
return;
-
+
if (ima->x > ima->y) {
scaledx = (float)w;
scaledy = ( (float)ima->y / (float)ima->x) * (float)w;
@@ -888,15 +891,15 @@ static void icon_copy_rect(ImBuf *ibuf, unsigned int w, unsigned int h, unsigned
scaledx = ( (float)ima->x / (float)ima->y) * (float)h;
scaledy = (float)h;
}
-
+
ex = (short)scaledx;
ey = (short)scaledy;
-
+
dx = (w - ex) / 2;
dy = (h - ey) / 2;
-
+
IMB_scalefastImBuf(ima, ex, ey);
-
+
/* if needed, convert to 32 bits */
if (ima->rect == NULL)
IMB_rect_from_float(ima);
@@ -914,7 +917,7 @@ static void icon_copy_rect(ImBuf *ibuf, unsigned int w, unsigned int h, unsigned
IMB_freeImBuf(ima);
}
-static void set_alpha(char *cp, int sizex, int sizey, char alpha)
+static void set_alpha(char *cp, int sizex, int sizey, char alpha)
{
int a, size = sizex * sizey;
@@ -1098,7 +1101,7 @@ static void icon_preview_endjob(void *customdata)
if (GS(ip->id->name) == ID_BR)
WM_main_add_notifier(NC_BRUSH | NA_EDITED, ip->id);
-#if 0
+#if 0
if (GS(ip->id->name) == ID_MA) {
Material *ma = (Material *)ip->id;
PreviewImage *prv_img = ma->preview;
@@ -1243,12 +1246,12 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M
if (ob && ob->totcol) copy_v4_v4(sp->col, ob->col);
else sp->col[0] = sp->col[1] = sp->col[2] = sp->col[3] = 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);
}
@@ -1257,4 +1260,3 @@ void ED_preview_kill_jobs(wmWindowManager *wm, Main *UNUSED(bmain))
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 e792de01e2c..3d67095263f 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
@@ -100,23 +100,24 @@
static int material_slot_add_exec(bContext *C, wmOperator *UNUSED(op))
{
+ Main *bmain = CTX_data_main(C);
Object *ob = ED_object_context(C);
if (!ob)
return OPERATOR_CANCELLED;
-
- BKE_object_material_slot_add(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);
}
-
+
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;
}
@@ -126,7 +127,7 @@ void OBJECT_OT_material_slot_add(wmOperatorType *ot)
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;
@@ -147,20 +148,20 @@ static int material_slot_remove_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "Unable to remove material slot in edit mode");
return OPERATOR_CANCELLED;
}
-
- BKE_object_material_slot_remove(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);
}
-
+
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
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;
}
@@ -170,7 +171,7 @@ void OBJECT_OT_material_slot_remove(wmOperatorType *ot)
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;
@@ -224,7 +225,7 @@ static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op))
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
-
+
return OPERATOR_FINISHED;
}
@@ -234,7 +235,7 @@ void OBJECT_OT_material_slot_assign(wmOperatorType *ot)
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;
@@ -302,6 +303,7 @@ static int material_slot_de_select(bContext *C, bool select)
}
}
+ DEG_id_tag_update(ob->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
return OPERATOR_FINISHED;
@@ -318,7 +320,7 @@ void OBJECT_OT_material_slot_select(wmOperatorType *ot)
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;
@@ -337,7 +339,7 @@ void OBJECT_OT_material_slot_deselect(wmOperatorType *ot)
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;
@@ -348,6 +350,7 @@ void OBJECT_OT_material_slot_deselect(wmOperatorType *ot)
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;
@@ -358,8 +361,8 @@ static int material_slot_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
if (ob != ob_iter && give_matarar(ob_iter)) {
if (ob->data != ob_iter->data)
- assign_matarar(ob_iter, matar, ob->totcol);
-
+ 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, OB_RECALC_DATA);
@@ -490,7 +493,7 @@ static int new_material_exec(bContext *C, wmOperator *UNUSED(op))
}
WM_event_add_notifier(C, NC_MATERIAL | NA_ADDED, ma);
-
+
return OPERATOR_FINISHED;
}
@@ -500,7 +503,7 @@ void MATERIAL_OT_new(wmOperatorType *ot)
ot->name = "New Material";
ot->idname = "MATERIAL_OT_new";
ot->description = "Add a new material";
-
+
/* api callbacks */
ot->exec = new_material_exec;
@@ -539,7 +542,7 @@ static int new_texture_exec(bContext *C, wmOperator *UNUSED(op))
}
WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, tex);
-
+
return OPERATOR_FINISHED;
}
@@ -549,7 +552,7 @@ void TEXTURE_OT_new(wmOperatorType *ot)
ot->name = "New Texture";
ot->idname = "TEXTURE_OT_new";
ot->description = "Add a new texture";
-
+
/* api callbacks */
ot->exec = new_texture_exec;
@@ -590,7 +593,7 @@ static int new_world_exec(bContext *C, wmOperator *UNUSED(op))
}
WM_event_add_notifier(C, NC_WORLD | NA_ADDED, wo);
-
+
return OPERATOR_FINISHED;
}
@@ -600,7 +603,7 @@ void WORLD_OT_new(wmOperatorType *ot)
ot->name = "New World";
ot->idname = "WORLD_OT_new";
ot->description = "Create a new world Data-Block";
-
+
/* api callbacks */
ot->exec = new_world_exec;
@@ -623,7 +626,7 @@ static int view_layer_add_exec(bContext *C, wmOperator *UNUSED(op))
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;
}
@@ -633,7 +636,7 @@ void SCENE_OT_view_layer_add(wmOperatorType *ot)
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;
@@ -662,7 +665,7 @@ void SCENE_OT_view_layer_remove(wmOperatorType *ot)
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;
@@ -1431,11 +1434,11 @@ static int texture_slot_move_exec(bContext *C, wmOperator *op)
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);
-
+
set_active_mtex(id, act - 1);
}
}
@@ -1444,11 +1447,11 @@ static int texture_slot_move_exec(bContext *C, wmOperator *op)
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);
-
+
set_active_mtex(id, act + 1);
}
}
@@ -1494,7 +1497,7 @@ static int copy_material_exec(bContext *C, wmOperator *UNUSED(op))
if (ma == NULL)
return OPERATOR_CANCELLED;
- copy_matcopybuf(ma);
+ copy_matcopybuf(CTX_data_main(C), ma);
return OPERATOR_FINISHED;
}
@@ -1520,7 +1523,7 @@ static int paste_material_exec(bContext *C, wmOperator *UNUSED(op))
if (ma == NULL)
return OPERATOR_CANCELLED;
- paste_matcopybuf(ma);
+ paste_matcopybuf(CTX_data_main(C), ma);
WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma);
@@ -1553,7 +1556,7 @@ void ED_render_clear_mtex_copybuf(void)
static void copy_mtex_copybuf(ID *id)
{
MTex **mtex = NULL;
-
+
switch (GS(id->name)) {
case ID_PA:
mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]);
@@ -1564,7 +1567,7 @@ static void copy_mtex_copybuf(ID *id)
default:
break;
}
-
+
if (mtex && *mtex) {
memcpy(&mtexcopybuf, *mtex, sizeof(MTex));
mtexcopied = 1;
@@ -1577,10 +1580,10 @@ static void copy_mtex_copybuf(ID *id)
static void paste_mtex_copybuf(ID *id)
{
MTex **mtex = NULL;
-
+
if (mtexcopied == 0 || mtexcopybuf.tex == NULL)
return;
-
+
switch (GS(id->name)) {
case ID_PA:
mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]);
@@ -1592,7 +1595,7 @@ static void paste_mtex_copybuf(ID *id)
BLI_assert(!"invalid id type");
return;
}
-
+
if (mtex) {
if (*mtex == NULL) {
*mtex = MEM_mallocN(sizeof(MTex), "mtex copy");
@@ -1600,9 +1603,9 @@ static void paste_mtex_copybuf(ID *id)
else if ((*mtex)->tex) {
id_us_min(&(*mtex)->tex->id);
}
-
+
memcpy(*mtex, &mtexcopybuf, sizeof(MTex));
-
+
id_us_plus((ID *)mtexcopybuf.tex);
}
}
@@ -1626,7 +1629,7 @@ static int copy_mtex_exec(bContext *C, wmOperator *UNUSED(op))
static int copy_mtex_poll(bContext *C)
{
ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
-
+
return (id != NULL);
}
@@ -1640,7 +1643,7 @@ void TEXTURE_OT_slot_copy(wmOperatorType *ot)
/* api callbacks */
ot->exec = copy_mtex_exec;
ot->poll = copy_mtex_poll;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_INTERNAL; /* no undo needed since no changes are made to the mtex */
}
@@ -1666,7 +1669,7 @@ static int paste_mtex_exec(bContext *C, wmOperator *UNUSED(op))
id = &psys->part->id;
else if (linestyle)
id = &linestyle->id;
-
+
if (id == NULL)
return OPERATOR_CANCELLED;
}
@@ -1691,4 +1694,3 @@ void TEXTURE_OT_slot_paste(wmOperatorType *ot)
/* 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 7da571f1941..97fd7295a7b 100644
--- a/source/blender/editors/render/render_update.c
+++ b/source/blender/editors/render/render_update.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
@@ -49,7 +49,6 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_icons.h"
#include "BKE_layer.h"
#include "BKE_main.h"
@@ -111,12 +110,12 @@ void ED_render_scene_update(const DEGEditorUpdateContext *update_ctx, int update
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) {
@@ -220,22 +219,22 @@ static void render_engine_flag_changed(Main *bmain, int update_flag)
bScreen *sc;
ScrArea *sa;
ARegion *ar;
-
+
for (sc = bmain->screen.first; sc; sc = sc->id.next) {
for (sa = sc->areabase.first; sa; sa = sa->next) {
if (sa->spacetype != SPACE_VIEW3D)
continue;
-
+
for (ar = sa->regionbase.first; ar; ar = ar->next) {
RegionView3D *rv3d;
-
+
if (ar->regiontype != RGN_TYPE_WINDOW)
continue;
-
+
rv3d = ar->regiondata;
if (rv3d->render_engine)
rv3d->render_engine->update_flag |= update_flag;
-
+
}
}
}
@@ -371,4 +370,3 @@ void ED_render_id_flush_update(const DEGEditorUpdateContext *update_ctx, ID *id)
break;
}
}
-
diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c
index e4bae9d78ea..12f9c8f40c1 100644
--- a/source/blender/editors/render/render_view.c
+++ b/source/blender/editors/render/render_view.c
@@ -37,6 +37,7 @@
#include "BKE_context.h"
#include "BKE_image.h"
#include "BKE_global.h"
+#include "BKE_main.h"
#include "BKE_screen.h"
#include "BKE_report.h"
@@ -104,7 +105,7 @@ static ScrArea *find_area_showing_r_result(bContext *C, Scene *scene, wmWindow *
break;
}
}
-
+
return sa;
}
@@ -131,6 +132,7 @@ 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;
@@ -139,7 +141,7 @@ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports)
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;
@@ -177,7 +179,7 @@ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports)
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);
@@ -213,7 +215,7 @@ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports)
sima = sa->spacedata.first;
/* get the correct image, and scale it */
- sima->image = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
+ 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
@@ -292,7 +294,7 @@ void RENDER_OT_view_cancel(struct wmOperatorType *ot)
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);
@@ -300,7 +302,7 @@ static int render_view_show_invoke(bContext *C, wmOperator *op, const wmEvent *e
else {
wmWindow *win, *winshow;
ScrArea *sa = find_area_showing_r_result(C, CTX_data_scene(C), &winshow);
-
+
/* 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);
@@ -312,7 +314,7 @@ static int render_view_show_invoke(bContext *C, wmOperator *op, const wmEvent *e
return OPERATOR_FINISHED;
}
}
-
+
/* determine if render already shows */
if (sa) {
/* but don't close it when rendering */
@@ -351,4 +353,3 @@ void RENDER_OT_view_show(struct wmOperatorType *ot)
ot->invoke = render_view_show_invoke;
ot->poll = ED_operator_screenactive;
}
-
diff --git a/source/blender/editors/scene/scene_edit.c b/source/blender/editors/scene/scene_edit.c
index b6608ce600f..677fc0a068e 100644
--- a/source/blender/editors/scene/scene_edit.c
+++ b/source/blender/editors/scene/scene_edit.c
@@ -116,7 +116,7 @@ bool ED_scene_delete(bContext *C, Main *bmain, wmWindow *win, Scene *scene)
static ViewLayer *scene_change_get_new_view_layer(const WorkSpace *workspace, const Scene *scene_new)
{
- ViewLayer *layer_new = BKE_workspace_view_layer_get(workspace, scene_new);
+ ViewLayer *layer_new = BKE_workspace_view_layer_exists(workspace, scene_new);
return layer_new ? layer_new : BKE_view_layer_default_view(scene_new);
}
@@ -202,10 +202,11 @@ bool ED_scene_view_layer_delete(
BLI_assert(BLI_listbase_is_empty(&scene->view_layers) == false);
ED_workspace_view_layer_unset(bmain, scene, layer, scene->view_layers.first);
- BKE_workspace_view_layer_remove_references(bmain, layer);
BKE_view_layer_free(layer);
+ BKE_workspace_view_layer_remove(bmain, layer);
+
DEG_id_tag_update(&scene->id, 0);
DEG_relations_tag_update(bmain);
WM_main_add_notifier(NC_SCENE | ND_LAYER | NA_REMOVED, scene);
diff --git a/source/blender/editors/screen/CMakeLists.txt b/source/blender/editors/screen/CMakeLists.txt
index 29b9971eabb..4be65f60b21 100644
--- a/source/blender/editors/screen/CMakeLists.txt
+++ b/source/blender/editors/screen/CMakeLists.txt
@@ -46,7 +46,9 @@ set(SRC
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
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index ad4f6b0179d..207047c2ad3 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -52,6 +52,7 @@
#include "WM_api.h"
#include "WM_types.h"
#include "WM_message.h"
+#include "WM_toolsystem.h"
#include "ED_screen.h"
#include "ED_screen_types.h"
@@ -61,6 +62,8 @@
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
#include "GPU_draw.h"
+#include "GPU_state.h"
+#include "GPU_framebuffer.h"
#include "BLF_api.h"
@@ -96,8 +99,8 @@ static void region_draw_emboss(const ARegion *ar, const rcti *scirct, int sides)
rect.ymax = scirct->ymax - ar->winrct.ymin;
/* set transp line */
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
float color[4] = {0.0f, 0.0f, 0.0f, 0.25f};
UI_GetThemeColor3fv(TH_EDITOR_OUTLINE, color);
@@ -136,7 +139,7 @@ static void region_draw_emboss(const ARegion *ar, const rcti *scirct, int sides)
immEnd();
immUnbindProgram();
- glDisable(GL_BLEND);
+ GPU_blend(false);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
@@ -225,7 +228,7 @@ void ED_area_azones_update(ScrArea *sa, const int mouse_xy[2])
if (changed) {
sa->flag &= ~AREA_FLAG_ACTIONZONES_UPDATE;
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw_no_rebuild(sa);
}
}
@@ -295,7 +298,7 @@ static void draw_azone_plus(float x1, float y1, float x2, float y2)
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- glEnable(GL_BLEND);
+ GPU_blend(true);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4f(0.8f, 0.8f, 0.8f, 0.4f);
@@ -304,13 +307,13 @@ static void draw_azone_plus(float x1, float y1, float x2, float y2)
immRectf(pos, (x1 + x2 + width) * 0.5f, (y1 + y2 - width) * 0.5f, x2 - pad, (y1 + y2 + width) * 0.5f);
immUnbindProgram();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
static void region_draw_azone_tab_plus(AZone *az)
{
- glEnable(GL_BLEND);
-
+ GPU_blend(true);
+
/* add code to draw region hidden as 'too small' */
switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT:
@@ -345,13 +348,13 @@ static void region_draw_azones(ScrArea *sa, ARegion *ar)
if (!sa)
return;
- glLineWidth(1.0f);
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ 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);
gpuPushMatrix();
gpuTranslate2f(-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;
@@ -387,7 +390,7 @@ static void region_draw_azones(ScrArea *sa, ARegion *ar)
gpuPopMatrix();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
/* Follow wmMsgNotifyFn spec */
@@ -418,6 +421,17 @@ void ED_area_do_msg_notify_tag_refresh(
ED_area_tag_refresh(sa);
}
+/**
+ * Although there's no general support for minimizing areas, the status-bar can
+ * be snapped to be only a few pixels high. A few pixels rather than 0 so it
+ * can be un-minimized again. We consider it pseudo-minimalized and don't draw
+ * it then.
+ */
+static bool area_is_pseudo_minimized(const ScrArea *area)
+{
+ return (area->winx < 3) || (area->winy < 3);
+}
+
/* only exported for WM */
void ED_region_do_layout(bContext *C, ARegion *ar)
{
@@ -429,7 +443,7 @@ void ED_region_do_layout(bContext *C, ARegion *ar)
return;
}
- if (at->do_lock) {
+ if (at->do_lock || (sa && area_is_pseudo_minimized(sa))) {
return;
}
@@ -451,19 +465,24 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
return;
ar->do_draw |= RGN_DRAWING;
-
+
/* Set viewport, scissor, ortho and ar->drawrct. */
wmPartialViewport(&ar->drawrct, &ar->winrct, &ar->drawrct);
wmOrtho2_region_pixelspace(ar);
-
+
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? */
- if (ar->headerstr) {
+ else if (ar->headerstr) {
UI_ThemeClearColor(TH_HEADER);
glClear(GL_COLOR_BUFFER_BIT);
-
+
UI_FontThemeColor(BLF_default(), TH_TEXT);
BLF_draw_default(UI_UNIT_X, 0.4f * UI_UNIT_Y, 0.0f, ar->headerstr, BLF_DRAW_STR_DUMMY_MAX);
}
@@ -480,7 +499,7 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
/* for debugging unneeded area redraws and partial redraw */
#if 0
- glEnable(GL_BLEND);
+ GPU_blend(true);
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -488,11 +507,11 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
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();
- glDisable(GL_BLEND);
+ GPU_blend(false);
#endif
memset(&ar->drawrct, 0, sizeof(ar->drawrct));
-
+
UI_blocklist_free_inactive(C, &ar->uiblocks);
if (sa) {
@@ -550,7 +569,7 @@ void ED_region_tag_redraw(ARegion *ar)
* 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;
+ ar->do_draw &= ~(RGN_DRAW_PARTIAL | RGN_DRAW_NO_REBUILD);
ar->do_draw |= RGN_DRAW;
memset(&ar->drawrct, 0, sizeof(ar->drawrct));
}
@@ -562,6 +581,15 @@ void ED_region_tag_redraw_overlay(ARegion *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));
+ }
+}
+
void ED_region_tag_refresh_ui(ARegion *ar)
{
if (ar) {
@@ -572,7 +600,7 @@ void ED_region_tag_refresh_ui(ARegion *ar)
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_PARTIAL))) {
+ 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;
@@ -583,7 +611,7 @@ void ED_region_tag_redraw_partial(ARegion *ar, const rcti *rct)
BLI_rcti_union(&ar->drawrct, rct);
}
else {
- BLI_assert((ar->do_draw & RGN_DRAW) != 0);
+ BLI_assert((ar->do_draw & (RGN_DRAW | RGN_DRAW_NO_REBUILD)) != 0);
/* Else, full redraw is already requested, nothing to do here. */
}
}
@@ -592,16 +620,25 @@ void ED_region_tag_redraw_partial(ARegion *ar, const rcti *rct)
void ED_area_tag_redraw(ScrArea *sa)
{
ARegion *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;
+
+ 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;
-
+
if (sa) {
for (ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar->regiontype == regiontype) {
@@ -620,7 +657,7 @@ void ED_area_tag_refresh(ScrArea *sa)
/* *************************************************************** */
/* use NULL to disable it */
-void ED_area_headerprint(ScrArea *sa, const char *str)
+void ED_area_status_text(ScrArea *sa, const char *str)
{
ARegion *ar;
@@ -644,13 +681,41 @@ void ED_area_headerprint(ScrArea *sa, const char *str)
}
}
+void ED_workspace_status_text(bContext *C, const char *str)
+{
+ 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;
+
+ 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;
+ }
+ }
+}
+
/* ************************************************************ */
static void area_azone_initialize(wmWindow *win, const bScreen *screen, ScrArea *sa)
{
AZone *az;
-
+
/* reinitalize entirely, regions and fullscreen add azones too */
BLI_freelistN(&sa->actionzones);
@@ -775,11 +840,11 @@ static void region_azone_tab_plus(ScrArea *sa, AZone *az, ARegion *ar)
{
AZone *azt;
int tot = 0, add;
-
+
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;
@@ -809,7 +874,7 @@ static void region_azone_tab_plus(ScrArea *sa, AZone *az, ARegion *ar)
}
/* rect needed for mouse pointer test */
BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
-}
+}
static void region_azone_edge_initialize(ScrArea *sa, ARegion *ar, AZEdge edge, const bool is_fullscreen)
{
@@ -829,7 +894,7 @@ static void region_azone_edge_initialize(ScrArea *sa, ARegion *ar, AZEdge edge,
if (is_hidden) {
region_azone_tab_plus(sa, az, ar);
}
- else {
+ else if (!is_hidden && (ar->regiontype != RGN_TYPE_HEADER)) {
region_azone_edge(az, ar);
}
}
@@ -934,6 +999,9 @@ static void region_overlap_fix(ScrArea *sa, ARegion *ar)
}
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) {
@@ -975,6 +1043,9 @@ static void region_overlap_fix(ScrArea *sa, ARegion *ar)
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)) {
@@ -987,19 +1058,22 @@ static void region_overlap_fix(ScrArea *sa, ARegion *ar)
}
/* overlapping regions only in the following restricted cases */
-static bool region_is_overlap(ScrArea *sa, ARegion *ar)
+bool ED_region_is_overlap(int spacetype, int regiontype)
{
+ if (regiontype == RGN_TYPE_HUD) {
+ return 1;
+ }
if (U.uiflag2 & USER_REGION_OVERLAP) {
- if (ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_SEQ, SPACE_IMAGE)) {
- if (ELEM(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS))
+ if (ELEM(spacetype, SPACE_VIEW3D, SPACE_SEQ, SPACE_IMAGE)) {
+ if (ELEM(regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS))
return 1;
- if (ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) {
- if (ar->regiontype == RGN_TYPE_HEADER)
+ if (ELEM(spacetype, SPACE_VIEW3D, SPACE_IMAGE)) {
+ if (regiontype == RGN_TYPE_HEADER)
return 1;
}
- else if (sa->spacetype == SPACE_SEQ) {
- if (ar->regiontype == RGN_TYPE_PREVIEW)
+ else if (spacetype == SPACE_SEQ) {
+ if (regiontype == RGN_TYPE_PREVIEW)
return 1;
}
}
@@ -1008,33 +1082,34 @@ static bool region_is_overlap(ScrArea *sa, ARegion *ar)
return 0;
}
-static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti *remainder, rcti *overlap_remainder, int quad)
+static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, rcti *overlap_remainder, int quad)
{
rcti *remainder_prev = remainder;
int prefsizex, prefsizey;
int alignment;
-
+
if (ar == NULL)
return;
-
+
/* 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;
-
+
alignment = ar->alignment & ~RGN_SPLIT_PREV;
-
+
/* set here, assuming userpref switching forces to call this again */
- ar->overlap = region_is_overlap(sa, ar);
+ ar->overlap = ED_region_is_overlap(sa->spacetype, ar->regiontype);
/* clear state flags first */
ar->flag &= ~RGN_FLAG_TOO_SMALL;
/* user errors */
- if (ar->next == NULL && alignment != RGN_ALIGN_QSPLIT)
+ if ((ar->next == NULL) && !ELEM(alignment, RGN_ALIGN_QSPLIT, RGN_ALIGN_FLOAT)) {
alignment = RGN_ALIGN_NONE;
+ }
/* prefsize, taking into account DPI */
prefsizex = UI_DPI_FAC * ((ar->sizex > 1) ? ar->sizex + 0.5f : ar->type->prefsizex);
@@ -1057,7 +1132,28 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti
/* hidden is user flag */
}
else if (alignment == RGN_ALIGN_FLOAT) {
- /* XXX floating area region, not handled yet here */
+ /**
+ * \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.
+ */
+ 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 + ar->sizex - 1;
+ ar->winrct.ymax = ar->winrct.ymin + ar->sizey - 1;
+
+ BLI_rcti_isect(&ar->winrct, &overlap_remainder_margin, &ar->winrct);
+ if (BLI_rcti_size_x(&ar->winrct) < UI_UNIT_X ||
+ BLI_rcti_size_y(&ar->winrct) < UI_UNIT_Y)
+ {
+ 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 */
@@ -1070,7 +1166,7 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti
}
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;
}
@@ -1079,9 +1175,9 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti
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;
@@ -1094,18 +1190,18 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti
}
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;
@@ -1119,7 +1215,7 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti
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);
@@ -1141,18 +1237,18 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti
}
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);
@@ -1185,25 +1281,25 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti
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) {
+ 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;
@@ -1237,10 +1333,10 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti
*overlap_remainder = *remainder;
}
- region_rect_recursive(win, sa, ar->next, remainder, overlap_remainder, quad);
+ region_rect_recursive(sa, ar->next, remainder, overlap_remainder, quad);
}
-static void area_calc_totrct(ScrArea *sa, int window_size_x, int window_size_y)
+static void area_calc_totrct(ScrArea *sa, const rcti *window_rect)
{
short px = (short)U.pixelsize;
@@ -1250,16 +1346,16 @@ static void area_calc_totrct(ScrArea *sa, int window_size_x, int window_size_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 > 0) {
+ if (sa->totrct.xmin > window_rect->xmin) {
sa->totrct.xmin += px;
}
- if (sa->totrct.xmax < (window_size_x - 1)) {
+ if (sa->totrct.xmax < (window_rect->xmax - 1)) {
sa->totrct.xmax -= px;
}
- if (sa->totrct.ymin > 0) {
+ if (sa->totrct.ymin > window_rect->ymin) {
sa->totrct.ymin += px;
}
- if (sa->totrct.ymax < (window_size_y - 1)) {
+ 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.
@@ -1309,7 +1405,7 @@ static void ed_default_handlers(wmWindowManager *wm, ScrArea *sa, ListBase *hand
if (flag & ED_KEYMAP_MARKERS) {
/* time-markers */
wmKeyMap *keymap = WM_keymap_find(wm->defaultconf, "Markers", 0, 0);
-
+
/* use a boundbox restricted map */
ARegion *ar;
/* same local check for all areas */
@@ -1332,16 +1428,16 @@ static void ed_default_handlers(wmWindowManager *wm, ScrArea *sa, ListBase *hand
}
if (flag & ED_KEYMAP_GPENCIL) {
/* grease pencil */
- /* NOTE: This is now 2 keymaps - One for basic functionality,
- * and one that only applies when "Edit Mode" is enabled
+ /* NOTE: This is now 2 keymaps - One for basic functionality,
+ * and one that only applies when "Edit Mode" is enabled
* for strokes.
*
- * For now, it's easier to just include both,
+ * For now, it's easier to just include both,
* since you hardly want one without the other.
*/
wmKeyMap *keymap_general = WM_keymap_find(wm->defaultconf, "Grease Pencil", 0, 0);
wmKeyMap *keymap_edit = WM_keymap_find(wm->defaultconf, "Grease Pencil Stroke Edit Mode", 0, 0);
-
+
WM_event_add_keymap_handler(handlers, keymap_general);
WM_event_add_keymap_handler(handlers, keymap_edit);
}
@@ -1354,20 +1450,20 @@ static void ed_default_handlers(wmWindowManager *wm, ScrArea *sa, ListBase *hand
void ED_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, ScrArea *area)
{
+ rcti rect, overlap_rect;
+ rcti window_rect;
+
if (!(area->flag & AREA_FLAG_REGION_SIZE_UPDATE)) {
return;
}
- const int size_x = WM_window_pixels_x(win);
- const int size_y = WM_window_pixels_y(win);
- rcti rect, overlap_rect;
-
- area_calc_totrct(area, size_x, size_y);
+ 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(win, area, area->regionbase.first, &rect, &overlap_rect, 0);
+ region_rect_recursive(area, area->regionbase.first, &rect, &overlap_rect, 0);
for (ARegion *ar = area->regionbase.first; ar; ar = ar->next) {
region_subwindow(ar);
@@ -1384,36 +1480,38 @@ void ED_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, ScrArea *ar
/* called in screen_refresh, or screens_init, also area size changes */
void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa)
{
- const bScreen *screen = WM_window_get_active_screen(win);
- const int window_size_x = WM_window_pixels_x(win);
- const int window_size_y = WM_window_pixels_y(win);
+ WorkSpace *workspace = WM_window_get_active_workspace(win);
+ const bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
+ Scene *scene = WM_window_get_active_scene(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(sa->type, ar->regiontype);
+ ar->type = BKE_regiontype_from_id_or_first(sa->type, ar->regiontype);
/* area sizes */
- area_calc_totrct(sa, window_size_x, window_size_y);
+ area_calc_totrct(sa, &window_rect);
/* region rect sizes */
rect = sa->totrct;
overlap_rect = rect;
- region_rect_recursive(win, sa, sa->regionbase.first, &rect, &overlap_rect, 0);
+ 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, &sa->handlers, sa->type->keymapflag);
/* checks spacedata, adds own handlers */
@@ -1426,7 +1524,7 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *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->handlers, ar->type->keymapflag);
@@ -1443,6 +1541,8 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa)
/* Some AZones use View2D data which is only updated in region init, so call that first! */
region_azones_add(screen, sa, ar, ar->alignment & ~RGN_SPLIT_PREV);
}
+
+ WM_toolsystem_refresh_screen_area(workspace, scene, sa);
}
static void region_update_rect(ARegion *ar)
@@ -1457,13 +1557,13 @@ static void region_update_rect(ARegion *ar)
/**
* Call to move a popup window (keep OpenGL context free!)
*/
-void ED_region_update_rect(bContext *UNUSED(C), ARegion *ar)
+void ED_region_update_rect(ARegion *ar)
{
region_update_rect(ar);
}
/* externally called for floating regions like menus */
-void ED_region_init(bContext *UNUSED(C), ARegion *ar)
+void ED_region_init(ARegion *ar)
{
/* refresh can be called before window opened */
region_subwindow(ar);
@@ -1477,6 +1577,9 @@ void ED_region_cursor_set(wmWindow *win, ScrArea *sa, ARegion *ar)
ar->type->cursor(win, sa, ar);
}
else {
+ if (WM_cursor_set_from_tool(win, sa, ar)) {
+ return;
+ }
WM_cursor_set(win, CURSOR_STD);
}
}
@@ -1485,10 +1588,10 @@ void ED_region_cursor_set(wmWindow *win, ScrArea *sa, ARegion *ar)
void ED_region_visibility_change_update(bContext *C, ARegion *ar)
{
ScrArea *sa = CTX_wm_area(C);
-
+
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);
}
@@ -1497,9 +1600,9 @@ void ED_region_visibility_change_update(bContext *C, ARegion *ar)
void region_toggle_hidden(bContext *C, ARegion *ar, const bool do_fade)
{
ScrArea *sa = CTX_wm_area(C);
-
+
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);
@@ -1524,7 +1627,7 @@ void ED_area_data_copy(ScrArea *sa_dst, ScrArea *sa_src, const bool do_free)
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;
@@ -1582,7 +1685,7 @@ void ED_area_swapspace(bContext *C, ScrArea *sa1, ScrArea *sa2)
/* 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);
@@ -1631,7 +1734,7 @@ void ED_area_newspace(bContext *C, ScrArea *sa, int type, const bool skip_ar_exi
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);
@@ -1647,7 +1750,7 @@ void ED_area_newspace(bContext *C, ScrArea *sa, int type, const bool skip_ar_exi
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);
@@ -1668,7 +1771,7 @@ void ED_area_newspace(bContext *C, ScrArea *sa, int type, const bool skip_ar_exi
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;
@@ -1676,18 +1779,18 @@ void ED_area_newspace(bContext *C, ScrArea *sa, int type, const bool skip_ar_exi
BLI_listbase_clear(&sl->regionbase);
}
}
-
+
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);
}
@@ -1727,7 +1830,7 @@ int ED_area_header_switchbutton(const bContext *C, uiBlock *block, int yco)
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, "type", 0, 0.0f, 0.0f, 0.0f, 0.0f, "");
+ &areaptr, "ui_type", 0, 0.0f, 0.0f, 0.0f, 0.0f, "");
return xco + 1.7 * U.widget_unit;
}
@@ -1755,46 +1858,162 @@ static ThemeColorID region_background_color_id(const bContext *C, const ARegion
static void region_clear_color(const bContext *C, const ARegion *ar, ThemeColorID colorid)
{
- if (ar->overlap) {
+ 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);
- glClearColor(back[3] * back[0], back[3] * back[1], back[3] * back[2], back[3]);
- glClear(GL_COLOR_BUFFER_BIT);
+ 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);
- glClear(GL_COLOR_BUFFER_BIT);
+ GPU_clear(GPU_COLOR_BIT);
}
}
-void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int contextnr, const bool vertical)
+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 (ar->regiontype == RGN_TYPE_TOOLS)
+ panelContext = UI_LAYOUT_TOOLBAR;
+ else
+ panelContext = UI_LAYOUT_PANEL;
+
+ panel->layout = UI_block_layout(
+ block, UI_LAYOUT_VERTICAL, panelContext,
+ style->panelspace, 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);
+}
+
+/**
+ * \param contexts: A NULL terminated array of context strings to match against.
+ * Matching against any of these strings will draw the panel.
+ * Can be NULL to skip context checks.
+ */
+void ED_region_panels_layout_ex(
+ const bContext *C, ARegion *ar,
+ const char *contexts[], int contextnr, const bool vertical)
+{
+ ar->runtime.category = NULL;
+
const WorkSpace *workspace = CTX_wm_workspace(C);
ScrArea *sa = CTX_wm_area(C);
- uiStyle *style = UI_style_get_dpi();
- uiBlock *block;
PanelType *pt;
- Panel *panel;
View2D *v2d = &ar->v2d;
- View2DScrollers *scrollers;
- int x, y, xco, yco, w, em, triangle;
+ int x, y, w, em;
bool is_context_new = 0;
int scroll;
- bool use_category_tabs = (ELEM(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI)); /* XXX, should use some better check? */
+ /* XXX, should use some better check? */
+ bool use_category_tabs = (ELEM(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI));
/* 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 */
@@ -1817,8 +2036,13 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c
/* 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 (context && pt->context[0] && !STREQ(context, pt->context)) {
+ if (contexts && pt->context[0] && !streq_array_any(pt->context, contexts)) {
continue;
}
@@ -1878,9 +2102,7 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c
BLI_SMALLSTACK_ITER_BEGIN(pt_stack, pt)
{
- bool open;
-
- panel = UI_panel_find_by_type(ar, 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)) {
@@ -1888,56 +2110,7 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c
}
}
- /* draw panel */
- block = UI_block_begin(C, ar, pt->idname, UI_EMBOSS);
- panel = UI_panel_begin(sa, ar, block, pt, panel, &open);
-
- /* bad fixed values */
- triangle = (int)(UI_UNIT_Y * 1.1f);
-
- if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) {
- /* for enabled buttons */
- panel->layout = UI_block_layout(
- block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER,
- triangle, (UI_UNIT_Y * 1.1f) + style->panelspace, UI_UNIT_Y, 1, 0, style);
-
- pt->draw_header(C, panel);
-
- UI_block_layout_resolve(block, &xco, &yco);
- panel->labelofs = xco - triangle;
- panel->layout = NULL;
- }
- else {
- panel->labelofs = 0;
- }
-
- if (open) {
- short panelContext;
-
- /* panel context can either be toolbar region or normal panels region */
- 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,
- style->panelspace, 0, w - 2 * style->panelspace, em, 0, style);
-
- pt->draw(C, panel);
-
- UI_block_layout_resolve(block, &xco, &yco);
- panel->layout = NULL;
-
- yco -= 2 * style->panelspace;
- UI_panel_end(block, w, -yco);
- }
- else {
- yco = 0;
- UI_panel_end(block, w, 0);
- }
-
- UI_block_end(C, block);
+ ed_panel_draw(C, sa, ar, &ar->panels, pt, panel, w, em, vertical);
}
BLI_SMALLSTACK_ITER_END;
@@ -1945,7 +2118,28 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c
UI_panels_end(C, ar, &x, &y);
/* before setting the view */
- if (vertical) {
+ 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_panel_size_y(panel),
+ };
+ /* 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 - 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 */
@@ -1986,10 +2180,25 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c
#endif
}
- region_clear_color(C, ar, (ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK);
-
+ 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);
+}
+
+void ED_region_panels_draw(const bContext *C, ARegion *ar)
+{
+ 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);
+ }
+
/* reset line width for drawing tabs */
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
/* set the view */
UI_view2d_view_ortho(v2d);
@@ -1999,17 +2208,35 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c
/* restore view matrix */
UI_view2d_view_restore(C);
-
- if (use_category_tabs) {
- UI_panel_category_draw_all(ar, category);
+
+ /* Set in layout. */
+ if (ar->runtime.category) {
+ UI_panel_category_draw_all(ar, ar->runtime.category);
}
/* scrollers */
- scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ View2DScrollers *scrollers = UI_view2d_scrollers_calc(
+ C, v2d, 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)
+{
+ /* 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);
+}
+
void ED_region_panels_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -2027,33 +2254,39 @@ void ED_region_header_layout(const bContext *C, ARegion *ar)
uiLayout *layout;
HeaderType *ht;
Header header = {NULL};
- int maxco, xco, yco;
- int headery = ED_area_headersize();
- const int start_ofs = 0.4f * UI_UNIT_X;
bool region_layout_based = ar->flag & RGN_FLAG_DYNAMIC_SIZE;
- /* set view2d view matrix for scrolling (without scrollers) */
- UI_view2d_view_ortho(&ar->v2d);
+ /* 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;
- xco = maxco = start_ofs;
- yco = headery + (ar->winy - headery) / 2 - floor(0.2f * UI_UNIT_Y);
+ /* 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 (CTX_wm_area(C)->spacetype == SPACE_TOPBAR) {
- xco += 1;
- yco += 1;
+ 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);
+
/* draw all headers types */
for (ht = ar->type->headertypes.first; ht; ht = ht->next) {
block = UI_block_begin(C, ar, ht->idname, UI_EMBOSS);
- layout = UI_block_layout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, xco, yco, UI_UNIT_Y, 1, 0, style);
+ 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 (ht->draw) {
header.type = ht;
header.layout = layout;
ht->draw(C, &header);
-
+
/* for view2d */
xco = uiLayoutGetWidth(layout);
if (xco > maxco)
@@ -2061,12 +2294,12 @@ void ED_region_header_layout(const bContext *C, ARegion *ar)
}
UI_block_layout_resolve(block, &xco, &yco);
-
+
/* for view2d */
if (xco > maxco)
maxco = xco;
- int new_sizex = (maxco + start_ofs) / 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 */
@@ -2079,8 +2312,12 @@ void ED_region_header_layout(const bContext *C, ARegion *ar)
UI_block_end(C, block);
}
+ if (!region_layout_based) {
+ maxco += UI_HEADER_OFFSET;
+ }
+
/* always as last */
- UI_view2d_totRect_set(&ar->v2d, maxco + (region_layout_based ? 0 : UI_UNIT_X + 80), headery);
+ UI_view2d_totRect_set(&ar->v2d, maxco, ar->winy);
/* restore view matrix */
UI_view2d_view_restore(C);
@@ -2088,11 +2325,11 @@ void ED_region_header_layout(const bContext *C, ARegion *ar)
void ED_region_header_draw(const bContext *C, ARegion *ar)
{
- UI_view2d_view_ortho(&ar->v2d);
-
/* clear */
region_clear_color(C, ar, region_background_color_id(C, ar));
+ UI_view2d_view_ortho(&ar->v2d);
+
/* View2D matrix might have changed due to dynamic sized regions. */
UI_blocklist_update_window_matrix(C, &ar->uiblocks);
@@ -2141,6 +2378,16 @@ 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);
}
+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);
+}
+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);
+}
bool ED_area_is_global(const ScrArea *area)
{
@@ -2191,7 +2438,7 @@ void ED_region_info_draw_multiline(ARegion *ar, const char *text_array[], float
const int header_height = UI_UNIT_Y;
uiStyle *style = UI_style_get_dpi();
int fontid = style->widget.uifont_id;
- GLint scissor[4];
+ int scissor[4];
rcti rect;
int num_lines = 0;
@@ -2216,23 +2463,22 @@ void ED_region_info_draw_multiline(ARegion *ar, const char *text_array[], float
}
}
- rect.ymin = BLI_rcti_size_y(&ar->winrct) - header_height * num_lines;
- rect.ymax = BLI_rcti_size_y(&ar->winrct);
+ rect.ymin = rect.ymax - header_height * num_lines;
/* setup scissor */
- glGetIntegerv(GL_SCISSOR_BOX, scissor);
- glScissor(rect.xmin, rect.ymin,
+ GPU_scissor_geti(scissor);
+ GPU_scissor(rect.xmin, rect.ymin,
BLI_rcti_size_x(&rect) + 1, BLI_rcti_size_y(&rect) + 1);
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_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();
- glDisable(GL_BLEND);
+ GPU_blend(false);
/* text */
UI_FontThemeColor(fontid, TH_TEXT_HI);
@@ -2252,7 +2498,7 @@ void ED_region_info_draw_multiline(ARegion *ar, const char *text_array[], float
BLF_disable(fontid, BLF_CLIPPING);
/* restore scissor as it was before */
- glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
+ 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)
@@ -2361,7 +2607,7 @@ static void metadata_draw_imbuf(ImBuf *ibuf, const rctf *rect, int fontid, const
if (metadata_is_valid(ibuf, temp_str, i, len)) {
BLF_position(fontid, xmin + ofs_x, ymin, 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;
}
}
@@ -2501,7 +2747,7 @@ void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy)
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
-
+
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColorShade(TH_BACK, 20);
immRectf(pos, x1, y1, x2, y2);
@@ -2535,14 +2781,14 @@ void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy)
GWN_vertformat_clear(format);
pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
unsigned color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
-
+
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
immBegin(GWN_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++) {
immAttrib3fv(color, theme_color);
@@ -2559,7 +2805,7 @@ void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy)
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++) {
immAttrib3fv(color, theme_color);
@@ -2584,25 +2830,43 @@ void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy)
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)) {
-
- /* 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;
+ 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");
+ }
}
}
}
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index 39178af9e4e..6cff82295f0 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -51,6 +51,7 @@
#include "GPU_basic_shader.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "UI_interface.h"
@@ -59,11 +60,11 @@
void setlinestyle(int nr)
{
if (nr == 0) {
- glDisable(GL_LINE_STIPPLE);
+ GPU_line_stipple(false);
}
else {
-
- glEnable(GL_LINE_STIPPLE);
+
+ GPU_line_stipple(true);
if (U.pixelsize > 1.0f)
glLineStipple(nr, 0xCCCC);
else
@@ -72,10 +73,10 @@ void setlinestyle(int nr)
}
/* Invert line handling */
-
+
#define GL_TOGGLE(mode, onoff) (((onoff) ? glEnable : glDisable)(mode))
-void set_inverted_drawing(int enable)
+void set_inverted_drawing(int enable)
{
glLogicOp(enable ? GL_INVERT : GL_COPY);
GL_TOGGLE(GL_COLOR_LOGIC_OP, enable);
@@ -355,18 +356,18 @@ void immDrawPixelsTex_clipping(IMMDrawPixelsTexState *state,
void bglPolygonOffset(float viewdist, float dist)
{
static float winmat[16], offset = 0.0f;
-
+
if (dist != 0.0f) {
float offs;
-
+
// glEnable(GL_POLYGON_OFFSET_FILL);
// glPolygonOffset(-1.0, -1.0);
/* hack below is to mimic polygon offset */
gpuGetProjectionMatrix(winmat);
-
+
/* dist is from camera to center point */
-
+
if (winmat[15] > 0.5f) {
#if 1
offs = 0.00001f * dist * viewdist; // ortho tweaking
@@ -391,7 +392,7 @@ void bglPolygonOffset(float viewdist, float dist)
*/
offs = winmat[14] * -0.0025f * dist;
}
-
+
winmat[14] -= offs;
offset += offs;
}
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index 85087d58276..fa18826005e 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -80,7 +80,7 @@ const char *screen_context_dir[] = {
"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_gpencil_palette",
+ "active_gpencil_layer", "active_gpencil_frame", "active_gpencil_palette",
"active_gpencil_palettecolor", "active_gpencil_brush",
"active_operator", "selected_editable_fcurves",
NULL};
@@ -115,7 +115,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
}
else if (CTX_data_equals(member, "selectable_objects")) {
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (((base->flag & BASE_VISIBLED) != 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
+ if (((base->flag & BASE_VISIBLE) != 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
CTX_data_id_list_add(result, &base->object->id);
}
}
@@ -165,7 +165,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
}
else if (CTX_data_equals(member, "selectable_bases")) {
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if ((base->flag & BASE_SELECTABLED) != 0) {
+ if ((base->flag & BASE_SELECTABLE) != 0) {
CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
}
}
@@ -195,7 +195,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
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->flag & BASE_VISIBLED) != 0) {
+ if ((base->flag & BASE_VISIBLE) != 0) {
if (0 == BKE_object_is_libdata(base->object)) {
CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
}
@@ -208,7 +208,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
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, &objects_len);
@@ -259,7 +259,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
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, &objects_len);
@@ -364,7 +364,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
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);
@@ -393,7 +393,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
/* 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")) {
@@ -465,11 +465,11 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
}
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
+ * (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, scene, sa, obact);
-
+
if (gpd) {
CTX_data_id_pointer_set(result, &gpd->id);
return 1;
@@ -477,14 +477,14 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
}
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...
+ * 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, scene, sa, obact, &ptr);
-
+
if (gpd_ptr) {
CTX_data_pointer_set(result, ptr.id.data, ptr.type, ptr.data);
return 1;
@@ -493,10 +493,10 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
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, scene, sa, obact);
-
+
if (gpd) {
bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
-
+
if (gpl) {
CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilLayer, gpl);
return 1;
@@ -544,10 +544,10 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
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, scene, sa, 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;
@@ -557,10 +557,10 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
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, scene, sa, 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);
@@ -573,10 +573,10 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
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, scene, sa, 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);
@@ -589,15 +589,15 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
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, scene, sa, obact);
-
+
if (gpd) {
bGPDlayer *gpl;
-
+
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
if (gpencil_layer_is_editable(gpl) && (gpl->actframe)) {
bGPDframe *gpf = gpl->actframe;
bGPDstroke *gps;
-
+
for (gps = gpf->strokes.first; gps; gps = gps->next) {
if (ED_gpencil_stroke_can_use_direct(sa, gps)) {
/* check if the color is editable */
@@ -665,4 +665,3 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
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 fec39ade110..b5b0d16f6a7 100644
--- a/source/blender/editors/screen/screen_draw.c
+++ b/source/blender/editors/screen/screen_draw.c
@@ -27,6 +27,7 @@
#include "GPU_framebuffer.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "BLI_math.h"
@@ -43,11 +44,11 @@
*/
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;
- float width = sa->v3->vec.x - sa->v1->vec.x;
- float height = sa->v3->vec.y - sa->v1->vec.y;
if (height < width) {
h = height / 8;
@@ -124,11 +125,11 @@ 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;
- float width = sa->v3->vec.x - sa->v1->vec.x;
- float height = sa->v3->vec.y - sa->v1->vec.y;
if (height < width) {
h = height / 4;
@@ -353,7 +354,7 @@ static void drawscredge_corner(ScrArea *sa, int sizex, int sizey)
*/
static void scrarea_draw_shape_dark(ScrArea *sa, char dir, unsigned int pos)
{
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ 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);
@@ -364,7 +365,7 @@ 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)
{
- glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);
+ 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); */
@@ -444,7 +445,7 @@ void ED_screen_draw_edges(wmWindow *win)
/* Note: first loop only draws if U.pixelsize > 1, skip otherwise */
if (U.pixelsize > 1.0f) {
/* FIXME: doesn't our glLineWidth already scale by U.pixelsize? */
- glLineWidth((2.0f * U.pixelsize) - 1);
+ GPU_line_width((2.0f * U.pixelsize) - 1);
immUniformThemeColor(TH_EDITOR_OUTLINE);
for (sa = screen->areabase.first; sa; sa = sa->next) {
@@ -452,7 +453,7 @@ void ED_screen_draw_edges(wmWindow *win)
}
}
- glLineWidth(1);
+ GPU_line_width(1);
immUniformThemeColor(TH_EDITOR_OUTLINE);
for (sa = screen->areabase.first; sa; sa = sa->next) {
@@ -479,7 +480,7 @@ void ED_screen_draw_join_shape(ScrArea *sa1, ScrArea *sa2)
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- glLineWidth(1);
+ GPU_line_width(1);
/* blended join arrow */
int dir = area_getorientation(sa1, sa2);
@@ -504,12 +505,12 @@ void ED_screen_draw_join_shape(ScrArea *sa1, ScrArea *sa2)
break;
}
- glEnable(GL_BLEND);
+ GPU_blend(true);
scrarea_draw_shape_dark(sa2, dir, pos);
scrarea_draw_shape_light(sa1, dira, pos);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
immUnbindProgram();
@@ -521,7 +522,7 @@ void ED_screen_draw_split_preview(ScrArea *sa, const int dir, const float fac)
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* splitpoint */
- glEnable(GL_BLEND);
+ GPU_blend(true);
immUniformColor4ub(255, 255, 255, 100);
immBegin(GWN_PRIM_LINES, 2);
@@ -562,7 +563,7 @@ void ED_screen_draw_split_preview(ScrArea *sa, const int dir, const float fac)
immEnd();
}
- glDisable(GL_BLEND);
+ GPU_blend(false);
immUnbindProgram();
}
@@ -645,8 +646,8 @@ void ED_screen_preview_render(const bScreen *screen, int size_x, int size_y, uns
GPUOffScreen *offscreen = GPU_offscreen_create(size_x, size_y, 0, true, false, err_out);
GPU_offscreen_bind(offscreen, true);
- glClearColor(0.0, 0.0, 0.0, 0.0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ 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);
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 8ebdb5f32b8..6bc8a6c10cf 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -74,98 +74,6 @@
#include "screen_intern.h" /* own module include */
-/* ******************* screen vert, edge, area managing *********************** */
-
-static ScrVert *screen_addvert_ex(ScrAreaMap *area_map, short x, short y)
-{
- ScrVert *sv = MEM_callocN(sizeof(ScrVert), "addscrvert");
- sv->vec.x = x;
- sv->vec.y = y;
-
- BLI_addtail(&area_map->vertbase, sv);
- return sv;
-}
-static ScrVert *screen_addvert(bScreen *sc, short x, short y)
-{
- return screen_addvert_ex(AREAMAP_FROM_SCREEN(sc), x, y);
-}
-
-static ScrEdge *screen_addedge_ex(ScrAreaMap *area_map, ScrVert *v1, ScrVert *v2)
-{
- ScrEdge *se = MEM_callocN(sizeof(ScrEdge), "addscredge");
-
- BKE_screen_sort_scrvert(&v1, &v2);
- se->v1 = v1;
- se->v2 = v2;
-
- BLI_addtail(&area_map->edgebase, se);
- return se;
-}
-static ScrEdge *screen_addedge(bScreen *sc, ScrVert *v1, ScrVert *v2)
-{
- return screen_addedge_ex(AREAMAP_FROM_SCREEN(sc), v1, v2);
-}
-
-bool scredge_is_horizontal(ScrEdge *se)
-{
- return (se->v1->vec.y == se->v2->vec.y);
-}
-
-/* need win size to make sure not to include edges along screen edge */
-ScrEdge *screen_area_map_find_active_scredge(
- const ScrAreaMap *area_map,
- const int winsize_x, const int winsize_y,
- 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 (scredge_is_horizontal(se)) {
- if (se->v1->vec.y > 0 && se->v1->vec.y < winsize_y - 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 > 0 && se->v1->vec.x < winsize_x - 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_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 */
- const int screen_x = WM_window_screen_pixels_x(win), screen_y = WM_window_screen_pixels_y(win);
- ScrEdge *se = screen_area_map_find_active_scredge(AREAMAP_FROM_SCREEN(screen), screen_x, screen_y, mx, my);
-
- if (!se) {
- /* Use entire window size (screen including global areas) for global area edges */
- const int win_x = WM_window_pixels_x(win), win_y = WM_window_pixels_y(win);
- se = screen_area_map_find_active_scredge(&win->global_areas, win_x, win_y, mx, my);
- }
- return se;
-}
-
-
-
/* adds no space data */
static ScrArea *screen_addarea_ex(
ScrAreaMap *area_map,
@@ -195,81 +103,45 @@ static ScrArea *screen_addarea(
static void screen_delarea(bContext *C, bScreen *sc, ScrArea *sa)
{
-
+
ED_area_exit(C, sa);
-
+
BKE_screen_area_free(sa);
-
+
BLI_remlink(&sc->areabase, sa);
MEM_freeN(sa);
}
-/* return 0: no split possible */
-/* else return (integer) screencoordinate split point */
-static short testsplitpoint(ScrArea *sa, char dir, float fac)
-{
- short x, y;
- const short area_min_x = AREAMINX;
- const short area_min_y = ED_area_headersize();
-
- // area big enough?
- if (dir == 'v' && (sa->v4->vec.x - sa->v1->vec.x <= 2 * area_min_x)) return 0;
- if (dir == 'h' && (sa->v2->vec.y - sa->v1->vec.y <= 2 * area_min_y)) return 0;
-
- // to be sure
- CLAMP(fac, 0.0f, 1.0f);
-
- if (dir == 'h') {
- y = sa->v1->vec.y + fac * (sa->v2->vec.y - sa->v1->vec.y);
-
- if (y - sa->v1->vec.y < area_min_y)
- y = sa->v1->vec.y + area_min_y;
- else if (sa->v2->vec.y - y < area_min_y)
- y = sa->v2->vec.y - area_min_y;
- else y -= (y % AREAGRID);
-
- return y;
- }
- else {
- x = sa->v1->vec.x + fac * (sa->v4->vec.x - sa->v1->vec.x);
-
- if (x - sa->v1->vec.x < area_min_x)
- x = sa->v1->vec.x + area_min_x;
- else if (sa->v4->vec.x - x < area_min_x)
- x = sa->v4->vec.x - area_min_x;
- else x -= (x % AREAGRID);
-
- return x;
- }
-}
-
-ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge)
+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;
-
- split = testsplitpoint(sa, dir, fac);
+
+ 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_addvert(sc, sa->v1->vec.x, split);
- sv2 = screen_addvert(sc, sa->v4->vec.x, split);
-
+ 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_addedge(sc, sa->v1, sv1);
- screen_addedge(sc, sv1, sa->v2);
- screen_addedge(sc, sa->v3, sv2);
- screen_addedge(sc, sv2, sa->v4);
- screen_addedge(sc, sv1, sv2);
-
+ 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);
@@ -288,20 +160,20 @@ ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge)
}
ED_area_data_copy(newa, sa, true);
-
+
}
else {
/* new vertices */
- sv1 = screen_addvert(sc, split, sa->v1->vec.y);
- sv2 = screen_addvert(sc, split, sa->v2->vec.y);
-
+ 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_addedge(sc, sa->v1, sv1);
- screen_addedge(sc, sv1, sa->v4);
- screen_addedge(sc, sa->v2, sv2);
- screen_addedge(sc, sv2, sa->v3);
- screen_addedge(sc, sv1, sv2);
-
+ 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);
@@ -321,41 +193,41 @@ ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge)
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;
}
/**
* Empty screen, with 1 dummy area without spacedata. Uses window size.
*/
-bScreen *screen_add(const char *name, const int winsize_x, const int winsize_y)
+bScreen *screen_add(Main *bmain, const char *name, const rcti *rect)
{
bScreen *sc;
ScrVert *sv1, *sv2, *sv3, *sv4;
-
- sc = BKE_libblock_alloc(G.main, ID_SCR, name, 0);
+
+ 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_addvert(sc, 0, 0);
- sv2 = screen_addvert(sc, 0, winsize_y - 1);
- sv3 = screen_addvert(sc, winsize_x - 1, winsize_y - 1);
- sv4 = screen_addvert(sc, winsize_x - 1, 0);
-
- screen_addedge(sc, sv1, sv2);
- screen_addedge(sc, sv2, sv3);
- screen_addedge(sc, sv3, sv4);
- screen_addedge(sc, sv4, sv1);
-
+ 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);
+
/* dummy type, no spacedata */
screen_addarea(sc, sv1, sv2, sv3, sv4, SPACE_EMPTY);
-
+
return sc;
}
@@ -364,26 +236,26 @@ 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);
-
+
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;
@@ -395,10 +267,10 @@ void screen_data_copy(bScreen *to, bScreen *from)
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;
@@ -433,7 +305,7 @@ int area_getorientation(ScrArea *sa, ScrArea *sb)
sbv2 = sb->v2;
sbv3 = sb->v3;
sbv4 = sb->v4;
-
+
if (sav1 == sbv4 && sav2 == sbv3) { /* sa to right of sb = W */
return 0;
}
@@ -446,7 +318,7 @@ int area_getorientation(ScrArea *sa, ScrArea *sb)
else if (sav1 == sbv2 && sav4 == sbv3) { /* sa on top of sb = S*/
return 3;
}
-
+
return -1;
}
@@ -456,39 +328,39 @@ 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_addedge(scr, sa1->v2, sa1->v3);
- screen_addedge(scr, sa1->v1, sa1->v4);
+ 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_addedge(scr, sa1->v1, sa1->v2);
- screen_addedge(scr, sa1->v3, sa1->v4);
+ 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_addedge(scr, sa1->v2, sa1->v3);
- screen_addedge(scr, sa1->v1, sa1->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_addedge(scr, sa1->v1, sa1->v2);
- screen_addedge(scr, sa1->v3, sa1->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 */
@@ -497,241 +369,6 @@ int screen_area_join(bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2)
return 1;
}
-void select_connected_scredge(const wmWindow *win, ScrEdge *edge)
-{
- bScreen *sc = WM_window_get_active_screen(win);
- ScrEdge *se;
- int oneselected;
- 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;
-
- oneselected = 1;
- while (oneselected) {
- se = sc->edgebase.first;
- oneselected = 0;
- while (se) {
- 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 = 1;
- }
- }
- if (dir == 'v') {
- if (se->v1->vec.x == se->v2->vec.x) {
- se->v1->flag = se->v2->flag = 1;
- oneselected = 1;
- }
- }
- }
- se = se->next;
- }
- }
-}
-
-/**
- * Test if screen vertices should be scaled and do if needed.
- */
-static void screen_vertices_scale(
- const wmWindow *win, bScreen *sc,
- int window_size_x, int window_size_y,
- int screen_size_x, int screen_size_y)
-{
- /* clamp Y size of header sized areas when expanding windows
- * avoids annoying empty space around file menu */
-#define USE_HEADER_SIZE_CLAMP
-
- const int headery_init = ED_area_headersize();
- ScrVert *sv = NULL;
- ScrArea *sa;
- int screen_size_x_prev, screen_size_y_prev;
- float facx, facy, tempf, min[2], max[2];
-
- /* calculate size */
- min[0] = min[1] = 20000.0f;
- max[0] = max[1] = 0.0f;
-
- 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);
- }
-
- /* always make 0.0 left under */
- for (sv = sc->vertbase.first; sv; sv = sv->next) {
- sv->vec.x -= min[0];
- sv->vec.y -= min[1];
- }
-
- 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 + 4;
- 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 == screen_size_y_prev) {
- if ((sa->v2->vec.y - sa->v1->vec.y) < headery_margin_max) {
- sa->temp = TEMP_TOP;
- }
- }
- else if (sa->v1->vec.y == 0) {
- if ((sa->v2->vec.y - sa->v1->vec.y) < headery_margin_max) {
- sa->temp = TEMP_BOTTOM;
- }
- }
- }
- }
- }
-#endif
-
-
- if (screen_size_x_prev != screen_size_x || screen_size_y_prev != screen_size_y) {
- facx = ((float)screen_size_x - 1) / ((float)screen_size_x_prev - 1);
- facy = ((float)screen_size_y) / ((float)screen_size_y_prev);
-
- /* make sure it fits! */
- for (sv = sc->vertbase.first; sv; sv = sv->next) {
- /* FIXME, this re-sizing logic is no good when re-sizing the window + redrawing [#24428]
- * need some way to store these as floats internally and re-apply from there. */
- tempf = ((float)sv->vec.x) * facx;
- sv->vec.x = (short)(tempf + 0.5f);
- //sv->vec.x += AREAGRID - 1;
- //sv->vec.x -= (sv->vec.x % AREAGRID);
-
- CLAMP(sv->vec.x, 0, screen_size_x - 1);
-
- tempf = ((float)sv->vec.y) * facy;
- sv->vec.y = (short)(tempf + 0.5f);
- //sv->vec.y += AREAGRID - 1;
- //sv->vec.y -= (sv->vec.y % AREAGRID);
-
- CLAMP(sv->vec.y, 0, screen_size_y);
- }
- }
-
-
-#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) {
- select_connected_scredge(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) {
- select_connected_scredge(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 > 0)
- headery += U.pixelsize;
- if (sa->v2->vec.y < screen_size_y)
- headery += U.pixelsize;
-
- if (sa->v2->vec.y - sa->v1->vec.y + 1 < headery) {
- /* lower edge */
- ScrEdge *se = BKE_screen_find_edge(sc, sa->v4, sa->v1);
- if (se && sa->v1 != sa->v2) {
- int yval;
-
- select_connected_scredge(win, se);
-
- /* all selected vertices get the right offset */
- yval = sa->v2->vec.y - headery + 1;
- 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.
- * TODO Assumes global area to be top-aligned. Should be made more generic */
- for (ScrArea *area = win->global_areas.areabase.first; area; area = area->next) {
- if (area->global->flag & GLOBAL_AREA_IS_HIDDEN) {
- continue;
- }
- /* width */
- area->v1->vec.x = area->v2->vec.x = 0;
- area->v3->vec.x = area->v4->vec.x = window_size_x - 1;
- /* height */
- area->v2->vec.y = area->v3->vec.y = window_size_y - 1;
- area->v1->vec.y = area->v4->vec.y = area->v2->vec.y - ED_area_global_size_y(area);
- }
-}
-
/* ****************** EXPORTED API TO OTHER MODULES *************************** */
@@ -787,7 +424,7 @@ static void screen_refresh_headersizes(void)
{
const ListBase *lb = BKE_spacetypes_list();
SpaceType *st;
-
+
for (st = lb->first; st; st = st->next) {
ARegionType *art = BKE_regiontype_from_id(st, RGN_TYPE_HEADER);
if (art) art->prefsizey = ED_area_headersize();
@@ -802,23 +439,23 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
/* exception for bg mode, we only need the screen context */
if (!G.background) {
- const int window_size_x = WM_window_pixels_x(win);
- const int window_size_y = WM_window_pixels_y(win);
- const int screen_size_x = WM_window_screen_pixels_x(win);
- const int screen_size_y = WM_window_screen_pixels_y(win);
+ rcti window_rect, screen_rect;
/* header size depends on DPI, let's verify */
WM_window_set_dpi(win);
screen_refresh_headersizes();
- screen_vertices_scale(win, screen, window_size_x, window_size_y, screen_size_x, screen_size_y);
+ WM_window_rect_calc(win, &window_rect);
+ WM_window_screen_rect_calc(win, &screen_rect); /* Get screen bounds __after__ updating window DPI! */
+
+ 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);
@@ -835,19 +472,22 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
}
/* file read, set all screens, ... */
-void ED_screens_initialize(wmWindowManager *wm)
+void ED_screens_initialize(Main *bmain, wmWindowManager *wm)
{
wmWindow *win;
-
+
for (win = wm->windows.first; win; win = win->next) {
if (WM_window_get_active_workspace(win) == NULL) {
- WM_window_set_active_workspace(win, G.main->workspaces.first);
+ WM_window_set_active_workspace(win, bmain->workspaces.first);
}
if (BLI_listbase_is_empty(&win->global_areas.areabase)) {
ED_screen_global_areas_create(win);
}
ED_screen_refresh(wm, win);
+ if (win->eventstate) {
+ ED_screen_set_active_region(NULL, win, &win->eventstate->x);
+ }
}
}
@@ -875,12 +515,12 @@ void ED_region_exit(bContext *C, ARegion *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->regiontimer) {
WM_event_remove_timer(wm, win, ar->regiontimer);
ar->regiontimer = NULL;
@@ -916,31 +556,30 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *prevwin = CTX_wm_window(C);
- ScrArea *sa;
- ARegion *ar;
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 (ar = screen->regionbase.first; ar; ar = ar->next) {
+
+ for (ARegion *ar = screen->regionbase.first; ar; ar = ar->next) {
ED_region_exit(C, ar);
}
- for (sa = screen->areabase.first; sa; sa = sa->next) {
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
ED_area_exit(C, sa);
}
- for (sa = window->global_areas.areabase.first; sa; sa = sa->next) {
+ /* 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);
@@ -949,7 +588,7 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen)
/* none otherwise */
CTX_wm_window_set(C, NULL);
}
-
+
}
/* *********************************** */
@@ -960,11 +599,11 @@ 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 = is_in_area_actionzone(sa, xy)))
+ if ((az = ED_area_actionzone_find_xy(sa, xy)))
break;
-
+
if (sa) {
if (az->type == AZONE_AREA)
WM_cursor_set(win, CURSOR_EDIT);
@@ -976,10 +615,10 @@ static void screen_cursor_set(wmWindow *win, const int xy[2])
}
}
else {
- ScrEdge *actedge = screen_find_active_scredge(win, screen, xy[0], xy[1]);
+ ScrEdge *actedge = screen_geom_find_active_scredge(win, screen, xy[0], xy[1]);
if (actedge) {
- if (scredge_is_horizontal(actedge))
+ if (screen_geom_edge_is_horizontal(actedge))
WM_cursor_set(win, CURSOR_Y_MOVE);
else
WM_cursor_set(win, CURSOR_X_MOVE);
@@ -992,9 +631,8 @@ static void screen_cursor_set(wmWindow *win, const int xy[2])
/* called in wm_event_system.c. sets state vars in screen, cursors */
/* event type is mouse move */
-void ED_screen_set_active_region(bContext *C, const int xy[2])
+void ED_screen_set_active_region(bContext *C, wmWindow *win, const int xy[2])
{
- wmWindow *win = CTX_wm_window(C);
bScreen *scr = WM_window_get_active_screen(win);
if (scr) {
@@ -1005,7 +643,7 @@ void ED_screen_set_active_region(bContext *C, const int xy[2])
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 (is_in_area_actionzone(area_iter, xy) == NULL) {
+ if (ED_area_actionzone_refresh_xy(area_iter, xy) == NULL) {
sa = area_iter;
break;
}
@@ -1023,29 +661,29 @@ void ED_screen_set_active_region(bContext *C, const int xy[2])
}
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(ar);
+ ED_region_tag_redraw_no_rebuild(ar);
}
}
}
}
}
-
+
/* cursors, for time being set always on edges, otherwise aregion doesnt switch */
if (scr->active_region == NULL) {
screen_cursor_set(win, xy);
@@ -1058,7 +696,9 @@ void ED_screen_set_active_region(bContext *C, const int xy[2])
/* 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 */
- UI_screen_free_active_but(C, scr);
+ if (C) {
+ UI_screen_free_active_but(C, scr);
+ }
}
else
region_cursor_set(win, false);
@@ -1073,12 +713,12 @@ int ED_screen_area_active(const bContext *C)
ScrArea *sa = CTX_wm_area(C);
if (win && sc && sa) {
- AZone *az = is_in_area_actionzone(sa, &win->eventstate->x);
+ 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;
@@ -1094,52 +734,69 @@ static ScrArea *screen_area_create_with_geometry(
ScrAreaMap *area_map, const rcti *rect,
short spacetype)
{
- ScrVert *bottom_left = screen_addvert_ex(area_map, rect->xmin, rect->ymin);
- ScrVert *top_left = screen_addvert_ex(area_map, rect->xmin, rect->ymax);
- ScrVert *top_right = screen_addvert_ex(area_map, rect->xmax, rect->ymax);
- ScrVert *bottom_right = screen_addvert_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_addedge_ex(area_map, bottom_left, top_left);
- screen_addedge_ex(area_map, top_left, top_right);
- screen_addedge_ex(area_map, top_right, bottom_right);
- screen_addedge_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);
}
-void ED_screen_global_topbar_area_create(wmWindow *win, const bScreen *screen)
+static void screen_global_area_create(
+ wmWindow *win, eSpace_Type space_type, GlobalAreaAlign align, const rcti *rect,
+ const short height_cur, const short height_min, const short height_max)
{
- if (screen->temp == 0) {
- const short size_y = 2.25 * HEADERY;
- SpaceType *st;
- SpaceLink *sl;
- ScrArea *sa;
- 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_y;
-
- sa = screen_area_create_with_geometry(&win->global_areas, &rect, SPACE_TOPBAR);
- st = BKE_spacetype_from_id(SPACE_TOPBAR);
- sl = st->new(sa, WM_window_get_active_scene(win));
- sa->regionbase = sl->regionbase;
-
- /* Data specific to global areas. */
- sa->global = MEM_callocN(sizeof(*sa->global), __func__);
- sa->global->cur_fixed_height = size_y;
- sa->global->size_max = size_y;
- sa->global->size_min = HEADERY;
-
- BLI_addhead(&sa->spacedata, sl);
- BLI_listbase_clear(&sl->regionbase);
- }
- /* Do not create more area types here! Function is called on file load (wm_window_ghostwindows_ensure). TODO */
+ ScrArea *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;
+
+ /* Data specific to global areas. */
+ area->global = MEM_callocN(sizeof(*area->global), __func__);
+ area->global->cur_fixed_height = height_cur;
+ area->global->size_max = height_max;
+ area->global->size_min = height_min;
+ area->global->align = align;
+
+ BLI_addhead(&area->spacedata, slink);
+ BLI_listbase_clear(&slink->regionbase);
+}
+
+static void screen_global_topbar_area_create(wmWindow *win)
+{
+ const short size_y = 2.25 * HEADERY;
+ 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_y;
+
+ screen_global_area_create(win, SPACE_TOPBAR, GLOBAL_AREA_ALIGN_TOP, &rect, size_y, HEADERY, size_y);
+}
+
+static void screen_global_statusbar_area_create(wmWindow *win)
+{
+ const short size_y = 0.8f * HEADERY;
+ 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_y;
+
+ screen_global_area_create(win, SPACE_STATUSBAR, GLOBAL_AREA_ALIGN_BOTTOM, &rect, size_y, 0, size_y);
}
void ED_screen_global_areas_create(wmWindow *win)
{
- const bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
- ED_screen_global_topbar_area_create(win, screen);
+ bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
+ if (screen->temp == 0) {
+ screen_global_topbar_area_create(win);
+ screen_global_statusbar_area_create(win);
+ }
}
@@ -1260,13 +917,13 @@ static void screen_set_3dview_camera(Scene *scene, ViewLayer *view_layer, ScrAre
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;
@@ -1299,7 +956,7 @@ ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type)
if (!sa || sa->full == NULL) {
newsa = ED_screen_state_toggle(C, win, sa, SCREENMAXIMIZED);
}
-
+
if (!newsa) {
newsa = sa;
}
@@ -1356,10 +1013,10 @@ void ED_screen_full_restore(bContext *C, ScrArea *sa)
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);
@@ -1382,6 +1039,7 @@ 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;
@@ -1400,8 +1058,9 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
}
}
- /* prevent hanging header prints */
- ED_area_headerprint(sa, NULL);
+ /* prevent hanging status prints */
+ ED_area_status_text(sa, NULL);
+ ED_workspace_status_text(C, NULL);
}
if (sa && sa->full) {
@@ -1472,7 +1131,7 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
oldscreen->state = state;
BLI_snprintf(newname, sizeof(newname), "%s-%s", oldscreen->id.name + 2, "nonnormal");
- layout_new = ED_workspace_layout_add(workspace, win, newname);
+ layout_new = ED_workspace_layout_add(bmain, workspace, win, newname);
sc = BKE_workspace_layout_screen_get(layout_new);
sc->state = state;
@@ -1485,7 +1144,7 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
/* 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) {
+ if (!sa || sa->global) {
sa = oldscreen->areabase.first;
}
@@ -1527,15 +1186,15 @@ 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;
@@ -1548,7 +1207,7 @@ void ED_refresh_viewport_fps(bContext *C)
}
}
-/* redraws: uses defines from stime->redraws
+/* redraws: uses defines from stime->redraws
* enable: 1 - forward on, -1 - backwards on, 0 - off
*/
void ED_screen_animation_timer(bContext *C, int redraws, int refresh, int sync, int enable)
@@ -1558,17 +1217,17 @@ void ED_screen_animation_timer(bContext *C, int redraws, int refresh, int sync,
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) */
@@ -1603,7 +1262,7 @@ void ED_screen_animation_timer(bContext *C, int redraws, int refresh, int sync,
sad->from_anim_edit = (ELEM(spacetype, SPACE_IPO, SPACE_ACTION, SPACE_NLA));
screen->animtimer->customdata = sad;
-
+
}
/* notifier catched by top header, for button */
@@ -1616,7 +1275,7 @@ 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;
@@ -1639,7 +1298,7 @@ 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;
@@ -1662,9 +1321,10 @@ void ED_update_for_newframe(Main *bmain, Depsgraph *depsgraph)
for (sc = bmain->screen.first; sc; sc = sc->id.next) {
BKE_screen_view3d_scene_sync(sc, scene);
}
+ DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
}
#endif
-
+
ED_clip_update_frame(bmain, scene->r.cfra);
/* this function applies the changes too */
@@ -1673,7 +1333,7 @@ void ED_update_for_newframe(Main *bmain, Depsgraph *depsgraph)
/* composite */
if (scene->use_nodes && scene->nodetree)
ntreeCompositTagAnimated(scene->nodetree);
-
+
/* update animated texture nodes */
{
Tex *tex;
@@ -1683,7 +1343,7 @@ void ED_update_for_newframe(Main *bmain, Depsgraph *depsgraph)
}
}
}
-
+
}
/*
diff --git a/source/blender/editors/screen/screen_geometry.c b/source/blender/editors/screen/screen_geometry.c
new file mode 100644
index 00000000000..5d87479e371
--- /dev/null
+++ b/source/blender/editors/screen/screen_geometry.c
@@ -0,0 +1,462 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/screen/screen_geometry.c
+ * \ingroup edscr
+ * \brief Functions for screen vertices and edges
+ *
+ * Screen geometry refers to the vertices (ScrVert) and edges (ScrEdge) through
+ * which the flexible screen-layout system of Blender is established.
+ */
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_rect.h"
+
+#include "BKE_screen.h"
+
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "ED_screen.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "WM_api.h"
+
+#include "screen_intern.h"
+
+
+int screen_geom_area_height(const ScrArea *area)
+{
+ 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;
+}
+
+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;
+
+ 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);
+}
+
+ScrEdge *screen_geom_edge_add_ex(ScrAreaMap *area_map, ScrVert *v1, ScrVert *v2)
+{
+ ScrEdge *se = MEM_callocN(sizeof(ScrEdge), "addscredge");
+
+ BKE_screen_sort_scrvert(&v1, &v2);
+ se->v1 = v1;
+ se->v2 = v2;
+
+ 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);
+}
+
+bool screen_geom_edge_is_horizontal(ScrEdge *se)
+{
+ 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)
+{
+ 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)
+{
+ /* 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;
+}
+
+/**
+ * \brief Main screen-layout calculation function.
+ *
+ * * Scale areas nicely on window size and DPI changes.
+ * * Ensure areas have a minimum height.
+ * * Correctly set global areas to their fixed height.
+ */
+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 */
+#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);
+
+ 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];
+
+ /* calculate size */
+ min[0] = min[1] = 20000.0f;
+ max[0] = max[1] = 0.0f;
+
+ 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;
+ }
+ }
+ }
+ }
+ }
+#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);
+
+ /* 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
+#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;
+ }
+ }
+}
+
+/**
+ * \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 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;
+ }
+}
+
+/**
+ * Select all edges that are directly or indirectly connected to \a edge.
+ */
+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;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h
index 045e5ee6b48..cd71c07a3c0 100644
--- a/source/blender/editors/screen/screen_intern.h
+++ b/source/blender/editors/screen/screen_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -48,26 +48,37 @@ void screen_area_update_region_sizes(wmWindowManager *wm, wmWindow *win,
void region_toggle_hidden(struct bContext *C, ARegion *ar, const bool do_fade);
/* screen_edit.c */
-bScreen *screen_add(const char *name, const int winsize_x, const int winsize_y);
+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(bScreen *sc, ScrArea *sa, char dir, float fac, int merge);
+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);
-void select_connected_scredge(const wmWindow *win, ScrEdge *edge);
-bool scredge_is_horizontal(ScrEdge *se);
-ScrEdge *screen_area_map_find_active_scredge(
+struct AZone *ED_area_actionzone_find_xy(ScrArea *sa, const int xy[2]);
+struct AZone *ED_area_actionzone_refresh_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 int winsize_x, const int winsize_y,
+ const rcti *bounds_rect,
const int mx, const int my);
-ScrEdge *screen_find_active_scredge(
+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);
-struct AZone *is_in_area_actionzone(ScrArea *sa, const int xy[2]);
/* screen_context.c */
int ed_screen_context(
@@ -77,7 +88,6 @@ extern const char *screen_context_dir[]; /* doc access */
/* screendump.c */
void SCREEN_OT_screenshot(struct wmOperatorType *ot);
-void SCREEN_OT_screencast(struct wmOperatorType *ot);
/* screen_ops.c */
void region_blend_start(struct bContext *C, struct ScrArea *sa, struct ARegion *ar);
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 6f422a39584..2776bd98a43 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -39,6 +39,7 @@
#include "BLT_translation.h"
+#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_lattice_types.h"
#include "DNA_object_types.h"
@@ -53,6 +54,7 @@
#include "BKE_context.h"
#include "BKE_customdata.h"
+#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_icons.h"
#include "BKE_main.h"
@@ -70,6 +72,7 @@
#include "DEG_depsgraph.h"
+#include "ED_anim_api.h"
#include "ED_armature.h"
#include "ED_clip.h"
#include "ED_image.h"
@@ -143,6 +146,14 @@ int ED_operator_screen_mainwinactive(bContext *C)
return 1;
}
+int ED_operator_scene(bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ if (scene)
+ return 1;
+ return 0;
+}
+
int ED_operator_scene_editable(bContext *C)
{
Scene *scene = CTX_data_scene(C);
@@ -160,11 +171,11 @@ int ED_operator_objectmode(bContext *C)
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;
-
+
return 1;
}
@@ -241,20 +252,20 @@ int ED_operator_buttons_active(bContext *C)
int ED_operator_node_active(bContext *C)
{
SpaceNode *snode = CTX_wm_space_node(C);
-
+
if (snode && snode->edittree)
return 1;
-
+
return 0;
}
int ED_operator_node_editable(bContext *C)
{
SpaceNode *snode = CTX_wm_space_node(C);
-
+
if (snode && snode->edittree && !ID_IS_LINKED(snode->edittree))
return 1;
-
+
return 0;
}
@@ -440,15 +451,15 @@ int ED_operator_uvmap(bContext *C)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = NULL;
-
+
if (obedit && obedit->type == OB_MESH) {
em = BKE_editmesh_from_object(obedit);
}
-
+
if (em && (em->bm->totface)) {
return true;
}
-
+
return false;
}
@@ -595,23 +606,23 @@ static ARegion *screen_find_region_type(bContext *C, int type)
/** \name Action Zone Operator
* \{ */
-/* operator state vars used:
+/* operator state vars used:
* none
- *
+ *
* functions:
- *
+ *
* apply() set actionzone event
- *
+ *
* exit() free customdata
- *
+ *
* callbacks:
- *
+ *
* exec() never used
- *
- * invoke() check if in zone
+ *
+ * invoke() check if in zone
* add customdata, put mouseco and area in it
* add modal handler
- *
+ *
* modal() accept modal events while doing it
* call apply() with gesture info, active window, nonactive window
* call exit() and remove handler when LMB confirm
@@ -628,11 +639,11 @@ static int actionzone_area_poll(bContext *C)
{
wmWindow *win = CTX_wm_window(C);
ScrArea *sa = CTX_wm_area(C);
-
+
if (sa && win && win->eventstate) {
const int *xy = &win->eventstate->x;
AZone *az;
-
+
for (az = sa->actionzones.first; az; az = az->next)
if (BLI_rcti_isect_pt_v(&az->rect, xy))
return 1;
@@ -658,117 +669,141 @@ static void fullscreen_click_rcti_init(rcti *rect, const short x1, const short y
BLI_rcti_init(rect, x, x + icon_size, y, y + icon_size);
}
-AZone *is_in_area_actionzone(ScrArea *sa, const int xy[2])
+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) {
/* no triangle intersect but a hotspot circle based on corner */
- int radius = (xy[0] - az->x1) * (xy[0] - az->x1) + (xy[1] - az->y1) * (xy[1] - az->y1);
-
- if (radius <= AZONESPOT * AZONESPOT)
+ int radius_sq = SQUARE(xy[0] - az->x1) + SQUARE(xy[1] - az->y1);
+ if (radius_sq <= SQUARE(AZONESPOT)) {
break;
+ }
}
else if (az->type == AZONE_REGION) {
break;
}
else if (az->type == AZONE_FULLSCREEN) {
- int mouse_radius, spot_radius, fadein_radius, fadeout_radius;
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 (BLI_rcti_isect_pt_v(&click_rect, xy)) {
- az->alpha = 1.0f;
+ if (test_only) {
+ if (click_isect) {
+ break;
+ }
}
else {
- mouse_radius = (xy[0] - az->x2) * (xy[0] - az->x2) + (xy[1] - az->y2) * (xy[1] - az->y2);
- spot_radius = AZONESPOT * AZONESPOT;
- fadein_radius = AZONEFADEIN * AZONEFADEIN;
- fadeout_radius = AZONEFADEOUT * AZONEFADEOUT;
-
- if (mouse_radius < spot_radius) {
+ if (click_isect) {
az->alpha = 1.0f;
}
- else if (mouse_radius < fadein_radius) {
- az->alpha = 1.0f;
- }
- else if (mouse_radius < fadeout_radius) {
- az->alpha = 1.0f - ((float)(mouse_radius - fadein_radius)) / ((float)(fadeout_radius - fadein_radius));
- }
else {
- az->alpha = 0.0f;
+ const int mouse_sq = SQUARE(xy[0] - az->x2) + SQUARE(xy[1] - az->y2);
+ const int spot_sq = SQUARE(AZONESPOT);
+ 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;
}
- /* fade in/out but no click */
- az = NULL;
+ /* XXX force redraw to show/hide the action zone */
+ ED_area_tag_redraw(sa);
+ break;
}
-
- /* 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;
const short isect_value = UI_view2d_mouse_in_scrollers(ar, v2d, xy[0], xy[1]);
- bool redraw = false;
-
- if (isect_value == 'h') {
- if (az->direction == AZ_SCROLL_HOR) {
- az->alpha = 1.0f;
- v2d->alpha_hor = 255;
- v2d->size_hor = V2D_SCROLL_HEIGHT;
- redraw = true;
- }
- }
- else if (isect_value == 'v') {
- if (az->direction == AZ_SCROLL_VERT) {
- az->alpha = 1.0f;
- v2d->alpha_vert = 255;
- v2d->size_vert = V2D_SCROLL_WIDTH;
- redraw = true;
+ if (test_only) {
+ if (isect_value != 0) {
+ break;
}
}
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;
+ bool redraw = false;
- v2d->alpha_hor = alpha * 255;
- v2d->size_hor = round_fl_to_int(V2D_SCROLL_HEIGHT -
- ((V2D_SCROLL_HEIGHT - V2D_SCROLL_HEIGHT_MIN) * dist_fac));
+ if (isect_value == 'h') {
+ if (az->direction == AZ_SCROLL_HOR) {
+ az->alpha = 1.0f;
+ v2d->alpha_hor = 255;
+ v2d->size_hor = V2D_SCROLL_HEIGHT;
+ redraw = true;
+ }
}
- 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;
- v2d->size_vert = round_fl_to_int(V2D_SCROLL_WIDTH -
- ((V2D_SCROLL_WIDTH - V2D_SCROLL_WIDTH_MIN) * dist_fac));
+ else if (isect_value == 'v') {
+ if (az->direction == AZ_SCROLL_VERT) {
+ az->alpha = 1.0f;
+ v2d->alpha_vert = 255;
+ v2d->size_vert = V2D_SCROLL_WIDTH;
+ 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;
+ v2d->size_hor = round_fl_to_int(
+ V2D_SCROLL_HEIGHT -
+ ((V2D_SCROLL_HEIGHT - V2D_SCROLL_HEIGHT_MIN) * dist_fac));
+ }
+ 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;
+ v2d->size_vert = round_fl_to_int(
+ V2D_SCROLL_WIDTH -
+ ((V2D_SCROLL_WIDTH - V2D_SCROLL_WIDTH_MIN) * dist_fac));
+ }
+ az->alpha = alpha;
+ redraw = true;
}
- az->alpha = alpha;
- redraw = true;
- }
- if (redraw) {
- ED_area_tag_redraw(sa);
+ if (redraw) {
+ ED_area_tag_redraw_no_rebuild(sa);
+ }
+ /* Don't return! */
}
- /* Don't return! */
}
}
}
-
+
return az;
}
+AZone *ED_area_actionzone_find_xy(ScrArea *sa, const int xy[2])
+{
+ return area_actionzone_refresh_xy(sa, xy, true);
+}
+
+AZone *ED_area_actionzone_refresh_xy(ScrArea *sa, const int xy[2])
+{
+ return area_actionzone_refresh_xy(sa, xy, false);
+}
static void actionzone_exit(wmOperator *op)
{
@@ -783,9 +818,9 @@ static void actionzone_apply(bContext *C, wmOperator *op, int type)
wmEvent event;
wmWindow *win = CTX_wm_window(C);
sActionzoneData *sad = op->customdata;
-
+
sad->modifier = RNA_int_get(op->ptr, "modifier");
-
+
wm_event_init_from_window(win, &event);
if (type == AZONE_AREA)
@@ -799,39 +834,36 @@ static void actionzone_apply(bContext *C, wmOperator *op, int type)
event.customdata = op->customdata;
event.customdatafree = true;
op->customdata = NULL;
-
+
wm_event_add(win, &event);
}
static int actionzone_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ScrArea *sa = CTX_wm_area(C);
- AZone *az = is_in_area_actionzone(sa, &event->x);
+ AZone *az = ED_area_actionzone_find_xy(sa, &event->x);
sActionzoneData *sad;
-
- /* quick escape */
- if (az == NULL)
+
+ /* 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 actionzone */
sad = op->customdata = MEM_callocN(sizeof(sActionzoneData), "sActionzoneData");
sad->sa1 = sa;
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 if (ELEM(sad->az->type, AZONE_REGION_SCROLL)) {
- return OPERATOR_PASS_THROUGH;
- }
else {
/* add modal handler */
WM_event_add_modal_handler(C, op);
-
+
return OPERATOR_RUNNING_MODAL;
}
}
@@ -839,11 +871,8 @@ static int actionzone_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- wmWindow *win = CTX_wm_window(C);
bScreen *sc = CTX_wm_screen(C);
sActionzoneData *sad = op->customdata;
- const int screen_size_x = WM_window_screen_pixels_x(win);
- const int screen_size_y = WM_window_screen_pixels_y(win);
switch (event->type) {
case MOUSEMOVE:
@@ -862,13 +891,17 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event)
sad->gesture_dir = 's';
else
sad->gesture_dir = 'w';
-
+
if (sad->az->type == AZONE_AREA) {
+ const wmWindow *win = CTX_wm_window(C);
+ rcti screen_rect;
+
+ WM_window_screen_rect_calc(win, &screen_rect);
/* once we drag outside the actionzone, register a gesture
* check we're not on an edge so join finds the other area */
- is_gesture = ((is_in_area_actionzone(sad->sa1, &event->x) != sad->az) &&
- (screen_area_map_find_active_scredge(
- AREAMAP_FROM_SCREEN(sc), screen_size_x, screen_size_y, event->x, event->y) == NULL));
+ is_gesture = ((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));
}
else {
const int delta_min = 1;
@@ -882,7 +915,7 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* apply sends event */
actionzone_apply(C, op, sad->az->type);
actionzone_exit(op);
-
+
return OPERATOR_FINISHED;
}
break;
@@ -893,9 +926,9 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event)
case LEFTMOUSE:
actionzone_exit(op);
return OPERATOR_CANCELLED;
-
+
}
-
+
return OPERATOR_RUNNING_MODAL;
}
@@ -910,15 +943,15 @@ static void SCREEN_OT_actionzone(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
-
+
RNA_def_int(ot->srna, "modifier", 0, 0, 2, "Modifier", "Modifier state", 0, 2);
}
@@ -956,15 +989,15 @@ static int area_swap_init(wmOperator *op, const wmEvent *event)
{
sAreaSwapData *sd = NULL;
sActionzoneData *sad = event->customdata;
-
+
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;
-
+
return 1;
}
@@ -984,22 +1017,22 @@ static void area_swap_cancel(bContext *C, wmOperator *op)
static int area_swap_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
-
+
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;
-
+
}
static int area_swap_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
sActionzoneData *sad = op->customdata;
-
+
switch (event->type) {
case MOUSEMOVE:
/* second area, for join */
@@ -1016,15 +1049,15 @@ static int area_swap_modal(bContext *C, wmOperator *op, const wmEvent *event)
ED_area_tag_redraw(sad->sa2);
ED_area_swapspace(C, sad->sa1, sad->sa2);
-
+
area_swap_exit(C, op);
-
+
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
break;
-
+
case ESCKEY:
area_swap_cancel(C, op);
return OPERATOR_CANCELLED;
@@ -1037,12 +1070,12 @@ 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->invoke = area_swap_invoke;
ot->modal = area_swap_modal;
ot->poll = ED_operator_areaactive;
ot->cancel = area_swap_cancel;
-
+
ot->flag = OPTYPE_BLOCKING;
}
@@ -1057,6 +1090,7 @@ 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);
@@ -1065,18 +1099,18 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event)
bScreen *newsc;
ScrArea *sa;
rcti rect;
-
+
win = CTX_wm_window(C);
scene = CTX_data_scene(C);
sa = CTX_wm_area(C);
-
+
/* XXX hrmf! */
if (event->type == EVT_ACTIONZONE_AREA) {
sActionzoneData *sad = event->customdata;
-
+
if (sad == NULL)
return OPERATOR_PASS_THROUGH;
-
+
sa = sad->sa1;
}
@@ -1098,7 +1132,7 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event)
WM_window_set_active_workspace(newwin, workspace);
/* allocs new screen and adds to newly created window, using window size */
- layout_new = ED_workspace_layout_add(workspace, newwin, BKE_workspace_layout_name_get(layout_old));
+ 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_screen_global_areas_create(newwin);
@@ -1115,7 +1149,7 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event)
finally:
if (event->type == EVT_ACTIONZONE_AREA)
actionzone_exit(op);
-
+
if (newwin) {
return OPERATOR_FINISHED;
}
@@ -1129,7 +1163,7 @@ 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->invoke = area_dupli_invoke;
ot->poll = ED_operator_areaactive;
}
@@ -1140,29 +1174,29 @@ static void SCREEN_OT_area_dupli(wmOperatorType *ot)
/** \name Move Area Edge Operator
* \{ */
-/* operator state vars used:
+/* operator state vars used:
* x, y mouse coord near edge
* delta movement of edge
- *
+ *
* functions:
- *
+ *
* 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
- *
+ *
* exit() cleanup, send notifier
- *
+ *
* cancel() cancel moving
- *
+ *
* callbacks:
- *
+ *
* exec() execute without any user interaction, based on properties
* call init(), apply(), exit()
- *
+ *
* invoke() gets called on mouse click near edge
* call init(), add handler
- *
+ *
* modal() accept modal events while doing it
* call apply() with delta motion
* call exit() and remove handler
@@ -1174,6 +1208,8 @@ typedef struct sAreaMoveData {
enum AreaMoveSnapType {
/* Snapping disabled */
SNAP_NONE = 0,
+ /* Snap to an invisible grid with a unit defined in AREAGRID */
+ SNAP_AREAGRID,
/* Snap to mid-point and adjacent edges. */
SNAP_MIDPOINT_AND_ADJACENT,
/* Snap to either bigger or smaller, nothing in-between (used for
@@ -1184,13 +1220,13 @@ typedef struct sAreaMoveData {
} sAreaMoveData;
/* helper call to move area-edge, sets limits
- * need window size in order to get correct limits */
+ * need window bounds in order to get correct limits */
static void area_move_set_limits(
wmWindow *win, bScreen *sc, int dir,
- const int winsize_x, const int winsize_y,
int *bigger, int *smaller,
bool *use_bigger_smaller_snap)
{
+ rcti window_rect;
int areaminy = ED_area_headersize();
int areamin;
@@ -1200,8 +1236,11 @@ static void area_move_set_limits(
if (use_bigger_smaller_snap != NULL) {
*use_bigger_smaller_snap = false;
for (ScrArea *area = win->global_areas.areabase.first; area; area = area->next) {
- const int size_min = round_fl_to_int(area->global->size_min * UI_DPI_FAC);
- const int size_max = round_fl_to_int(area->global->size_max * UI_DPI_FAC);
+ int size_min = ED_area_global_min_size_y(area) - 1;
+ int size_max = ED_area_global_max_size_y(area) - 1;
+
+ size_min = MAX2(size_min, 0);
+ BLI_assert(size_min < size_max);
/* logic here is only tested for lower edge :) */
/* left edge */
@@ -1235,18 +1274,20 @@ static void area_move_set_limits(
}
}
+ 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 > 0)
+
+ if (sa->v1->vec.y > window_rect.ymin)
areamin += U.pixelsize;
- if (sa->v2->vec.y < winsize_y - 1)
+ if (sa->v2->vec.y < (window_rect.ymax - 1))
areamin += U.pixelsize;
-
- y1 = sa->v2->vec.y - sa->v1->vec.y + 1 - areamin;
-
+
+ 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);
@@ -1256,14 +1297,14 @@ static void area_move_set_limits(
else {
int x1;
areamin = AREAMINX;
-
- if (sa->v1->vec.x > 0)
+
+ if (sa->v1->vec.x > window_rect.xmin)
areamin += U.pixelsize;
- if (sa->v4->vec.x < winsize_x - 1)
+ if (sa->v4->vec.x < (window_rect.xmax - 1))
areamin += U.pixelsize;
-
- x1 = sa->v4->vec.x - sa->v1->vec.x + 1 - areamin;
-
+
+ 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);
@@ -1281,37 +1322,33 @@ static int area_move_init(bContext *C, wmOperator *op)
wmWindow *win = CTX_wm_window(C);
ScrEdge *actedge;
sAreaMoveData *md;
- const int screen_size_x = WM_window_screen_pixels_x(win);
- const int screen_size_y = WM_window_screen_pixels_y(win);
int x, y;
-
+
/* required properties */
x = RNA_int_get(op->ptr, "x");
y = RNA_int_get(op->ptr, "y");
-
+
/* setup */
- actedge = screen_find_active_scredge(win, sc, x, y);
+ 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 = scredge_is_horizontal(actedge) ? 'h' : 'v';
+
+ 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;
-
- select_connected_scredge(win, actedge);
+
+ 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, screen_size_x, screen_size_y,
- &md->bigger, &md->smaller,
- &use_bigger_smaller_snap);
+ 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_NONE;
+ md->snap_type = use_bigger_smaller_snap ? SNAP_BIGGER_SMALLER_ONLY : SNAP_AREAGRID;
return 1;
}
@@ -1322,30 +1359,44 @@ static int area_snap_calc_location(
const int bigger, const int smaller)
{
BLI_assert(snap_type != SNAP_NONE);
- if (snap_type == SNAP_BIGGER_SMALLER_ONLY) {
- return ((origval + delta) >= bigger) ? bigger : smaller;
- }
-
int final_loc = -1;
const int m_loc = origval + delta;
- const int axis = (dir == 'v') ? 0 : 1;
- int snap_dist;
- int dist;
- {
- /* Test the snap to middle. */
- int middle = origval + (bigger - smaller) / 2;
- middle -= (middle % AREAGRID);
- snap_dist = abs(m_loc - middle);
- final_loc = middle;
- }
+ switch (snap_type) {
+ case SNAP_AREAGRID:
+ final_loc = m_loc;
+ if (delta != bigger && delta != -smaller) {
+ final_loc -= (m_loc % AREAGRID);
+ CLAMP(final_loc, origval - smaller, origval + bigger);
+ }
+ break;
- for (const ScrVert *v1 = sc->vertbase.first; v1; v1 = v1->next) {
- if (v1->editflag) {
- const int v_loc = (&v1->vec.x)[!axis];
+ case SNAP_BIGGER_SMALLER_ONLY:
+ final_loc = (m_loc >= bigger) ? bigger : smaller;
+ break;
- for (const ScrVert *v2 = sc->vertbase.first; v2; v2 = v2->next) {
- if (!v2->editflag) {
+ case SNAP_MIDPOINT_AND_ADJACENT:
+ {
+ const int axis = (dir == 'v') ? 0 : 1;
+ int snap_dist;
+ int dist;
+ {
+ /* Test the snap to middle. */
+ int middle = origval + (bigger - smaller) / 2;
+ snap_dist = abs(m_loc - middle);
+ final_loc = middle;
+ }
+
+ 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. */
@@ -1359,9 +1410,15 @@ static int area_snap_calc_location(
}
}
}
+ break;
}
+ case SNAP_NONE:
+ break;
}
+ BLI_assert(ELEM(snap_type, SNAP_BIGGER_SMALLER_ONLY) ||
+ IN_RANGE_INCL(final_loc, origval - smaller, origval + bigger));
+
return final_loc;
}
@@ -1374,16 +1431,15 @@ static void area_move_apply_do(
{
wmWindow *win = CTX_wm_window(C);
bScreen *sc = CTX_wm_screen(C);
+ short final_loc = -1;
bool doredraw = false;
- CLAMP(delta, -smaller, bigger);
- short final_loc = -1;
+ if (snap_type != SNAP_BIGGER_SMALLER_ONLY) {
+ CLAMP(delta, -smaller, bigger);
+ }
if (snap_type == SNAP_NONE) {
final_loc = origval + delta;
- if (delta != bigger && delta != -smaller) {
- final_loc -= (final_loc % AREAGRID);
- }
}
else {
final_loc = area_snap_calc_location(sc, snap_type, delta, origval, dir, bigger, smaller);
@@ -1411,7 +1467,7 @@ static void area_move_apply_do(
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)) {
- sa->global->cur_fixed_height = round_fl_to_int((sa->v2->vec.y - sa->v1->vec.y) / UI_DPI_FAC);
+ sa->global->cur_fixed_height = round_fl_to_int(screen_geom_area_height(sa) / UI_DPI_FAC);
sc->do_refresh = true;
redraw_all = true;
}
@@ -1443,7 +1499,7 @@ static void area_move_exit(bContext *C, wmOperator *op)
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));
@@ -1453,10 +1509,10 @@ static int area_move_exec(bContext *C, wmOperator *op)
{
if (!area_move_init(C, op))
return OPERATOR_CANCELLED;
-
+
area_move_apply(C, op);
area_move_exit(C, op);
-
+
return OPERATOR_FINISHED;
}
@@ -1465,19 +1521,19 @@ 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);
-
- if (!area_move_init(C, op))
+
+ if (!area_move_init(C, op))
return OPERATOR_PASS_THROUGH;
-
+
/* add temp handler */
WM_event_add_modal_handler(C, op);
-
+
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);
@@ -1488,17 +1544,17 @@ 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;
}
@@ -1508,26 +1564,27 @@ static int area_move_modal(bContext *C, wmOperator *op, const wmEvent *event)
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_NONE) {
+ if (md->snap_type != SNAP_BIGGER_SMALLER_ONLY) {
md->snap_type = SNAP_MIDPOINT_AND_ADJACENT;
}
break;
+
case KM_MODAL_SNAP_OFF:
- if (md->snap_type == SNAP_MIDPOINT_AND_ADJACENT) {
- md->snap_type = SNAP_NONE;
+ if (md->snap_type != SNAP_BIGGER_SMALLER_ONLY) {
+ md->snap_type = SNAP_AREAGRID;
}
break;
}
break;
}
}
-
+
return OPERATOR_RUNNING_MODAL;
}
@@ -1537,16 +1594,16 @@ static void SCREEN_OT_area_move(wmOperatorType *ot)
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 */
-
+
/* 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);
@@ -1605,7 +1662,7 @@ typedef struct sAreaSplitData {
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)
@@ -1625,11 +1682,11 @@ static void area_split_draw_cb(const struct wmWindow *UNUSED(win), void *userdat
static int area_split_menu_init(bContext *C, wmOperator *op)
{
sAreaSplitData *sd;
-
+
/* custom data */
sd = (sAreaSplitData *)MEM_callocN(sizeof(sAreaSplitData), "op_area_split");
op->customdata = sd;
-
+
sd->sarea = CTX_wm_area(C);
return 1;
@@ -1640,27 +1697,33 @@ static int area_split_init(bContext *C, wmOperator *op)
{
ScrArea *sa = CTX_wm_area(C);
sAreaSplitData *sd;
- int areaminy = ED_area_headersize() + 1;
+ int areaminy = ED_area_headersize();
int dir;
-
+
/* required context */
if (sa == NULL) return 0;
-
+
/* 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;
-
+
/* custom data */
sd = (sAreaSplitData *)MEM_callocN(sizeof(sAreaSplitData), "op_area_split");
op->customdata = sd;
-
+
sd->sarea = sa;
- sd->origsize = dir == 'v' ? sa->winx : sa->winy;
- sd->origmin = dir == 'v' ? sa->totrct.xmin : sa->totrct.ymin;
-
+ 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;
}
@@ -1676,7 +1739,7 @@ static ScrEdge *area_findsharededge(bScreen *screen, ScrArea *sa, ScrArea *sb)
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);
}
@@ -1689,7 +1752,7 @@ static ScrEdge *area_findsharededge(bScreen *screen, ScrArea *sa, ScrArea *sb)
else if (sav1 == sbv2 && sav4 == sbv3) { /* sa on top of sb = S*/
return BKE_screen_find_edge(screen, sav1, sav4);
}
-
+
return NULL;
}
@@ -1697,28 +1760,28 @@ static ScrEdge *area_findsharededge(bScreen *screen, ScrArea *sa, ScrArea *sb)
/* 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;
-
+
fac = RNA_float_get(op->ptr, "factor");
dir = RNA_enum_get(op->ptr, "direction");
-
- sd->narea = area_split(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) {
- ScrVert *sv;
-
sd->nedge = area_findsharededge(sc, sd->sarea, sd->narea);
-
+
/* select newly created edge, prepare for moving edge */
- for (sv = sc->vertbase.first; sv; sv = sv->next)
+ ED_screen_verts_iter(win, sc, sv) {
sv->editflag = 0;
-
+ }
+
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;
@@ -1731,7 +1794,7 @@ static int area_split_apply(bContext *C, wmOperator *op)
return 1;
}
-
+
return 0;
}
@@ -1748,10 +1811,10 @@ static void area_split_exit(bContext *C, wmOperator *op)
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);
-
+
/* 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));
@@ -1770,29 +1833,27 @@ 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;
- const int screen_size_x = WM_window_screen_pixels_x(win);
- const int screen_size_y = WM_window_screen_pixels_y(win);
int dir;
-
+
/* no full window splitting allowed */
if (sc->state != SCREENNORMAL)
return OPERATOR_CANCELLED;
-
+
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;
-
+
/* prepare operator state vars */
if (sad->gesture_dir == 'n' || sad->gesture_dir == 's') {
dir = 'h';
@@ -1803,52 +1864,55 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
RNA_float_set(op->ptr, "factor", ((float)(event->y - sad->sa1->v1->vec.y)) / (float)sad->sa1->winy);
}
RNA_enum_set(op->ptr, "direction", dir);
-
+
/* general init, also non-UI case, adds customdata, sets area and defaults */
if (!area_split_init(C, op))
return OPERATOR_PASS_THROUGH;
-
+
}
else {
ScrEdge *actedge;
+ rcti screen_rect;
int x, y;
-
+
/* retrieve initial mouse coord, so we can find the active edge */
if (RNA_struct_property_is_set(op->ptr, "mouse_x"))
x = RNA_int_get(op->ptr, "mouse_x");
else
x = event->x;
-
+
if (RNA_struct_property_is_set(op->ptr, "mouse_y"))
y = RNA_int_get(op->ptr, "mouse_y");
else
y = event->x;
-
- actedge = screen_area_map_find_active_scredge(AREAMAP_FROM_SCREEN(sc), screen_size_x, screen_size_y, x, y);
+
+ WM_window_screen_rect_calc(win, &screen_rect);
+
+ actedge = screen_geom_area_map_find_active_scredge(AREAMAP_FROM_SCREEN(sc), &screen_rect, x, y);
if (actedge == NULL)
return OPERATOR_CANCELLED;
-
- dir = scredge_is_horizontal(actedge) ? 'v' : 'h';
-
+
+ dir = screen_geom_edge_is_horizontal(actedge) ? 'v' : 'h';
+
RNA_enum_set(op->ptr, "direction", 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, screen_size_x, screen_size_y, &sd->bigger, &sd->smaller, NULL);
-
+ 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;
}
}
@@ -1860,22 +1924,22 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
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;
-
+
area_split_apply(C, op);
area_split_exit(C, op);
-
+
return OPERATOR_FINISHED;
}
@@ -1883,7 +1947,7 @@ static int area_split_exec(bContext *C, wmOperator *op)
static void area_split_cancel(bContext *C, wmOperator *op)
{
sAreaSplitData *sd = (sAreaSplitData *)op->customdata;
-
+
if (sd->previewmode) {
/* pass */
}
@@ -1924,7 +1988,7 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
}
break;
-
+
case MIDDLEMOUSE:
case TABKEY:
if (sd->previewmode == 0) {
@@ -1940,9 +2004,9 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
}
}
-
+
break;
-
+
case RIGHTMOUSE: /* cancel operation */
case ESCKEY:
area_split_cancel(C, op);
@@ -1978,12 +2042,12 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (sd->sarea) {
ScrArea *sa = sd->sarea;
if (dir == 'v') {
- sd->origsize = sa->winx;
- sd->origmin = sa->totrct.xmin;
+ sd->origmin = sa->v1->vec.x;
+ sd->origsize = sa->v4->vec.x - sd->origmin;
}
else {
- sd->origsize = sa->winy;
- sd->origmin = sa->totrct.ymin;
+ sd->origmin = sa->v1->vec.y;
+ sd->origsize = sa->v2->vec.y - sd->origmin;
}
if (sd->do_snap) {
@@ -2021,17 +2085,17 @@ 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->exec = area_split_exec;
ot->invoke = area_split_invoke;
ot->modal = area_split_modal;
ot->cancel = area_split_cancel;
-
+
ot->poll = screen_active_editable;
/* 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);
@@ -2053,7 +2117,7 @@ typedef struct RegionMoveData {
int origx, origy;
int maxsize;
AZEdge edge;
-
+
} RegionMoveData;
@@ -2061,20 +2125,20 @@ static int area_max_regionsize(ScrArea *sa, ARegion *scalear, AZEdge edge)
{
ARegion *ar;
int dist;
-
+
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
+
+ /* subtractwidth of regions on opposite side
* prevents dragging regions into other opposite regions */
for (ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar == scalear)
continue;
-
+
if (scalear->alignment == RGN_ALIGN_TOP && ar->alignment == RGN_ALIGN_BOTTOM)
dist -= ar->winy;
else if (scalear->alignment == RGN_ALIGN_BOTTOM && ar->alignment == RGN_ALIGN_TOP)
@@ -2083,7 +2147,7 @@ static int area_max_regionsize(ScrArea *sa, ARegion *scalear, AZEdge edge)
dist -= ar->winx;
else if (scalear->alignment == RGN_ALIGN_RIGHT && ar->alignment == RGN_ALIGN_LEFT)
dist -= ar->winx;
-
+
/* case of regions in regions, like operator properties panel */
/* these can sit on top of other regions such as headers, so account for this */
else if (edge == AE_BOTTOM_TO_TOPLEFT && scalear->alignment & RGN_ALIGN_TOP &&
@@ -2105,20 +2169,20 @@ static int region_scale_invoke(bContext *C, wmOperator *op, const wmEvent *event
{
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;
}
-
+
az = sad->az;
-
+
if (az->ar) {
RegionMoveData *rmd = MEM_callocN(sizeof(RegionMoveData), "RegionMoveData");
int maxsize;
-
+
op->customdata = rmd;
-
+
rmd->az = az;
rmd->ar = az->ar;
rmd->sa = sad->sa1;
@@ -2126,13 +2190,13 @@ static int region_scale_invoke(bContext *C, wmOperator *op, const wmEvent *event
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;
-
+
/* now copy to regionmovedata */
if (rmd->edge == AE_LEFT_TO_TOPRIGHT || rmd->edge == AE_RIGHT_TO_TOPLEFT) {
rmd->origval = rmd->ar->sizex;
@@ -2140,21 +2204,21 @@ static int region_scale_invoke(bContext *C, wmOperator *op, const wmEvent *event
else {
rmd->origval = rmd->ar->sizey;
}
-
+
/* limit headers to standard height for now */
if (rmd->ar->regiontype == RGN_TYPE_HEADER)
maxsize = ED_area_headersize();
else
maxsize = 1000;
-
+
CLAMP(rmd->maxsize, 0, maxsize);
-
+
/* add temp handler */
WM_event_add_modal_handler(C, op);
-
+
return OPERATOR_RUNNING_MODAL;
}
-
+
return OPERATOR_FINISHED;
}
@@ -2210,20 +2274,20 @@ 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 * 3) / aspect;
+ 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) {
@@ -2246,7 +2310,7 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event)
int maxsize = region_scale_get_maxsize(rmd);
delta = event->y - rmd->origy;
if (rmd->edge == AE_BOTTOM_TO_TOPLEFT) delta = -delta;
-
+
/* region sizes now get multiplied */
delta /= UI_DPI_FAC;
@@ -2268,19 +2332,19 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (!(rmd->ar->flag & RGN_FLAG_HIDDEN))
region_scale_toggle_hidden(C, rmd);
}
- else if (maxsize > 0 && (rmd->ar->sizey > maxsize))
+ else if (maxsize > 0 && (rmd->ar->sizey > maxsize))
rmd->ar->sizey = maxsize;
else if (rmd->ar->flag & RGN_FLAG_HIDDEN)
region_scale_toggle_hidden(C, rmd);
}
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 (ABS(event->x - rmd->origx) < 2 && ABS(event->y - rmd->origy) < 2) {
if (rmd->ar->flag & RGN_FLAG_HIDDEN) {
region_scale_toggle_hidden(C, rmd);
@@ -2294,15 +2358,15 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
MEM_freeN(op->customdata);
op->customdata = NULL;
-
+
return OPERATOR_FINISHED;
}
break;
-
+
case ESCKEY:
break;
}
-
+
return OPERATOR_RUNNING_MODAL;
}
@@ -2318,13 +2382,13 @@ static void SCREEN_OT_region_scale(wmOperatorType *ot)
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->poll = ED_operator_areaactive;
-
+
/* flags */
ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
}
@@ -2382,19 +2446,19 @@ static int frame_offset_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
int delta;
-
+
delta = RNA_int_get(op->ptr, "delta");
CFRA += delta;
FRAMENUMBER_MIN_CLAMP(CFRA);
SUBFRA = 0.f;
-
+
areas_do_frame_follow(C, false);
BKE_sound_seek_scene(bmain, scene);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
-
+
return OPERATOR_FINISHED;
}
@@ -2403,13 +2467,13 @@ 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->exec = frame_offset_exec;
-
+
ot->poll = ED_operator_screenactive_norender;
ot->flag = OPTYPE_UNDO_GROUPED;
- ot->undo_group = "FRAME_CHANGE";
-
+ ot->undo_group = "Frame Change";
+
/* rna */
RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
}
@@ -2433,9 +2497,9 @@ static int frame_jump_exec(bContext *C, wmOperator *op)
*/
if (animtimer) {
ScreenAnimData *sad = animtimer->customdata;
-
+
sad->flag |= ANIMPLAY_FLAG_USE_NEXT_FRAME;
-
+
if (RNA_boolean_get(op->ptr, "end"))
sad->nextfra = PEFRA;
else
@@ -2446,14 +2510,14 @@ static int frame_jump_exec(bContext *C, wmOperator *op)
CFRA = PEFRA;
else
CFRA = PSFRA;
-
+
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;
}
@@ -2462,13 +2526,13 @@ 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->exec = frame_jump_exec;
-
+
ot->poll = ED_operator_screenactive_norender;
ot->flag = OPTYPE_UNDO_GROUPED;
- ot->undo_group = "FRAME_CHANGE";
-
+ ot->undo_group = "Frame Change";
+
/* rna */
RNA_def_boolean(ot->srna, "end", 0, "Last Frame", "Jump to the last frame of the frame range");
}
@@ -2491,7 +2555,7 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op)
float cfra;
const bool next = RNA_boolean_get(op->ptr, "next");
bool done = false;
-
+
/* sanity checks */
if (scene == NULL)
return OPERATOR_CANCELLED;
@@ -2500,13 +2564,13 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op)
/* 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, NULL);
gpencil_to_keylist(&ads, scene->gpd, &keys);
@@ -2515,7 +2579,7 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op)
ob_to_keylist(&ads, ob, &keys, NULL);
gpencil_to_keylist(&ads, ob->gpd, &keys);
}
-
+
{
Mask *mask = CTX_data_edit_mask(C);
if (mask) {
@@ -2526,13 +2590,13 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op)
/* build linked-list for searching */
BLI_dlrbTree_linkedlist_sync(&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 */
@@ -2549,7 +2613,7 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op)
}
}
}
-
+
/* free temp stuff */
BLI_dlrbTree_free(&keys);
@@ -2575,13 +2639,13 @@ 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->exec = keyframe_jump_exec;
-
+
ot->poll = ED_operator_screenactive_norender;
ot->flag = OPTYPE_UNDO_GROUPED;
- ot->undo_group = "FRAME_CHANGE";
-
+ ot->undo_group = "Frame Change";
+
/* properties */
RNA_def_boolean(ot->srna, "next", true, "Next Keyframe", "");
}
@@ -2647,7 +2711,7 @@ static void SCREEN_OT_marker_jump(wmOperatorType *ot)
ot->poll = ED_operator_screenactive_norender;
ot->flag = OPTYPE_UNDO_GROUPED;
- ot->undo_group = "FRAME_CHANGE";
+ ot->undo_group = "Frame Change";
/* properties */
RNA_def_boolean(ot->srna, "next", true, "Next Marker", "");
@@ -2677,7 +2741,7 @@ 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->exec = screen_set_exec;
ot->poll = ED_operator_screenactive;
@@ -2697,17 +2761,17 @@ 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;
@@ -2729,7 +2793,8 @@ static int 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) &&
- ((screen->state != SCREENNORMAL) || (area->spacetype != SPACE_TOPBAR));
+ /* 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)
@@ -2739,7 +2804,7 @@ static void SCREEN_OT_screen_full_area(wmOperatorType *ot)
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;
@@ -2754,28 +2819,28 @@ static void SCREEN_OT_screen_full_area(wmOperatorType *ot)
/** \name Screen Join-Area Operator
* \{ */
-/* operator state vars used:
+/* operator state vars used:
* x1, y1 mouse coord in first area, which will disappear
* x2, y2 mouse coord in 2nd area, which will become joined
- *
+ *
* functions:
- *
- * init() find edge based on state vars
- * test if the edge divides two areas,
+ *
+ * init() find edge based on state vars
+ * test if the edge divides two areas,
* store active and nonactive area,
- *
+ *
* apply() do the actual join
- *
+ *
* 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
* call apply() with active window and nonactive window
* call exit() and remove handler when LMB confirm
@@ -2809,18 +2874,18 @@ static int area_join_init(bContext *C, wmOperator *op)
int x1, y1;
int x2, y2;
int shared = 0;
-
+
/* 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(CTX_wm_screen(C), SPACE_TYPE_ANY, x1, y1);
sa2 = BKE_screen_find_area_xy(CTX_wm_screen(C), SPACE_TYPE_ANY, x2, y2);
if (sa1 == NULL || sa2 == NULL || sa1 == sa2)
return 0;
-
+
/* do areas share an edge? */
if (sa1->v1 == sa2->v1 || sa1->v1 == sa2->v2 || sa1->v1 == sa2->v3 || sa1->v1 == sa2->v4) shared++;
if (sa1->v2 == sa2->v1 || sa1->v2 == sa2->v2 || sa1->v2 == sa2->v3 || sa1->v2 == sa2->v4) shared++;
@@ -2830,7 +2895,7 @@ static int area_join_init(bContext *C, wmOperator *op)
printf("areas don't share edge\n");
return 0;
}
-
+
jd = (sAreaJoinData *)MEM_callocN(sizeof(sAreaJoinData), "op_area_join");
jd->sa1 = sa1;
@@ -2848,7 +2913,7 @@ static int area_join_apply(bContext *C, wmOperator *op)
{
sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
if (!jd) return 0;
-
+
if (!screen_area_join(C, CTX_wm_screen(C), jd->sa1, jd->sa2)) {
return 0;
}
@@ -2856,7 +2921,7 @@ static int area_join_apply(bContext *C, wmOperator *op)
CTX_wm_area_set(C, NULL);
CTX_wm_region_set(C, NULL);
}
-
+
return 1;
}
@@ -2872,7 +2937,7 @@ static void area_join_exit(bContext *C, wmOperator *op)
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));
@@ -2881,55 +2946,55 @@ static void area_join_exit(bContext *C, wmOperator *op)
static int area_join_exec(bContext *C, wmOperator *op)
{
- if (!area_join_init(C, op))
+ if (!area_join_init(C, op))
return OPERATOR_CANCELLED;
-
+
area_join_apply(C, op);
area_join_exit(C, op);
-
+
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 (sad == NULL || sad->modifier > 0) {
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;
-
+
/* prepare operator state vars */
RNA_int_set(op->ptr, "min_x", sad->x);
RNA_int_set(op->ptr, "min_y", sad->y);
RNA_int_set(op->ptr, "max_x", event->x);
RNA_int_set(op->ptr, "max_y", event->y);
}
-
-
- if (!area_join_init(C, op))
+
+
+ if (!area_join_init(C, op))
return OPERATOR_PASS_THROUGH;
-
+
/* add temp handler */
WM_event_add_modal_handler(C, op);
-
+
return OPERATOR_RUNNING_MODAL;
}
static void area_join_cancel(bContext *C, wmOperator *op)
{
WM_event_add_notifier(C, NC_WINDOW, NULL);
-
+
area_join_exit(C, op);
}
@@ -2938,15 +3003,15 @@ static int area_join_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
bScreen *sc = CTX_wm_screen(C);
sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
-
+
/* execute the events */
switch (event->type) {
-
- case MOUSEMOVE:
+
+ case MOUSEMOVE:
{
ScrArea *sa = BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, event->x, event->y);
int dir;
-
+
if (sa) {
if (jd->sa1 != sa) {
dir = area_getorientation(jd->sa1, sa);
@@ -2954,7 +3019,7 @@ static int area_join_modal(bContext *C, wmOperator *op, const wmEvent *event)
jd->sa2 = sa;
}
else {
- /* we are not bordering on the previously selected area
+ /* 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.
*/
@@ -2970,7 +3035,7 @@ static int area_join_modal(bContext *C, wmOperator *op, const wmEvent *event)
WM_event_add_notifier(C, NC_WINDOW, NULL);
}
else {
- /* we are back in the area previously selected for keeping
+ /* 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;
@@ -3002,13 +3067,13 @@ static int area_join_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_FINISHED;
}
break;
-
+
case RIGHTMOUSE:
case ESCKEY:
area_join_cancel(C, op);
return OPERATOR_CANCELLED;
}
-
+
return OPERATOR_RUNNING_MODAL;
}
@@ -3019,17 +3084,17 @@ static void SCREEN_OT_area_join(wmOperatorType *ot)
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;
-
+
/* 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);
@@ -3045,23 +3110,22 @@ static void SCREEN_OT_area_join(wmOperatorType *ot)
static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- wmWindow *win = CTX_wm_window(C);
- bScreen *sc = CTX_wm_screen(C);
+ const wmWindow *win = CTX_wm_window(C);
+ const bScreen *sc = CTX_wm_screen(C);
uiPopupMenu *pup;
uiLayout *layout;
PointerRNA ptr;
ScrEdge *actedge;
- const int screen_size_x = WM_window_screen_pixels_x(win);
- const int screen_size_y = WM_window_screen_pixels_y(win);
+ rcti screen_rect;
+
+ WM_window_screen_rect_calc(win, &screen_rect);
+ actedge = screen_geom_area_map_find_active_scredge(AREAMAP_FROM_SCREEN(sc), &screen_rect, event->x, event->y);
- actedge = screen_area_map_find_active_scredge(
- AREAMAP_FROM_SCREEN(sc), screen_size_x, screen_size_y, event->x, event->y);
-
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);
-
+
uiItemFullO(layout, "SCREEN_OT_area_split", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, &ptr);
/* store initial mouse cursor position */
RNA_int_set(&ptr, "mouse_x", event->x);
@@ -3073,9 +3137,9 @@ static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent
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);
-
+
return OPERATOR_INTERFACE;
}
@@ -3085,10 +3149,10 @@ static void SCREEN_OT_area_options(wmOperatorType *ot)
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;
-
+
ot->poll = ED_operator_screen_mainwinactive;
/* flags */
@@ -3107,7 +3171,7 @@ static int spacedata_cleanup_exec(bContext *C, wmOperator *op)
bScreen *screen;
ScrArea *sa;
int tot = 0;
-
+
for (screen = bmain->screen.first; screen; screen = screen->id.next) {
for (sa = screen->areabase.first; sa; sa = sa->next) {
if (sa->spacedata.first != sa->spacedata.last) {
@@ -3121,7 +3185,7 @@ static int spacedata_cleanup_exec(bContext *C, wmOperator *op)
}
}
BKE_reportf(op->reports, RPT_INFO, "Removed amount of editors: %d", tot);
-
+
return OPERATOR_FINISHED;
}
@@ -3131,11 +3195,11 @@ static void SCREEN_OT_spacedata_cleanup(wmOperatorType *ot)
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;
-
+
}
/** \} */
@@ -3163,7 +3227,7 @@ static int repeat_last_exec(bContext *C, wmOperator *UNUSED(op))
WM_operator_free_all_after(wm, lastop);
WM_operator_repeat(C, lastop);
}
-
+
return OPERATOR_CANCELLED;
}
@@ -3173,12 +3237,12 @@ static void SCREEN_OT_repeat_last(wmOperatorType *ot)
ot->name = "Repeat Last";
ot->description = "Repeat last action";
ot->idname = "SCREEN_OT_repeat_last";
-
+
/* api callbacks */
ot->exec = repeat_last_exec;
-
+
ot->poll = ED_operator_screenactive;
-
+
}
/** \} */
@@ -3194,37 +3258,37 @@ static int repeat_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNU
uiPopupMenu *pup;
uiLayout *layout;
int items, i;
-
+
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);
-
+
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);
-
+
return OPERATOR_INTERFACE;
}
static int repeat_history_exec(bContext *C, wmOperator *op)
{
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);
-
+
WM_operator_repeat(C, op);
}
-
+
return OPERATOR_FINISHED;
}
@@ -3234,13 +3298,13 @@ static void SCREEN_OT_repeat_history(wmOperatorType *ot)
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;
-
+
ot->poll = ED_operator_screenactive;
-
+
RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, 1000);
}
@@ -3253,10 +3317,10 @@ 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);
-
+
if (lastop)
WM_operator_redo_popup(C, lastop);
-
+
return OPERATOR_CANCELLED;
}
@@ -3266,10 +3330,10 @@ static void SCREEN_OT_redo_last(wmOperatorType *ot)
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;
-
+
ot->poll = ED_operator_screenactive;
}
@@ -3312,7 +3376,7 @@ static void region_quadview_init_rv3d(ScrArea *sa, ARegion *ar,
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");
@@ -3321,10 +3385,10 @@ static int region_quadview_exec(bContext *C, wmOperator *op)
/* 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;
@@ -3354,7 +3418,7 @@ static int region_quadview_exec(bContext *C, wmOperator *op)
}
}
}
-
+
for (ar = sa->regionbase.first; ar; ar = arn) {
arn = ar->next;
if (ar->alignment == RGN_ALIGN_QSPLIT) {
@@ -3375,14 +3439,14 @@ static int region_quadview_exec(bContext *C, wmOperator *op)
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;
@@ -3412,8 +3476,8 @@ static int region_quadview_exec(bContext *C, wmOperator *op)
ED_area_tag_redraw(sa);
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
}
-
-
+
+
return OPERATOR_FINISHED;
}
@@ -3423,7 +3487,7 @@ static void SCREEN_OT_region_quadview(wmOperatorType *ot)
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;
@@ -3440,10 +3504,10 @@ static void SCREEN_OT_region_quadview(wmOperatorType *ot)
static int region_flip_exec(bContext *C, wmOperator *UNUSED(op))
{
ARegion *ar = CTX_wm_region(C);
-
+
if (!ar)
return OPERATOR_CANCELLED;
-
+
if (ar->alignment == RGN_ALIGN_TOP)
ar->alignment = RGN_ALIGN_BOTTOM;
else if (ar->alignment == RGN_ALIGN_BOTTOM)
@@ -3455,7 +3519,7 @@ static int region_flip_exec(bContext *C, wmOperator *UNUSED(op))
ED_area_tag_redraw(CTX_wm_area(C));
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -3478,7 +3542,7 @@ static void SCREEN_OT_region_flip(wmOperatorType *ot)
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;
@@ -3545,7 +3609,7 @@ static void SCREEN_OT_header_toggle_menus(wmOperatorType *ot)
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;
@@ -3564,6 +3628,8 @@ void ED_screens_header_tools_menu_create(bContext *C, uiLayout *layout, void *UN
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 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);
@@ -3582,7 +3648,7 @@ void ED_screens_header_tools_menu_create(bContext *C, uiLayout *layout, void *UN
}
}
-static int header_toolbox_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;
@@ -3597,15 +3663,15 @@ static int header_toolbox_invoke(bContext *C, wmOperator *UNUSED(op), const wmEv
return OPERATOR_INTERFACE;
}
-static void SCREEN_OT_header_toolbox(wmOperatorType *ot)
+static void SCREEN_OT_header_context_menu(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Header Toolbox";
- ot->description = "Display header region toolbox";
- ot->idname = "SCREEN_OT_header_toolbox";
-
+ ot->name = "Header Context Menu";
+ ot->description = "Display header region context menu";
+ ot->idname = "SCREEN_OT_header_context_menu";
+
/* api callbacks */
- ot->invoke = header_toolbox_invoke;
+ ot->invoke = header_context_menu_invoke;
}
/** \} */
@@ -3624,14 +3690,14 @@ static int match_area_with_refresh(int spacetype, int refresh)
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)
@@ -3669,7 +3735,7 @@ static int match_region_with_redraws(int spacetype, int regiontype, int redraws,
if ((redraws & TIME_CLIPS) || from_anim_edit)
return 1;
break;
-
+
}
}
else if (regiontype == RGN_TYPE_CHANNELS) {
@@ -3734,12 +3800,12 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
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)))
@@ -3785,12 +3851,12 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
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) {
@@ -3828,14 +3894,14 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
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;
#endif
}
-
+
/* since we follow drawflags, we can't send notifier but tag regions ourselves */
ED_update_for_newframe(bmain, depsgraph);
@@ -3874,24 +3940,24 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
}
}
}
-
+
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.
+
+ /* 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 timestep 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;
@@ -3903,12 +3969,12 @@ static void SCREEN_OT_animation_step(wmOperatorType *ot)
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;
-
+
}
/** \} */
@@ -3962,16 +4028,16 @@ int ED_screen_animation_play(bContext *C, int sync, int mode)
}
else {
int refresh = SPACE_ACTION; /* these settings are currently only available from a menu in the TimeLine */
-
+
if (mode == 1) /* XXX only play audio forwards!? */
BKE_sound_play_scene(scene);
-
+
ED_screen_animation_timer(C, screen->redraws_flag, refresh, sync, mode);
-
+
if (screen->animtimer) {
wmTimer *wt = screen->animtimer;
ScreenAnimData *sad = wt->customdata;
-
+
sad->ar = CTX_wm_region(C);
}
}
@@ -3983,10 +4049,10 @@ static int screen_animation_play_exec(bContext *C, wmOperator *op)
{
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"));
-
+
return ED_screen_animation_play(C, sync, mode);
}
@@ -3998,12 +4064,12 @@ static void SCREEN_OT_animation_play(wmOperatorType *ot)
ot->name = "Play Animation";
ot->description = "Play animation";
ot->idname = "SCREEN_OT_animation_play";
-
+
/* api callbacks */
ot->exec = screen_animation_play_exec;
-
+
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");
@@ -4046,10 +4112,10 @@ static void SCREEN_OT_animation_cancel(wmOperatorType *ot)
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;
-
+
ot->poll = ED_operator_screenactive;
RNA_def_boolean(ot->srna, "restore_frame", true, "Restore Frame", "Restore the frame when animation was initialized");
@@ -4061,36 +4127,36 @@ static void SCREEN_OT_animation_cancel(wmOperatorType *ot)
/** \name Border Select Operator (Template)
* \{ */
-/* operator state vars used: (added by default WM callbacks)
- * xmin, ymin
- * xmax, ymax
- *
+/* operator state vars used: (added by default WM callbacks)
+ * xmin, ymin
+ * xmax, ymax
+ *
* customdata: the wmGesture pointer
- *
+ *
* callbacks:
- *
+ *
* 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
*/
#if 0
static int border_select_exec(bContext *C, wmOperator *op)
{
int event_type = RNA_int_get(op->ptr, "event_type");
-
+
if (event_type == LEFTMOUSE)
printf("border select do select\n");
else if (event_type == RIGHTMOUSE)
printf("border select deselect\n");
- else
+ else
printf("border select do something\n");
-
+
return 1;
}
@@ -4099,15 +4165,15 @@ static void SCREEN_OT_border_select(wmOperatorType *ot)
/* identifiers */
ot->name = "Border Select";
ot->idname = "SCREEN_OT_border_select";
-
+
/* api callbacks */
ot->exec = border_select_exec;
ot->invoke = WM_gesture_border_invoke;
ot->modal = WM_gesture_border_modal;
ot->cancel = WM_gesture_border_cancel;
-
+
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);
@@ -4127,7 +4193,7 @@ static int fullscreen_back_exec(bContext *C, wmOperator *op)
{
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;
@@ -4148,7 +4214,7 @@ static void SCREEN_OT_back_to_previous(struct wmOperatorType *ot)
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;
@@ -4163,8 +4229,8 @@ static void SCREEN_OT_back_to_previous(struct wmOperatorType *ot)
static int userpref_show_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
int sizex = 800 * UI_DPI_FAC;
- int sizey = 480 * UI_DPI_FAC;
-
+ int sizey = 500 * UI_DPI_FAC;
+
/* changes context! */
if (WM_window_open_temp(C, event->x, event->y, sizex, sizey, WM_WINDOW_USERPREFS) != NULL) {
return OPERATOR_FINISHED;
@@ -4182,7 +4248,7 @@ static void SCREEN_OT_userpref_show(struct wmOperatorType *ot)
ot->name = "Show User Preferences";
ot->description = "Show user preferences";
ot->idname = "SCREEN_OT_userpref_show";
-
+
/* api callbacks */
ot->invoke = userpref_show_invoke;
ot->poll = ED_operator_screenactive;
@@ -4191,17 +4257,86 @@ static void SCREEN_OT_userpref_show(struct wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Show Drivers Editor Operator
+ * \{ */
+
+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;
+ }
+}
+
+
+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";
+
+ /* api callbacks */
+ ot->invoke = drivers_editor_show_invoke;
+ ot->poll = ED_operator_screenactive;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name New Screen Operator
* \{ */
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;
- layout_new = ED_workspace_layout_duplicate(workspace, layout_old, win);
+ 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;
@@ -4213,7 +4348,7 @@ static void SCREEN_OT_new(wmOperatorType *ot)
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;
@@ -4242,7 +4377,7 @@ static void SCREEN_OT_delete(wmOperatorType *ot)
ot->name = "Delete Screen";
ot->description = "Delete active screen";
ot->idname = "SCREEN_OT_delete";
-
+
/* api callbacks */
ot->exec = screen_delete_exec;
}
@@ -4280,7 +4415,7 @@ float ED_region_blend_alpha(ARegion *ar)
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;
}
@@ -4291,12 +4426,12 @@ float ED_region_blend_alpha(ARegion *ar)
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)
@@ -4320,14 +4455,14 @@ 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) {
region_blend_end(C, ar, true);
}
rgi = MEM_callocN(sizeof(RegionAlphaInfo), "RegionAlphaInfo");
-
+
rgi->hidden = ar->flag & RGN_FLAG_HIDDEN;
rgi->sa = sa;
rgi->ar = ar;
@@ -4356,18 +4491,18 @@ static int region_blend_invoke(bContext *C, wmOperator *UNUSED(op), const wmEven
{
RegionAlphaInfo *rgi;
wmTimer *timer = event->customdata;
-
+
/* event type is TIMERREGION, but we better check */
if (event->type != TIMERREGION || timer == NULL)
return OPERATOR_PASS_THROUGH;
-
+
rgi = timer->customdata;
-
+
/* 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);
@@ -4383,13 +4518,13 @@ static void SCREEN_OT_region_blend(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_INTERNAL;
-
+
/* properties */
}
@@ -4452,11 +4587,10 @@ static int space_context_cycle_invoke(bContext *C, wmOperator *op, const wmEvent
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);
+ 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);
@@ -4483,6 +4617,51 @@ static void SCREEN_OT_space_context_cycle(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Workspace Cycle Operator
+ * \{ */
+
+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;
+ }
+
+ 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 = (direction == SPACE_CONTEXT_CYCLE_PREV) ? workspace_src->id.prev : workspace_src->id.next;
+ if (workspace_dst == NULL) {
+ workspace_dst = (direction == SPACE_CONTEXT_CYCLE_PREV) ? bmain->workspaces.last : bmain->workspaces.first;
+ }
+ if (workspace_src != workspace_dst) {
+ 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;
+}
+
+static void SCREEN_OT_workspace_cycle(wmOperatorType *ot)
+{
+ /* 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;;
+
+ ot->flag = 0;
+
+ RNA_def_enum(ot->srna, "direction", space_context_cycle_direction, SPACE_CONTEXT_CYCLE_NEXT, "Direction",
+ "Direction to cycle through");
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Assigning Operator Types
* \{ */
@@ -4494,7 +4673,7 @@ void ED_operatortypes_screen(void)
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);
@@ -4507,23 +4686,24 @@ void ED_operatortypes_screen(void)
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_toolbox);
+ WM_operatortype_append(SCREEN_OT_header_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_screencast);
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_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);
@@ -4540,7 +4720,7 @@ void ED_operatortypes_screen(void)
WM_operatortype_append(ED_OT_undo_history);
WM_operatortype_append(ED_OT_flush_edits);
-
+
}
/** \} */
@@ -4558,20 +4738,20 @@ static void keymap_modal_set(wmKeyConfig *keyconf)
{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_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, KM_MODAL_CANCEL);
WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_ANY, KM_ANY, 0, KM_MODAL_APPLY);
WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, KM_MODAL_APPLY);
WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, KM_MODAL_APPLY);
-
+
WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, KM_MODAL_SNAP_ON);
WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, KM_MODAL_SNAP_OFF);
-
+
WM_modalkeymap_assign(keymap, "SCREEN_OT_area_move");
-
+
}
static int open_file_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
@@ -4597,14 +4777,14 @@ void ED_keymap_screen(wmKeyConfig *keyconf)
ListBase *lb;
wmKeyMap *keymap;
wmKeyMapItem *kmi;
-
+
/* Screen Editing ------------------------------------------------ */
keymap = WM_keymap_find(keyconf, "Screen Editing", 0, 0);
-
+
RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, 0, 0)->ptr, "modifier", 0);
RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "modifier", 1);
RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "modifier", 2);
-
+
/* screen tools */
WM_keymap_verify_item(keymap, "SCREEN_OT_area_split", EVT_ACTIONZONE_AREA, 0, 0, 0);
WM_keymap_verify_item(keymap, "SCREEN_OT_area_join", EVT_ACTIONZONE_AREA, 0, 0, 0);
@@ -4615,65 +4795,77 @@ void ED_keymap_screen(wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "use_hide_panels", true);
/* area move after action zones */
WM_keymap_verify_item(keymap, "SCREEN_OT_area_move", LEFTMOUSE, KM_PRESS, 0, 0);
-
+
WM_keymap_verify_item(keymap, "SCREEN_OT_area_options", RIGHTMOUSE, KM_PRESS, 0, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "SCREEN_OT_header", F9KEY, KM_PRESS, KM_ALT, 0);
+#endif
/* Header Editing ------------------------------------------------ */
/* note: this is only used when the cursor is inside the header */
keymap = WM_keymap_find(keyconf, "Header", 0, 0);
- WM_keymap_add_item(keymap, "SCREEN_OT_header_toolbox", RIGHTMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "SCREEN_OT_header_context_menu", RIGHTMOUSE, KM_PRESS, 0, 0);
/* Screen General ------------------------------------------------ */
keymap = WM_keymap_find(keyconf, "Screen", 0, 0);
-
+
/* standard timers */
WM_keymap_add_item(keymap, "SCREEN_OT_animation_step", TIMER0, KM_ANY, KM_ANY, 0);
WM_keymap_add_item(keymap, "SCREEN_OT_region_blend", TIMERREGION, KM_ANY, KM_ANY, 0);
-
-
+
+#ifdef USE_WM_KEYMAP_27X
RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_screen_set", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", 1);
RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_screen_set", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", -1);
- WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", UPARROWKEY, KM_PRESS, KM_CTRL, 0);
- WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", DOWNARROWKEY, KM_PRESS, KM_CTRL, 0);
+#endif
WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", SPACEKEY, KM_PRESS, KM_SHIFT, 0);
- kmi = WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", F10KEY, KM_PRESS, KM_ALT, 0);
+ kmi = WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", SPACEKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "use_hide_panels", true);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "SCREEN_OT_screenshot", F3KEY, KM_PRESS, KM_CTRL, 0);
- WM_keymap_add_item(keymap, "SCREEN_OT_screencast", F3KEY, KM_PRESS, KM_ALT, 0);
+#endif
kmi = WM_keymap_add_item(keymap, "SCREEN_OT_space_context_cycle", TABKEY, KM_PRESS, KM_CTRL, 0);
RNA_enum_set(kmi->ptr, "direction", SPACE_CONTEXT_CYCLE_NEXT);
kmi = WM_keymap_add_item(keymap, "SCREEN_OT_space_context_cycle", TABKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
RNA_enum_set(kmi->ptr, "direction", SPACE_CONTEXT_CYCLE_PREV);
+ kmi = WM_keymap_add_item(keymap, "SCREEN_OT_workspace_cycle", TABKEY, KM_PRESS, KM_CTRL, 0);
+ RNA_enum_set(kmi->ptr, "direction", SPACE_CONTEXT_CYCLE_NEXT);
+ kmi = WM_keymap_add_item(keymap, "SCREEN_OT_workspace_cycle", TABKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
+ RNA_enum_set(kmi->ptr, "direction", SPACE_CONTEXT_CYCLE_PREV);
+
/* tests */
WM_keymap_add_item(keymap, "SCREEN_OT_region_quadview", QKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
- WM_keymap_verify_item(keymap, "SCREEN_OT_repeat_history", F3KEY, KM_PRESS, 0, 0);
+#ifdef USE_WM_KEYMAP_27X
+ WM_keymap_verify_item(keymap, "SCREEN_OT_repeat_history", RKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
WM_keymap_add_item(keymap, "SCREEN_OT_repeat_last", RKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_verify_item(keymap, "SCREEN_OT_region_flip", F5KEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "SCREEN_OT_redo_last", F6KEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "SCRIPT_OT_reload", F8KEY, KM_PRESS, 0, 0);
-
+#endif
+
/* files */
WM_keymap_add_item(keymap, "FILE_OT_execute", RETKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "FILE_OT_execute", PADENTER, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "FILE_OT_cancel", ESCKEY, KM_PRESS, 0, 0);
-
+
/* undo */
#ifdef __APPLE__
WM_keymap_add_item(keymap, "ED_OT_undo", ZKEY, KM_PRESS, KM_OSKEY, 0);
WM_keymap_add_item(keymap, "ED_OT_redo", ZKEY, KM_PRESS, KM_SHIFT | KM_OSKEY, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "ED_OT_undo_history", ZKEY, KM_PRESS, KM_ALT | KM_OSKEY, 0);
#endif
+#endif
WM_keymap_add_item(keymap, "ED_OT_undo", ZKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "ED_OT_redo", ZKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "ED_OT_undo_history", ZKEY, KM_PRESS, KM_ALT | KM_CTRL, 0);
-
-
+#endif
+
/* render */
kmi = WM_keymap_add_item(keymap, "RENDER_OT_render", F12KEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "use_viewport", true);
@@ -4683,62 +4875,68 @@ void ED_keymap_screen(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "RENDER_OT_view_cancel", ESCKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "RENDER_OT_view_show", F11KEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "RENDER_OT_play_rendered_anim", F11KEY, KM_PRESS, KM_CTRL, 0);
-
+
+#ifdef USE_WM_KEYMAP_27X
/* user prefs */
#ifdef __APPLE__
WM_keymap_add_item(keymap, "SCREEN_OT_userpref_show", COMMAKEY, KM_PRESS, KM_OSKEY, 0);
#endif
WM_keymap_add_item(keymap, "SCREEN_OT_userpref_show", UKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
-
-
+#endif
+
+
/* Anim Playback ------------------------------------------------ */
keymap = WM_keymap_find(keyconf, "Frames", 0, 0);
-
+
/* frame offsets */
+#ifdef USE_WM_KEYMAP_27X
RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", UPARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "delta", 10);
RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", DOWNARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "delta", -10);
+#endif
RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", LEFTARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", -1);
RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", RIGHTARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", 1);
-
+
+#ifdef USE_WM_KEYMAP_27X
RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", WHEELDOWNMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "delta", 1);
RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", WHEELUPMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "delta", -1);
-
+
RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", UPARROWKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0)->ptr, "end", true);
RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", DOWNARROWKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0)->ptr, "end", false);
+#endif
RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", RIGHTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "end", true);
RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", LEFTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "end", false);
-
+
kmi = WM_keymap_add_item(keymap, "SCREEN_OT_keyframe_jump", UPARROWKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "next", true);
kmi = WM_keymap_add_item(keymap, "SCREEN_OT_keyframe_jump", DOWNARROWKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "next", false);
-
+
kmi = WM_keymap_add_item(keymap, "SCREEN_OT_keyframe_jump", MEDIALAST, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "next", true);
kmi = WM_keymap_add_item(keymap, "SCREEN_OT_keyframe_jump", MEDIAFIRST, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "next", false);
-
+
/* play (forward and backwards) */
WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", AKEY, KM_PRESS, KM_ALT, 0);
RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", AKEY, KM_PRESS, KM_ALT | KM_SHIFT, 0)->ptr, "reverse", true);
WM_keymap_add_item(keymap, "SCREEN_OT_animation_cancel", ESCKEY, KM_PRESS, 0, 0);
-
+
WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", MEDIAPLAY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "SCREEN_OT_animation_cancel", MEDIASTOP, KM_PRESS, 0, 0);
-
+
/* Alternative keys for animation and sequencer playing */
#if 0 /* XXX: disabled for restoring later... bad implementation */
keymap = WM_keymap_find(keyconf, "Frames", 0, 0);
kmi = WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", RIGHTARROWKEY, KM_PRESS, KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "cycle_speed", true);
-
+
kmi = WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", LEFTARROWKEY, KM_PRESS, KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "reverse", true);
RNA_boolean_set(kmi->ptr, "cycle_speed", true);
-
+
WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", DOWNARROWKEY, KM_PRESS, KM_ALT, 0);
#endif
diff --git a/source/blender/editors/screen/screen_user_menu.c b/source/blender/editors/screen/screen_user_menu.c
new file mode 100644
index 00000000000..c51227d7107
--- /dev/null
+++ b/source/blender/editors/screen/screen_user_menu.c
@@ -0,0 +1,196 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/screen/screen_user_menu.c
+ * \ingroup spview3d
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <float.h>
+
+#include "DNA_scene_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+#include "BLT_translation.h"
+
+#include "BKE_blender_user_menu.h"
+#include "BKE_context.h"
+#include "BKE_screen.h"
+#include "BKE_idprop.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Menu Type
+ * \{ */
+
+bUserMenu *ED_screen_user_menu_find(bContext *C)
+{
+ SpaceLink *sl = CTX_wm_space_data(C);
+ const char *context = CTX_data_mode_string(C);
+ return BKE_blender_user_menu_find(&U.user_menus, sl->spacetype, context);
+}
+
+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);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Menu Item
+ * \{ */
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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);
+}
+
+void ED_screen_user_menu_item_remove(ListBase *lb, bUserMenuItem *umi)
+{
+ BLI_remlink(lb, umi);
+ BKE_blender_user_menu_item_free(umi);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Menu Definition
+ * \{ */
+
+static void screen_user_menu_draw(const bContext *C, Menu *menu)
+{
+ SpaceLink *sl = CTX_wm_space_data(C);
+ const char *context = CTX_data_mode_string(C);
+ bUserMenu *um_array[] = {
+ BKE_blender_user_menu_find(&U.user_menus, sl->spacetype, context),
+ (sl->spacetype != SPACE_TOPBAR) ? BKE_blender_user_menu_find(&U.user_menus, SPACE_TOPBAR, context) : NULL,
+ };
+ for (int um_index = 0; um_index < ARRAY_SIZE(um_array); 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);
+ }
+ 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);
+ }
+ else if (umi->type == USER_MENU_TYPE_SEP) {
+ uiItemS(menu->layout);
+ }
+ }
+ }
+}
+
+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);
+}
+
+/** \} */
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c
index 2c1cbc3d21d..387cd7df998 100644
--- a/source/blender/editors/screen/screendump.c
+++ b/source/blender/editors/screen/screendump.c
@@ -36,7 +36,6 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "BLI_math.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -44,20 +43,15 @@
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
-#include "DNA_userdef_types.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_image.h"
#include "BKE_report.h"
-#include "BKE_writeavi.h"
#include "BIF_gl.h"
-#include "GPU_immediate.h"
-#include "GPU_immediate_util.h"
-
#include "RNA_access.h"
#include "RNA_define.h"
@@ -66,9 +60,6 @@
#include "WM_types.h"
#include "WM_api.h"
-#include "PIL_time.h"
-
-
#include "screen_intern.h"
typedef struct ScreenshotData {
@@ -104,7 +95,7 @@ static unsigned int *screenshot(bContext *C, int *dumpsx, int *dumpsy)
*dumpsy = WM_window_pixels_y(win);
if (*dumpsx && *dumpsy) {
-
+
dumprect = MEM_mallocN(sizeof(int) * (*dumpsx) * (*dumpsy), "dumprect");
glReadBuffer(GL_FRONT);
screenshot_read_pixels(x, y, *dumpsx, *dumpsy, (unsigned char *)dumprect);
@@ -122,13 +113,13 @@ static int screenshot_data_create(bContext *C, wmOperator *op)
/* do redraw so we don't show popups/menus */
WM_redraw_windows(C);
-
+
dumprect = screenshot(C, &dumpsx, &dumpsy);
if (dumprect) {
ScreenshotData *scd = MEM_callocN(sizeof(ScreenshotData), "screenshot");
ScrArea *sa = CTX_wm_area(C);
-
+
scd->dumpsx = dumpsx;
scd->dumpsy = dumpsy;
scd->dumprect = dumprect;
@@ -194,7 +185,7 @@ static int screenshot_exec(bContext *C, wmOperator *op)
char path[FILE_MAX];
RNA_string_get(op->ptr, "filepath", path);
- BLI_path_abs(path, G.main->name);
+ BLI_path_abs(path, BKE_main_blendfile_path_from_global());
/* operator ensures the extension */
ibuf = IMB_allocImBuf(scd->dumpsx, scd->dumpsy, 24, 0);
@@ -233,13 +224,13 @@ static int screenshot_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
/* extension is added by 'screenshot_check' after */
char filepath[FILE_MAX] = "//screen";
if (G.relbase_valid) {
- BLI_strncpy(filepath, G.main->name, sizeof(filepath));
- BLI_replace_extension(filepath, sizeof(filepath), ""); /* strip '.blend' */
+ 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;
@@ -291,274 +282,19 @@ void SCREEN_OT_screenshot(wmOperatorType *ot)
ot->name = "Save Screenshot"; /* weak: opname starting with 'save' makes filewindow give save-over */
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)");
}
-
-/* *************** screenshot movie job ************************* */
-
-typedef struct ScreenshotJob {
- Main *bmain;
- Scene *scene;
- wmWindowManager *wm;
- unsigned int *dumprect;
- int x, y, dumpsx, dumpsy;
- const short *stop;
- const short *do_update;
- ReportList reports;
-
- bMovieHandle *movie_handle;
- void *movie_ctx;
-} ScreenshotJob;
-
-
-static void screenshot_freejob(void *sjv)
-{
- ScreenshotJob *sj = sjv;
-
- if (sj->dumprect)
- MEM_freeN(sj->dumprect);
-
- if (sj->movie_handle) {
- bMovieHandle *mh = sj->movie_handle;
- mh->end_movie(sj->movie_ctx);
- mh->context_free(sj->movie_ctx);
- }
-
- MEM_freeN(sj);
-}
-
-
-/* called before redraw notifiers, copies a new dumprect */
-static void screenshot_updatejob(void *sjv)
-{
- ScreenshotJob *sj = sjv;
- unsigned int *dumprect;
-
- if (sj->dumprect == NULL) {
- dumprect = MEM_mallocN(sizeof(int) * sj->dumpsx * sj->dumpsy, "dumprect");
- screenshot_read_pixels(sj->x, sj->y, sj->dumpsx, sj->dumpsy, (unsigned char *)dumprect);
-
- sj->dumprect = dumprect;
- }
-}
-
-
-/* only this runs inside thread */
-static void screenshot_startjob(void *sjv, short *stop, short *do_update, float *UNUSED(progress))
-{
- ScreenshotJob *sj = sjv;
- RenderData rd = sj->scene->r;
- bMovieHandle *mh = NULL;
-
- /* we need this as local variables for renderdata */
- rd.frs_sec = U.scrcastfps;
- rd.frs_sec_base = 1.0f;
-
- if (BKE_imtype_is_movie(rd.im_format.imtype)) {
- mh = BKE_movie_handle_get(sj->scene->r.im_format.imtype);
- if (mh == NULL) {
- printf("Movie format unsupported\n");
- return;
- }
- sj->movie_ctx = mh->context_create();
- sj->movie_handle = mh;
-
- if (!mh->start_movie(sj->movie_ctx, sj->scene, &rd, sj->dumpsx, sj->dumpsy, &sj->reports, false, "")) {
- printf("screencast job stopped\n");
- return;
- }
- }
-
- sj->stop = stop;
- sj->do_update = do_update;
-
- *do_update = true; /* wait for opengl rect */
-
- while (*stop == 0) {
-
- if (sj->dumprect) {
-
- if (mh) {
- if (mh->append_movie(sj->movie_ctx, &rd, rd.sfra, rd.cfra, (int *)sj->dumprect,
- sj->dumpsx, sj->dumpsy, "", &sj->reports))
- {
- BKE_reportf(&sj->reports, RPT_INFO, "Appended frame: %d", rd.cfra);
- printf("Appended frame %d\n", rd.cfra);
- }
- else {
- break;
- }
- }
- else {
- ImBuf *ibuf = IMB_allocImBuf(sj->dumpsx, sj->dumpsy, rd.im_format.planes, 0);
- char name[FILE_MAX];
- int ok;
-
- BKE_image_path_from_imformat(
- name, rd.pic, sj->bmain->name, rd.cfra,
- &rd.im_format, (rd.scemode & R_EXTENSION) != 0, true, NULL);
-
- ibuf->rect = sj->dumprect;
- ok = BKE_imbuf_write(ibuf, name, &rd.im_format);
-
- if (ok == 0) {
- printf("Write error: cannot save %s\n", name);
- BKE_reportf(&sj->reports, RPT_INFO, "Write error: cannot save %s", name);
- break;
- }
- else {
- printf("Saved file: %s\n", name);
- BKE_reportf(&sj->reports, RPT_INFO, "Saved file: %s", name);
- }
-
- /* imbuf knows which rects are not part of ibuf */
- IMB_freeImBuf(ibuf);
- }
-
- MEM_freeN(sj->dumprect);
- sj->dumprect = NULL;
-
- *do_update = true;
-
- rd.cfra++;
-
- }
- else
- PIL_sleep_ms(U.scrcastwait);
- }
-
- if (mh) {
- mh->end_movie(sj->movie_ctx);
- mh->context_free(sj->movie_ctx);
- sj->movie_handle = NULL;
- }
-
- BKE_report(&sj->reports, RPT_INFO, "Screencast job stopped");
-}
-
-/* Helper callback for drawing the cursor itself */
-static void screencast_draw_cursor(bContext *UNUSED(C), int x, int y, void *UNUSED(p_ptr))
-{
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
-
- Gwn_VertFormat *format = immVertexFormat();
- unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- immUniformColor4ub(0, 0, 0, 32);
- imm_draw_circle_fill_2d(pos, (float)x, (float)y, 20, 40);
-
- immUniformColor4ub(255, 255, 255, 128);
- imm_draw_circle_wire_2d(pos, (float)x, (float)y, 20, 40);
-
- immUnbindProgram();
-
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
-}
-
-/* Turn brush cursor in 3D view on/off */
-static void screencast_cursor_toggle(wmWindowManager *wm, short enable)
-{
- static void *cursor = NULL;
-
- if (cursor && !enable) {
- /* clear cursor */
- WM_paint_cursor_end(wm, cursor);
- cursor = NULL;
- }
- else if (enable) {
- /* enable cursor */
- cursor = WM_paint_cursor_activate(wm, NULL, screencast_draw_cursor, NULL);
- }
-}
-
-static void screenshot_endjob(void *sjv)
-{
- ScreenshotJob *sj = sjv;
-
- screencast_cursor_toggle(sj->wm, 0);
-}
-
-
-static int screencast_exec(bContext *C, wmOperator *op)
-{
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *win = CTX_wm_window(C);
- bScreen *screen = CTX_wm_screen(C);
- wmJob *wm_job;
- ScreenshotJob *sj;
-
- /* if called again, stop the running job */
- if (WM_jobs_test(wm, screen, WM_JOB_TYPE_SCREENCAST))
- WM_jobs_stop(wm, screen, screenshot_startjob);
-
- wm_job = WM_jobs_get(wm, win, screen, "Screencast", 0, WM_JOB_TYPE_SCREENCAST);
- sj = MEM_callocN(sizeof(ScreenshotJob), "screenshot job");
-
- /* setup sj */
- if (RNA_boolean_get(op->ptr, "full")) {
- sj->x = 0;
- sj->y = 0;
- sj->dumpsx = WM_window_pixels_x(win);
- sj->dumpsy = WM_window_pixels_y(win);
- }
- else {
- ScrArea *curarea = CTX_wm_area(C);
- sj->x = curarea->totrct.xmin;
- sj->y = curarea->totrct.ymin;
- sj->dumpsx = curarea->totrct.xmax - sj->x;
- sj->dumpsy = curarea->totrct.ymax - sj->y;
- }
- sj->bmain = CTX_data_main(C);
- sj->scene = CTX_data_scene(C);
- sj->wm = wm;
-
- BKE_reports_init(&sj->reports, RPT_PRINT);
-
- /* setup job */
- WM_jobs_customdata_set(wm_job, sj, screenshot_freejob);
- WM_jobs_timer(wm_job, 0.1, 0, NC_SCREEN | ND_SCREENCAST);
- WM_jobs_callbacks(wm_job, screenshot_startjob, NULL, screenshot_updatejob, screenshot_endjob);
-
- WM_jobs_start(sj->wm, wm_job);
-
- screencast_cursor_toggle(sj->wm, 1);
-
- WM_event_add_notifier(C, NC_SCREEN | ND_SCREENCAST, screen);
-
- return OPERATOR_FINISHED;
-}
-
-void SCREEN_OT_screencast(wmOperatorType *ot)
-{
- ot->name = "Make Screencast";
- ot->idname = "SCREEN_OT_screencast";
- ot->description = "Capture a video of the active area or whole Blender window";
-
- ot->invoke = WM_operator_confirm;
- ot->exec = screencast_exec;
- ot->poll = screenshot_poll; /* shared poll */
-
- ot->flag = 0;
-
- RNA_def_property(ot->srna, "filepath", PROP_STRING, PROP_FILEPATH);
- 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 21dc4e0f923..800b1fbe51d 100644
--- a/source/blender/editors/screen/workspace_edit.c
+++ b/source/blender/editors/screen/workspace_edit.c
@@ -65,6 +65,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_toolsystem.h"
#include "screen_intern.h"
@@ -109,7 +110,7 @@ static void workspace_change_update_view_layer(
WorkSpace *workspace_new, const WorkSpace *workspace_old,
Scene *scene)
{
- if (!BKE_workspace_view_layer_get(workspace_new, scene)) {
+ if (!BKE_workspace_view_layer_exists(workspace_new, scene)) {
BKE_workspace_view_layer_set(workspace_new, BKE_workspace_view_layer_get(workspace_old, scene), scene);
}
}
@@ -130,7 +131,7 @@ static bool workspace_change_find_new_layout_cb(const WorkSpaceLayout *layout, v
}
static WorkSpaceLayout *workspace_change_get_new_layout(
- WorkSpace *workspace_new, wmWindow *win)
+ Main *bmain, WorkSpace *workspace_new, wmWindow *win)
{
/* ED_workspace_duplicate may have stored a layout to activate once the workspace gets activated. */
WorkSpaceLayout *layout_new;
@@ -154,7 +155,7 @@ static WorkSpaceLayout *workspace_change_get_new_layout(
NULL, false);
if (!layout_temp) {
/* fallback solution: duplicate layout */
- layout_temp = ED_workspace_layout_duplicate(workspace_new, layout_new, win);
+ layout_temp = ED_workspace_layout_duplicate(bmain, workspace_new, layout_new, win);
}
layout_new = layout_temp;
}
@@ -176,7 +177,7 @@ bool ED_workspace_change(
{
Main *bmain = CTX_data_main(C);
WorkSpace *workspace_old = WM_window_get_active_workspace(win);
- WorkSpaceLayout *layout_new = workspace_change_get_new_layout(workspace_new, 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);
@@ -198,11 +199,11 @@ bool ED_workspace_change(
screen_change_update(C, win, screen_new);
workspace_change_update(workspace_new, workspace_old, C, wm);
- BLI_assert(BKE_workspace_view_layer_get(workspace_new, CTX_data_scene(C)) != NULL);
+ BLI_assert(BKE_workspace_view_layer_exists(workspace_new, CTX_data_scene(C)) != NULL);
BLI_assert(CTX_wm_workspace(C) == workspace_new);
- WM_toolsystem_unlink(C, workspace_old);
- WM_toolsystem_link(C, workspace_new);
+ WM_toolsystem_unlink_all(C, workspace_old);
+ WM_toolsystem_reinit_all(C, win);
return true;
}
@@ -224,10 +225,10 @@ WorkSpace *ED_workspace_duplicate(
bmain, workspace_old->id.name + 2, scene,
BKE_workspace_view_layer_get(workspace_old, scene));
- workspace_new->tool = workspace_old->tool;
+ /* TODO(campbell): tools */
for (WorkSpaceLayout *layout_old = layouts_old->first; layout_old; layout_old = layout_old->next) {
- WorkSpaceLayout *layout_new = ED_workspace_layout_duplicate(workspace_new, layout_old, win);
+ 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;
@@ -331,6 +332,12 @@ static void WORKSPACE_OT_workspace_delete(wmOperatorType *ot)
ot->exec = workspace_delete_exec;
}
+static int workspace_append_activate_poll(bContext *C)
+{
+ wmOperatorType *ot = WM_operatortype_find("WM_OT_append", false);
+ return WM_operator_poll(C, ot);
+}
+
static int workspace_append(bContext *C, const char *directory, const char *idname)
{
wmOperatorType *ot = WM_operatortype_find("WM_OT_append", false);
@@ -385,6 +392,7 @@ static void WORKSPACE_OT_append_activate(wmOperatorType *ot)
/* api callbacks */
ot->exec = workspace_append_activate_exec;
+ ot->poll = workspace_append_activate_poll;
RNA_def_string(ot->srna, "idname", NULL, MAX_ID_NAME - 2, "Identifier",
"Name of the workspace to append and activate");
diff --git a/source/blender/editors/screen/workspace_layout_edit.c b/source/blender/editors/screen/workspace_layout_edit.c
index a6f991d4bbe..6d504c05dd1 100644
--- a/source/blender/editors/screen/workspace_layout_edit.c
+++ b/source/blender/editors/screen/workspace_layout_edit.c
@@ -46,20 +46,22 @@
* 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)
{
- const int screen_size_x = WM_window_screen_pixels_x(win);
- const int screen_size_y = WM_window_screen_pixels_y(win);
+ bScreen *screen;
+ rcti screen_rect;
- bScreen *screen = screen_add(name, screen_size_x, screen_size_y);
- WorkSpaceLayout *layout = BKE_workspace_layout_add(workspace, screen, name);
+ WM_window_screen_rect_calc(win, &screen_rect);
+ screen = screen_add(bmain, name, &screen_rect);
- return layout;
+ return BKE_workspace_layout_add(bmain, workspace, screen, name);
}
WorkSpaceLayout *ED_workspace_layout_duplicate(
+ Main *bmain,
WorkSpace *workspace, const WorkSpaceLayout *layout_old,
wmWindow *win)
{
@@ -72,7 +74,7 @@ WorkSpaceLayout *ED_workspace_layout_duplicate(
return NULL; /* XXX handle this case! */
}
- layout_new = ED_workspace_layout_add(workspace, win, name);
+ layout_new = ED_workspace_layout_add(bmain, workspace, win, name);
screen_new = BKE_workspace_layout_screen_get(layout_new);
screen_data_copy(screen_new, screen_old);
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 8d941078c5f..50d178bc757 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -62,6 +62,7 @@
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "UI_resources.h"
@@ -262,7 +263,7 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima
target = (primary) ? &primary_snap : &secondary_snap;
- refresh =
+ refresh =
!target->overlay_texture ||
(invalid != 0) ||
!same_tex_snap(target, mtex, vc, col, zoom);
@@ -607,7 +608,7 @@ static void paint_draw_tex_overlay(UnifiedPaintSettings *ups, Brush *brush,
}
if (load_tex(brush, vc, zoom, col, primary)) {
- glEnable(GL_BLEND);
+ GPU_blend(true);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_FALSE);
@@ -726,7 +727,7 @@ static void paint_draw_cursor_overlay(UnifiedPaintSettings *ups, Brush *brush,
if (load_tex_cursor(brush, vc, zoom)) {
bool do_pop = false;
float center[2];
- glEnable(GL_BLEND);
+ GPU_blend(true);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_FALSE);
@@ -829,7 +830,7 @@ BLI_INLINE void draw_tri_point(
{
immUniformColor4fv(selected ? sel_col : pivot_col);
- glLineWidth(3.0f);
+ GPU_line_width(3.0f);
float w = width / 2.0f;
float tri[3][2] = {
@@ -845,7 +846,7 @@ BLI_INLINE void draw_tri_point(
immEnd();
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
immBegin(GWN_PRIM_LINE_LOOP, 3);
immVertex2fv(pos, tri[0]);
@@ -860,7 +861,7 @@ BLI_INLINE void draw_rect_point(
{
immUniformColor4fv(selected ? sel_col : handle_col);
- glLineWidth(3.0f);
+ GPU_line_width(3.0f);
float w = width / 2.0f;
float minx = co[0] - w;
@@ -871,7 +872,7 @@ BLI_INLINE void draw_rect_point(
imm_draw_box_wire_2d(pos, minx, miny, maxx, maxy);
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
imm_draw_box_wire_2d(pos, minx, miny, maxx, maxy);
}
@@ -880,7 +881,7 @@ BLI_INLINE void draw_rect_point(
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);
- glLineWidth(3.0f);
+ GPU_line_width(3.0f);
immBegin(GWN_PRIM_LINE_STRIP, 3);
immVertex2fv(pos, bez->vec[0]);
@@ -888,7 +889,7 @@ BLI_INLINE void draw_bezier_handle_lines(unsigned int pos, float sel_col[4], Bez
immVertex2fv(pos, bez->vec[2]);
immEnd();
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
if (bez->f1 || bez->f2) {
immUniformColor4fv(sel_col);
@@ -920,8 +921,8 @@ static void paint_draw_curve_cursor(Brush *brush)
PaintCurve *pc = brush->paint_curve;
PaintCurvePoint *cp = pc->points;
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
+ GPU_line_smooth(true);
+ GPU_blend(true);
/* draw the bezier handles and the curve segment between the current and next point */
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -954,7 +955,7 @@ static void paint_draw_curve_cursor(Brush *brush)
float (*v)[2] = (float(*)[2])data;
immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
- glLineWidth(3.0f);
+ GPU_line_width(3.0f);
immBegin(GWN_PRIM_LINE_STRIP, PAINT_CURVE_NUM_SEGMENTS + 1);
for (j = 0; j <= PAINT_CURVE_NUM_SEGMENTS; j++) {
immVertex2fv(pos, v[j]);
@@ -962,7 +963,7 @@ static void paint_draw_curve_cursor(Brush *brush)
immEnd();
immUniformColor4f(0.9f, 0.9f, 1.0f, 0.5f);
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
immBegin(GWN_PRIM_LINE_STRIP, PAINT_CURVE_NUM_SEGMENTS + 1);
for (j = 0; j <= PAINT_CURVE_NUM_SEGMENTS; j++) {
immVertex2fv(pos, v[j]);
@@ -976,8 +977,8 @@ static void paint_draw_curve_cursor(Brush *brush)
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);
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
+ GPU_blend(false);
+ GPU_line_smooth(false);
immUnbindProgram();
}
@@ -1001,7 +1002,7 @@ static void paint_cursor_on_hit(UnifiedPaintSettings *ups, Brush *brush, ViewCon
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);
@@ -1107,9 +1108,9 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
}
/* make lines pretty */
- glLineWidth(1.0f);
- glEnable(GL_BLEND); /* TODO: also set blend mode? */
- glEnable(GL_LINE_SMOOTH);
+ GPU_line_width(1.0f);
+ GPU_blend(true); /* TODO: also set blend mode? */
+ GPU_line_smooth(true);
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -1129,8 +1130,8 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
immUnbindProgram();
/* restore GL state */
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
+ GPU_blend(false);
+ GPU_line_smooth(false);
}
/* Public API */
diff --git a/source/blender/editors/sculpt_paint/paint_curve.c b/source/blender/editors/sculpt_paint/paint_curve.c
index 049d8ff8c0b..e2100ceb066 100644
--- a/source/blender/editors/sculpt_paint/paint_curve.c
+++ b/source/blender/editors/sculpt_paint/paint_curve.c
@@ -697,27 +697,27 @@ void PAINTCURVE_OT_draw(wmOperatorType *ot)
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 ePaintTexture2D:
{
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);
+ ED_view3d_cursor3d_update(C, event->mval, true, V3D_CURSOR_ORIENT_VIEW);
break;
}
-
+
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c
index 4dd770d79b9..4deec54a5b3 100644
--- a/source/blender/editors/sculpt_paint/paint_hide.c
+++ b/source/blender/editors/sculpt_paint/paint_hide.c
@@ -46,8 +46,8 @@
#include "BKE_pbvh.h"
#include "BKE_ccg.h"
#include "BKE_context.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
#include "BKE_multires.h"
#include "BKE_paint.h"
#include "BKE_subsurf.h"
@@ -101,7 +101,7 @@ static void partialvis_update_mesh(Object *ob,
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);
@@ -153,7 +153,7 @@ static void partialvis_update_grids(Object *ob,
&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++) {
@@ -323,7 +323,7 @@ static void clip_planes_from_rect(bContext *C,
{
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);
@@ -354,7 +354,7 @@ static void get_pbvh_nodes(PBVH *pbvh,
case PARTIALVIS_MASKED:
break;
}
-
+
BKE_pbvh_search_gather(pbvh, cb, clip_planes, nodes, totnode);
}
@@ -368,7 +368,6 @@ static int hide_show_exec(bContext *C, wmOperator *op)
PartialVisArea area;
PBVH *pbvh;
PBVHNode **nodes;
- DerivedMesh *dm;
PBVHType pbvh_type;
float clip_planes[4][4];
rcti rect;
@@ -381,9 +380,9 @@ static int hide_show_exec(bContext *C, wmOperator *op)
clip_planes_from_rect(C, clip_planes, &rect);
- dm = mesh_get_derived_final(depsgraph, CTX_data_scene(C), ob, CD_MASK_BAREMESH);
- pbvh = dm->getPBVH(ob, dm);
- ob->sculpt->pbvh = pbvh;
+ Mesh *me_eval_deform = mesh_get_eval_deform(depsgraph, CTX_data_scene(C), ob, CD_MASK_BAREMESH);
+ pbvh = BKE_sculpt_object_pbvh_ensure(ob, me_eval_deform);
+ BLI_assert(ob->sculpt->pbvh == pbvh);
get_pbvh_nodes(pbvh, &nodes, &totnode, clip_planes, area);
pbvh_type = BKE_pbvh_type(pbvh);
@@ -414,7 +413,7 @@ static int hide_show_exec(bContext *C, wmOperator *op)
if (nodes)
MEM_freeN(nodes);
-
+
/* end undo */
sculpt_undo_push_end();
@@ -425,7 +424,7 @@ static int hide_show_exec(bContext *C, wmOperator *op)
}
ED_region_tag_redraw(ar);
-
+
return OPERATOR_FINISHED;
}
@@ -454,7 +453,7 @@ void PAINT_OT_hide_show(struct wmOperatorType *ot)
{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";
@@ -474,6 +473,6 @@ void PAINT_OT_hide_show(struct wmOperatorType *ot)
"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 cbf755d26b5..e2dd043c0c3 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -46,15 +46,16 @@
#include "IMB_imbuf_types.h"
#include "DNA_brush_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "BKE_colorband.h"
#include "BKE_context.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_brush.h"
#include "BKE_main.h"
#include "BKE_material.h"
+#include "BKE_mesh.h"
#include "BKE_node.h"
#include "BKE_paint.h"
#include "BKE_undo_system.h"
@@ -74,12 +75,14 @@
#include "WM_api.h"
#include "WM_types.h"
#include "WM_message.h"
+#include "WM_toolsystem.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "GPU_draw.h"
#include "GPU_immediate.h"
+#include "GPU_state.h"
#include "BIF_gl.h"
@@ -168,7 +171,7 @@ void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short te
IMB_partial_display_buffer_update_delayed(ibuf, imapaintpartial.x1, imapaintpartial.y1,
imapaintpartial.x2, imapaintpartial.y2);
}
-
+
if (ibuf->mipmap[0])
ibuf->userflags |= IB_MIPMAP_INVALID;
@@ -194,7 +197,7 @@ BlurKernel *paint_new_blur_kernel(Brush *br, bool proj)
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");
@@ -203,15 +206,15 @@ BlurKernel *paint_new_blur_kernel(Brush *br, bool proj)
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++)
@@ -220,9 +223,9 @@ BlurKernel *paint_new_blur_kernel(Brush *br, bool proj)
case KERNEL_GAUSSIAN:
{
- /* at 3.0 standard deviations distance, kernel is about zero */
- float standard_dev = radius / 3.0f;
-
+ /* 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;
@@ -231,7 +234,7 @@ BlurKernel *paint_new_blur_kernel(Brush *br, bool proj)
float idist = radius - i;
float jdist = radius - j;
float value = exp((idist * idist + jdist * jdist) / standard_dev);
-
+
kernel->wdata[i + j * side] = value;
}
}
@@ -298,7 +301,7 @@ static int image_paint_poll(bContext *C)
return image_paint_poll_ex(C, true);
}
-static int image_paint_poll_ignore_tool(bContext *C)
+static int image_paint_ignore_tool_poll(bContext *C)
{
return image_paint_poll_ex(C, false);
}
@@ -311,7 +314,7 @@ static int image_paint_2d_clone_poll(bContext *C)
if (brush && (brush->imagepaint_tool == PAINT_TOOL_CLONE))
if (brush->clone.image)
return 1;
-
+
return 0;
}
@@ -411,15 +414,15 @@ static void gradient_draw_line(bContext *UNUSED(C), int x, int y, void *customda
PaintOperation *pop = (PaintOperation *)customdata;
if (pop) {
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
+ GPU_line_smooth(true);
+ GPU_blend(true);
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- glLineWidth(4.0);
+ GPU_line_width(4.0);
immUniformColor4ub(0, 0, 0, 255);
immBegin(GWN_PRIM_LINES, 2);
@@ -427,7 +430,7 @@ static void gradient_draw_line(bContext *UNUSED(C), int x, int y, void *customda
immVertex2i(pos, pop->startmouse[0], pop->startmouse[1]);
immEnd();
- glLineWidth(2.0);
+ GPU_line_width(2.0);
immUniformColor4ub(255, 255, 255, 255);
immBegin(GWN_PRIM_LINES, 2);
@@ -437,8 +440,8 @@ static void gradient_draw_line(bContext *UNUSED(C), int x, int y, void *customda
immUnbindProgram();
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
+ GPU_blend(false);
+ GPU_line_smooth(false);
}
}
@@ -464,7 +467,7 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const flo
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;
+ return NULL;
}
pop->mode = PAINT_MODE_3D_PROJECT;
pop->custom_paint = paint_proj_new_stroke(C, ob, mouse, mode);
@@ -482,7 +485,7 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const flo
if ((brush->imagepaint_tool == PAINT_TOOL_FILL) && (brush->flag & BRUSH_USE_GRADIENT)) {
pop->cursor = WM_paint_cursor_activate(CTX_wm_manager(C), image_paint_poll, gradient_draw_line, pop);
}
-
+
settings->imapaint.flag |= IMAGEPAINT_DRAWING;
ED_image_undo_push_begin(op->type->name);
@@ -738,7 +741,7 @@ static void toggle_paint_cursor(bContext *C, int enable)
* purpose is to make sure the paint cursor is shown if paint
* mode is enabled in the image editor. the paint poll will
* ensure that the cursor is hidden when not in paint mode */
-void ED_space_image_paint_update(wmWindowManager *wm, Scene *scene)
+void ED_space_image_paint_update(Main *bmain, wmWindowManager *wm, Scene *scene)
{
ToolSettings *settings = scene->toolsettings;
ImagePaintSettings *imapaint = &settings->imapaint;
@@ -757,7 +760,7 @@ void ED_space_image_paint_update(wmWindowManager *wm, Scene *scene)
}
if (enabled) {
- BKE_paint_init(scene, ePaintTexture2D, PAINT_CURSOR_TEXTURE_PAINT);
+ BKE_paint_init(bmain, scene, ePaintTexture2D, PAINT_CURSOR_TEXTURE_PAINT);
paint_cursor_start_explicit(&imapaint->paint, wm, image_paint_poll);
}
@@ -849,7 +852,7 @@ void PAINT_OT_grab_clone(wmOperatorType *ot)
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;
@@ -884,7 +887,7 @@ static void sample_color_update_header(SampleColorData *data, bContext *C)
!data->sample_palette ?
IFACE_("Brush. Use Left Click to sample for palette instead") :
IFACE_("Palette. Use Left Click to sample more colors"));
- ED_area_headerprint(sa, msg);
+ ED_workspace_status_text(C, msg);
}
}
@@ -914,7 +917,7 @@ static int sample_color_exec(bContext *C, wmOperator *op)
}
WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
-
+
return OPERATOR_FINISHED;
}
@@ -963,8 +966,6 @@ static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event)
Brush *brush = BKE_paint_brush(paint);
if ((event->type == data->event_type) && (event->val == KM_RELEASE)) {
- ScrArea *sa = CTX_wm_area(C);
-
if (data->show_cursor) {
paint->flags |= PAINT_SHOW_BRUSH;
}
@@ -975,7 +976,7 @@ static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
WM_cursor_modal_restore(CTX_wm_window(C));
MEM_freeN(data);
- ED_area_headerprint(sa, NULL);
+ ED_workspace_status_text(C, NULL);
return OPERATOR_FINISHED;
}
@@ -1010,23 +1011,18 @@ static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-static int sample_color_poll(bContext *C)
-{
- return (image_paint_poll_ignore_tool(C) || image_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";
-
+
/* api callbacks */
ot->exec = sample_color_exec;
ot->invoke = sample_color_invoke;
ot->modal = sample_color_modal;
- ot->poll = sample_color_poll;
+ ot->poll = image_paint_ignore_tool_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1059,6 +1055,7 @@ static int texture_paint_toggle_poll(bContext *C)
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;
@@ -1074,14 +1071,13 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
ob->mode &= ~mode_flag;
if (U.glreslimit != 0)
- GPU_free_images();
- GPU_paint_set_mipmap(1);
+ GPU_free_images(bmain);
+ GPU_paint_set_mipmap(bmain, 1);
toggle_paint_cursor(C, 0);
}
else {
bScreen *sc;
- Main *bmain = CTX_data_main(C);
Image *ima = NULL;
ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
@@ -1090,7 +1086,7 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
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) {
Material *ma = give_current_material(ob, ob->actcol); /* set the current material active paint slot on image editor */
@@ -1100,8 +1096,8 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
}
else if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
ima = imapaint->canvas;
- }
-
+ }
+
if (ima) {
for (sc = bmain->screen.first; sc; sc = sc->id.next) {
ScrArea *sa;
@@ -1110,32 +1106,38 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
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(sima, scene, obedit, ima);
+ ED_space_image_set(bmain, sima, scene, obedit, ima);
}
}
}
}
}
}
-
+
ob->mode |= mode_flag;
- BKE_paint_init(scene, ePaintTextureProjective, PAINT_CURSOR_TEXTURE_PAINT);
+ BKE_paint_init(bmain, scene, ePaintTextureProjective, PAINT_CURSOR_TEXTURE_PAINT);
if (U.glreslimit != 0)
- GPU_free_images();
- GPU_paint_set_mipmap(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, DEG_TAG_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;
}
@@ -1145,7 +1147,7 @@ void PAINT_OT_texture_paint_toggle(wmOperatorType *ot)
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;
@@ -1165,7 +1167,7 @@ static int brush_colors_flip_exec(bContext *C, wmOperator *UNUSED(op))
br = image_paint_brush(C);
}
else {
- /* At the moment, wpaint does not support the color flipper.
+ /* At the moment, wpaint does not support the color flipper.
* So for now we're only handling vpaint */
ToolSettings *ts = CTX_data_tool_settings(C);
VPaint *vp = ts->vpaint;
@@ -1238,7 +1240,7 @@ static int texture_paint_poll(bContext *C)
if (texture_paint_toggle_poll(C))
if (CTX_data_active_object(C)->mode & OB_MODE_TEXTURE_PAINT)
return 1;
-
+
return 0;
}
@@ -1261,4 +1263,3 @@ int mask_paint_poll(bContext *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 c2ce9d83782..a75d6344849 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -582,7 +582,7 @@ static void brush_painter_imbuf_partial_update(BrushPainter *painter, const floa
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);
@@ -1132,13 +1132,13 @@ static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *curveb, unsign
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;
@@ -1232,7 +1232,7 @@ static int paint_2d_canvas_set(ImagePaintState *s, Image *ima)
/* set masking */
s->do_masking = paint_use_opacity_masking(s->brush);
-
+
return 1;
}
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index fd8fe84cffc..f7cac84b728 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -58,6 +58,7 @@
#include "DNA_brush_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
@@ -65,7 +66,6 @@
#include "BKE_colorband.h"
#include "BKE_context.h"
#include "BKE_colortools.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_idprop.h"
#include "BKE_brush.h"
#include "BKE_image.h"
@@ -74,6 +74,7 @@
#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
+#include "BKE_mesh_runtime.h"
#include "BKE_node.h"
#include "BKE_paint.h"
#include "BKE_report.h"
@@ -81,9 +82,11 @@
#include "BKE_texture.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "UI_interface.h"
+#include "ED_object.h"
#include "ED_mesh.h"
#include "ED_node.h"
#include "ED_paint.h"
@@ -351,28 +354,30 @@ typedef struct ProjPaintState {
SpinLock *tile_lock;
- DerivedMesh *dm;
- int dm_totlooptri;
- int dm_totpoly;
- int dm_totedge;
- int dm_totvert;
- bool dm_release;
+ Mesh *me_eval;
+ int totlooptri_eval;
+ int totpoly_eval;
+ int totedge_eval;
+ int totvert_eval;
- const MVert *dm_mvert;
- const MEdge *dm_medge;
- const MPoly *dm_mpoly;
- const MLoop *dm_mloop;
- const MLoopTri *dm_mlooptri;
+ const MVert *mvert_eval;
+ const MEdge *medge_eval;
+ const MPoly *mpoly_eval;
+ const MLoop *mloop_eval;
+ const MLoopTri *mlooptri_eval;
- const MLoopUV *dm_mloopuv_stencil;
+ const MLoopUV *mloopuv_stencil_eval;
/**
- * \note These UV layers are aligned to \a dm_mpoly
+ * \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 **dm_mloopuv;
- const MLoopUV **dm_mloopuv_clone; /* other UV map, use for cloning between layers */
+ const MLoopUV **poly_to_loop_uv;
+ const MLoopUV **poly_to_loop_uv_clone; /* other UV map, use for cloning between layers */
+
+ /* Actual material for each index, either from object or Mesh datablock... */
+ Material **mat_array;
bool use_colormanagement;
} ProjPaintState;
@@ -438,13 +443,13 @@ typedef struct {
BLI_INLINE const MPoly *ps_tri_index_to_mpoly(const ProjPaintState *ps, int tri_index)
{
- return &ps->dm_mpoly[ps->dm_mlooptri[tri_index].poly];
+ return &ps->mpoly_eval[ps->mlooptri_eval[tri_index].poly];
}
#define PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) \
- ps->dm_mloop[lt->tri[0]].v, \
- ps->dm_mloop[lt->tri[1]].v, \
- ps->dm_mloop[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, \
@@ -466,7 +471,7 @@ BLI_INLINE const MPoly *ps_tri_index_to_mpoly(const ProjPaintState *ps, int tri_
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->dm->mat[mp->mat_nr];
+ Material *ma = ps->mat_array[mp->mat_nr];
return ma ? ma->texpaintslot + ma->paint_active_slot : NULL;
}
@@ -477,7 +482,7 @@ static Image *project_paint_face_paint_image(const ProjPaintState *ps, int tri_i
}
else {
const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
- Material *ma = ps->dm->mat[mp->mat_nr];
+ 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;
}
@@ -486,14 +491,14 @@ static Image *project_paint_face_paint_image(const ProjPaintState *ps, int tri_i
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->dm->mat[mp->mat_nr];
+ 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->dm->mat[mp->mat_nr];
+ 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;
}
@@ -594,11 +599,11 @@ static int project_paint_PickFace(
for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
const int tri_index = GET_INT_FROM_POINTER(node->link);
- const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+ const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const float *vtri_ss[3] = {
- ps->screenCoords[ps->dm_mloop[lt->tri[0]].v],
- ps->screenCoords[ps->dm_mloop[lt->tri[1]].v],
- ps->screenCoords[ps->dm_mloop[lt->tri[2]].v],
+ 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],
};
@@ -653,8 +658,8 @@ static bool project_paint_PickColor(
if (tri_index == -1)
return 0;
- lt = &ps->dm_mlooptri[tri_index];
- PS_LOOPTRI_ASSIGN_UV_3(lt_tri_uv, ps->dm_mloopuv, lt);
+ 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);
@@ -810,19 +815,19 @@ static bool project_bucket_point_occluded(
const int tri_index = GET_INT_FROM_POINTER(bucketFace->link);
if (orig_face != tri_index) {
- const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+ const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const float *vtri_ss[3] = {
- ps->screenCoords[ps->dm_mloop[lt->tri[0]].v],
- ps->screenCoords[ps->dm_mloop[lt->tri[1]].v],
- ps->screenCoords[ps->dm_mloop[lt->tri[2]].v],
+ 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->dm_mvert[ps->dm_mloop[lt->tri[0]].v].co,
- ps->dm_mvert[ps->dm_mloop[lt->tri[1]].v].co,
- ps->dm_mvert[ps->dm_mloop[lt->tri[2]].v].co,
+ 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),
@@ -1002,8 +1007,8 @@ static bool pixel_bounds_array(float (*uv)[2], rcti *bounds_px, const int ibuf_x
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->dm_mlooptri[tri_index];
- const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv, lt) };
+ 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)
@@ -1019,11 +1024,11 @@ static bool check_seam(
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->dm_mlooptri[orig_face];
- const float *orig_lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv, orig_lt) };
+ 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->dm_mloop[orig_lt->tri[orig_i1_fidx]].v;
- const unsigned int i2 = ps->dm_mloop[orig_lt->tri[orig_i2_fidx]].v;
+ 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;
int i1_fidx = -1, i2_fidx = -1; /* index in face */
@@ -1031,7 +1036,7 @@ static bool check_seam(
const int tri_index = GET_INT_FROM_POINTER(node->link);
if (tri_index != orig_face) {
- const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+ 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 */
@@ -1044,7 +1049,7 @@ static bool check_seam(
/* 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->dm_mloopuv, lt) };
+ 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);
@@ -1054,7 +1059,7 @@ static bool check_seam(
/* 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;
@@ -1348,8 +1353,8 @@ static float project_paint_uvpixel_mask(
Image *other_tpage = ps->stencil_ima;
if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
- const MLoopTri *lt_other = &ps->dm_mlooptri[tri_index];
- const float *lt_other_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv, lt_other) };
+ 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];
@@ -1382,7 +1387,7 @@ static float project_paint_uvpixel_mask(
}
if (ps->do_mask_cavity) {
- const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+ 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]];
@@ -1397,16 +1402,16 @@ static float project_paint_uvpixel_mask(
/* calculate mask */
if (ps->do_mask_normal) {
- const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+ 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->dm_mpoly[lt->poly];
+ 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->dm_mvert[lt_vtri[0]].no;
- no2 = ps->dm_mvert[lt_vtri[1]].no;
- no3 = ps->dm_mvert[lt_vtri[2]].no;
+ 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];
@@ -1418,9 +1423,9 @@ static float project_paint_uvpixel_mask(
#if 1
/* normalizing per pixel isn't optimal, we could cache or check ps->*/
normal_tri_v3(no,
- ps->dm_mvert[lt_vtri[0]].co,
- ps->dm_mvert[lt_vtri[1]].co,
- ps->dm_mvert[lt_vtri[2]].co);
+ 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));
@@ -1439,9 +1444,9 @@ static float project_paint_uvpixel_mask(
/* 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->dm_mvert[lt_vtri[0]].co;
- co2 = ps->dm_mvert[lt_vtri[1]].co;
- co3 = ps->dm_mvert[lt_vtri[2]].co;
+ 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]));
@@ -1610,13 +1615,13 @@ static ProjPixel *project_paint_uvpixel_init(
/* done with view3d_project_float inline */
if (ps->tool == PAINT_TOOL_CLONE) {
- if (ps->dm_mloopuv_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->dm_mlooptri[tri_index];
- const float *lt_other_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv_clone, lt_other) };
+ 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 */
@@ -2116,7 +2121,7 @@ static void project_bucket_clip_face(
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.
@@ -2127,12 +2132,12 @@ static void project_bucket_clip_face(
{
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) !=
@@ -2149,20 +2154,20 @@ static void project_bucket_clip_face(
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 tringle 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);
@@ -2170,9 +2175,9 @@ static void project_bucket_clip_face(
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))
@@ -2186,7 +2191,7 @@ static void project_bucket_clip_face(
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,
@@ -2351,7 +2356,7 @@ static void project_bucket_clip_face(
(*tot)--;
}
}
-
+
/* its possible there is only a few left after remove doubles */
if ((*tot) < 3) {
// printf("removed too many doubles B\n");
@@ -2507,9 +2512,9 @@ static void project_paint_face_init(
ps->projImages + image_index
};
- const MLoopTri *lt = &ps->dm_mlooptri[tri_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->dm_mloopuv, lt) };
+ const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt) };
/* UV/pixel seeking data */
int x; /* Image X-Pixel */
@@ -2543,9 +2548,9 @@ static void project_paint_face_init(
const bool do_backfacecull = ps->do_backfacecull;
const bool do_clip = ps->rv3d ? ps->rv3d->rflag & RV3D_CLIPPING : 0;
- vCo[0] = ps->dm_mvert[lt_vtri[0]].co;
- vCo[1] = ps->dm_mvert[lt_vtri[1]].co;
- vCo[2] = ps->dm_mvert[lt_vtri[2]].co;
+ 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
@@ -2629,9 +2634,9 @@ static void project_paint_face_init(
if (do_clip || do_3d_mapping) {
interp_v3_v3v3v3(
wco,
- ps->dm_mvert[lt_vtri[0]].co,
- ps->dm_mvert[lt_vtri[1]].co,
- ps->dm_mvert[lt_vtri[2]].co,
+ 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)) {
continue; /* Watch out that no code below this needs to run */
@@ -2811,7 +2816,7 @@ static void project_paint_face_init(
!project_bucket_point_occluded(ps, bucketFaceNodes, tri_index, pixelScreenCo))
{
/* Only bother calculating the weights if we intersect */
- if (ps->do_mask_normal || ps->dm_mloopuv_clone) {
+ if (ps->do_mask_normal || ps->poly_to_loop_uv_clone) {
const float uv_fac = fac1 + (fac * (fac2 - fac1));
#if 0
/* get the UV on the line since we want to copy the pixels from there for bleeding */
@@ -2975,7 +2980,7 @@ static bool project_bucket_face_isect(ProjPaintState *ps, int bucket_x, int buck
int fidx;
project_bucket_bounds(ps, bucket_x, bucket_y, &bucket_bounds);
-
+
/* Is one of the faces verts in the bucket bounds? */
fidx = 2;
@@ -3064,26 +3069,8 @@ static void project_paint_delayed_face_init(ProjPaintState *ps, const MLoopTri *
#endif
}
-/**
- * \note when using subsurf or multires, some arrays are thrown away, we need to keep a copy
- */
-static void proj_paint_state_non_cddm_init(ProjPaintState *ps)
-{
- if (ps->dm->type != DM_TYPE_CDDM) {
- ps->dm_mvert = MEM_dupallocN(ps->dm_mvert);
- ps->dm_mpoly = MEM_dupallocN(ps->dm_mpoly);
- ps->dm_mloop = MEM_dupallocN(ps->dm_mloop);
- /* looks like these are ok for now.*/
-#if 0
- ps->dm_mloopuv = MEM_dupallocN(ps->dm_mloopuv);
- ps->dm_mloopuv_clone = MEM_dupallocN(ps->dm_mloopuv_clone);
- ps->dm_mloopuv_stencil = MEM_dupallocN(ps->dm_mloopuv_stencil);
-#endif
- }
-}
-
static void proj_paint_state_viewport_init(
- ProjPaintState *ps, const char symmetry_flag)
+ ProjPaintState *ps, const Depsgraph *depsgraph, const char symmetry_flag)
{
float mat[3][3];
float viewmat[4][4];
@@ -3144,17 +3131,17 @@ static void proj_paint_state_viewport_init(
invert_m4_m4(viewinv, viewmat);
}
else if (ps->source == PROJ_SRC_IMAGE_CAM) {
- Object *cam_ob = ps->scene->camera;
+ Object *cam_ob_eval = DEG_get_evaluated_object(depsgraph, ps->scene->camera);
CameraParams params;
/* viewmat & viewinv */
- copy_m4_m4(viewinv, cam_ob->obmat);
+ 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);
+ 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);
@@ -3201,11 +3188,11 @@ static void proj_paint_state_screen_coords_init(ProjPaintState *ps, const int di
INIT_MINMAX2(ps->screenMin, ps->screenMax);
- ps->screenCoords = MEM_mallocN(sizeof(float) * ps->dm_totvert * 4, "ProjectPaint ScreenVerts");
+ ps->screenCoords = MEM_mallocN(sizeof(float) * ps->totvert_eval * 4, "ProjectPaint ScreenVerts");
projScreenCo = *ps->screenCoords;
if (ps->is_ortho) {
- for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++, projScreenCo += 4) {
+ 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 */
@@ -3215,7 +3202,7 @@ static void proj_paint_state_screen_coords_init(ProjPaintState *ps, const int di
}
}
else {
- for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++, projScreenCo += 4) {
+ 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;
@@ -3276,21 +3263,21 @@ static void proj_paint_state_cavity_init(ProjPaintState *ps)
int a;
if (ps->do_mask_cavity) {
- int *counter = MEM_callocN(sizeof(int) * ps->dm_totvert, "counter");
- float (*edges)[3] = MEM_callocN(sizeof(float) * 3 * ps->dm_totvert, "edges");
- ps->cavities = MEM_mallocN(sizeof(float) * ps->dm_totvert, "ProjectPaint Cavities");
+ 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->dm_medge; a < ps->dm_totedge; a++, me++) {
+ for (a = 0, me = ps->medge_eval; a < ps->totedge_eval; a++, me++) {
float e[3];
- sub_v3_v3v3(e, ps->dm_mvert[me->v1].co, ps->dm_mvert[me->v2].co);
+ 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->dm_mvert; a < ps->dm_totvert; a++, mv++) {
+ 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]);
@@ -3311,10 +3298,10 @@ static void proj_paint_state_cavity_init(ProjPaintState *ps)
static void proj_paint_state_seam_bleed_init(ProjPaintState *ps)
{
if (ps->seam_bleed_px > 0.0f) {
- ps->vertFaces = MEM_callocN(sizeof(LinkNode *) * ps->dm_totvert, "paint-vertFaces");
- ps->faceSeamFlags = MEM_callocN(sizeof(char) * ps->dm_totlooptri, "paint-faceSeamFlags");
- ps->faceWindingFlags = MEM_callocN(sizeof(char) * ps->dm_totlooptri, "paint-faceWindindFlags");
- ps->faceSeamUVs = MEM_mallocN(sizeof(float[3][2]) * ps->dm_totlooptri, "paint-faceSeamUVs");
+ ps->vertFaces = MEM_callocN(sizeof(LinkNode *) * ps->totvert_eval, "paint-vertFaces");
+ ps->faceSeamFlags = MEM_callocN(sizeof(char) * ps->totlooptri_eval, "paint-faceSeamFlags");
+ ps->faceWindingFlags = MEM_callocN(sizeof(char) * ps->totlooptri_eval, "paint-faceWindindFlags");
+ ps->faceSeamUVs = MEM_mallocN(sizeof(float[3][2]) * ps->totlooptri_eval, "paint-faceSeamUVs");
}
}
#endif
@@ -3358,9 +3345,9 @@ static void proj_paint_state_vert_flags_init(ProjPaintState *ps)
float no[3];
int a;
- ps->vertFlags = MEM_callocN(sizeof(char) * ps->dm_totvert, "paint-vertFlags");
+ ps->vertFlags = MEM_callocN(sizeof(char) * ps->totvert_eval, "paint-vertFlags");
- for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++) {
+ 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);
@@ -3405,58 +3392,63 @@ static void project_paint_bleed_add_face_user(
}
#endif
-/* Return true if DM can be painted on, false otherwise */
-static bool proj_paint_state_dm_init(const bContext *C, ProjPaintState *ps)
+/* 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);
+ Scene *sce = ps->scene;
+ Object *ob = ps->ob;
/* Workaround for subsurf selection, try the display mesh first */
+ /* XXX Don't think this is easily doable with new system, and not sure why that was needed in the first place :/ */
+#if 0
if (ps->source == PROJ_SRC_IMAGE_CAM) {
/* using render mesh, assume only camera was rendered from */
- ps->dm = mesh_create_derived_render(depsgraph, ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MTFACE);
+ ps->dm = mesh_create_derived_render(
+ depsgraph, ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MLOOPUV | CD_MASK_MTFACE);
ps->dm_release = true;
}
- else if (ps->ob->derivedFinal &&
- CustomData_has_layer(&ps->ob->derivedFinal->loopData, CD_MLOOPUV) &&
- (ps->do_face_sel == false || CustomData_has_layer(&ps->ob->derivedFinal->polyData, CD_ORIGINDEX)))
- {
- ps->dm = ps->ob->derivedFinal;
- ps->dm_release = false;
- }
else {
ps->dm = mesh_get_derived_final(
depsgraph, ps->scene, ps->ob,
- ps->scene->customdata_mask | CD_MASK_MTFACE | (ps->do_face_sel ? CD_ORIGINDEX : 0));
- ps->dm_release = true;
+ ps->scene->customdata_mask | CD_MASK_MLOOPUV | CD_MASK_MTFACE | (ps->do_face_sel ? CD_MASK_ORIGINDEX : 0));
+ ps->dm_release = false;
}
-
- if (!CustomData_has_layer(&ps->dm->loopData, CD_MLOOPUV)) {
-
- if (ps->dm_release)
- ps->dm->release(ps->dm);
-
- ps->dm = NULL;
+#endif
+ ps->me_eval = mesh_get_eval_final(
+ depsgraph, sce, ob,
+ sce->customdata_mask | CD_MASK_MLOOPUV | CD_MASK_MTFACE | (ps->do_face_sel ? CD_MASK_ORIGINDEX : 0));
+ if (!CustomData_has_layer(&ps->me_eval->ldata, CD_MLOOPUV)) {
+ ps->me_eval = NULL;
return false;
}
- DM_update_materials(ps->dm, ps->ob);
-
- ps->dm_mvert = ps->dm->getVertArray(ps->dm);
-
- if (ps->do_mask_cavity)
- ps->dm_medge = ps->dm->getEdgeArray(ps->dm);
+ /* Build final material array, we use this a lot here. */
+ const int totmat = ob->totcol + 1; /* materials start from 1, default material is 0 */
+ 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->dm_mloop = ps->dm->getLoopArray(ps->dm);
- ps->dm_mpoly = ps->dm->getPolyArray(ps->dm);
+ 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->dm_mlooptri = ps->dm->getLoopTriArray(ps->dm);
+ ps->totvert_eval = ps->me_eval->totvert;
+ ps->totedge_eval = ps->me_eval->totedge;
+ ps->totpoly_eval = ps->me_eval->totpoly;
- ps->dm_totvert = ps->dm->getNumVerts(ps->dm);
- ps->dm_totedge = ps->dm->getNumEdges(ps->dm);
- ps->dm_totpoly = ps->dm->getNumPolys(ps->dm);
- ps->dm_totlooptri = ps->dm->getNumLoopTri(ps->dm);
+ ps->mlooptri_eval = BKE_mesh_runtime_looptri_ensure(ps->me_eval);
+ ps->totlooptri_eval = ps->me_eval->runtime.looptris.len;
- ps->dm_mloopuv = MEM_mallocN(ps->dm_totpoly * sizeof(MLoopUV *), "proj_paint_mtfaces");
+ ps->poly_to_loop_uv = MEM_mallocN(ps->totpoly_eval * sizeof(MLoopUV *), "proj_paint_mtfaces");
return true;
}
@@ -3477,16 +3469,16 @@ static void proj_paint_layer_clone_init(
if (ps->do_layer_clone) {
const int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->ldata, CD_MLOOPUV);
- ps->dm_mloopuv_clone = MEM_mallocN(ps->dm_totpoly * 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->dm->loopData, CD_MLOOPUV, layer_num);
+ 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->dm->loopData, CD_MLOOPUV);
+ mloopuv_clone_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
}
-
+
}
memset(layer_clone, 0, sizeof(*layer_clone));
@@ -3512,19 +3504,19 @@ static bool project_paint_clone_face_skip(
if (ps->do_material_slots) {
if (lc->slot_clone != lc->slot_last_clone) {
- if (!slot->uvname ||
+ if (!slot->uvname ||
!(lc->mloopuv_clone_base = CustomData_get_layer_named(
- &ps->dm->loopData, CD_MLOOPUV,
+ &ps->me_eval->ldata, CD_MLOOPUV,
lc->slot_clone->uvname)))
{
- lc->mloopuv_clone_base = CustomData_get_layer(&ps->dm->loopData, CD_MLOOPUV);
+ 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->dm_mloopuv_clone[ps->dm_mlooptri[tri_index].poly] = lc->mloopuv_clone_base;
+ ps->poly_to_loop_uv_clone[ps->mlooptri_eval[tri_index].poly] = lc->mloopuv_clone_base;
}
return false;
}
@@ -3541,7 +3533,7 @@ static void proj_paint_face_lookup_init(
{
memset(face_lookup, 0, sizeof(*face_lookup));
if (ps->do_face_sel) {
- face_lookup->index_mp_to_orig = ps->dm->getPolyDataArray(ps->dm, CD_ORIGINDEX);
+ face_lookup->index_mp_to_orig = CustomData_get_layer(&ps->me_eval->pdata, CD_ORIGINDEX);
face_lookup->mpoly_orig = ((Mesh *)ps->ob->data)->mpoly;
}
}
@@ -3562,7 +3554,7 @@ static bool project_paint_check_face_sel(
mp = &face_lookup->mpoly_orig[orig_index];
}
else {
- mp = &ps->dm_mpoly[lt->poly];
+ mp = &ps->mpoly_eval[lt->poly];
}
return ((mp->flag & ME_FACE_SEL) != 0);
@@ -3676,7 +3668,7 @@ static void project_paint_prepare_all_faces(
int image_index = -1, tri_index;
int prev_poly = -1;
- for (tri_index = 0, lt = ps->dm_mlooptri; tri_index < ps->dm_totlooptri; tri_index++, lt++) {
+ for (tri_index = 0, lt = ps->mlooptri_eval; tri_index < ps->totlooptri_eval; tri_index++, lt++) {
bool is_face_sel;
#ifndef PROJ_DEBUG_NOSEAMBLEED
@@ -3689,13 +3681,13 @@ static void project_paint_prepare_all_faces(
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->dm->loopData, CD_MLOOPUV);
+ 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->dm->loopData, CD_MLOOPUV, slot->uvname)))
- mloopuv_base = CustomData_get_layer(&ps->dm->loopData, CD_MLOOPUV);
+ 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;
}
@@ -3703,10 +3695,10 @@ static void project_paint_prepare_all_faces(
if (slot->ima == ps->stencil_ima) {
/* 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. */
- ps->dm_mloopuv[lt->poly] = mloopuv_base;
+ ps->poly_to_loop_uv[lt->poly] = mloopuv_base;
continue;
}
-
+
tpage = slot->ima;
}
}
@@ -3714,7 +3706,7 @@ static void project_paint_prepare_all_faces(
tpage = ps->stencil_ima;
}
- ps->dm_mloopuv[lt->poly] = mloopuv_base;
+ ps->poly_to_loop_uv[lt->poly] = mloopuv_base;
if (project_paint_clone_face_skip(ps, layer_clone, slot, tri_index)) {
continue;
@@ -3745,11 +3737,11 @@ static void project_paint_prepare_all_faces(
if (prev_poly != lt->poly) {
int iloop;
bool culled = true;
- const MPoly *poly = ps->dm_mpoly + lt->poly;
+ 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->dm_mloop[poly->loopstart + iloop].v] & PROJ_VERT_CULL)) {
+ if (!(ps->vertFlags[ps->mloop_eval[poly->loopstart + iloop].v] & PROJ_VERT_CULL)) {
culled = false;
break;
}
@@ -3828,7 +3820,7 @@ static void project_paint_begin(
/* paint onto the derived mesh */
if (ps->is_shared_user == false) {
- if (!proj_paint_state_dm_init(C, ps)) {
+ if (!proj_paint_state_mesh_eval_init(C, ps)) {
return;
}
}
@@ -3837,28 +3829,26 @@ static void project_paint_begin(
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->dm->loopData, CD_MLOOPUV);
+ //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->dm_mloopuv_stencil = CustomData_get_layer_n(&ps->dm->loopData, CD_MLOOPUV, layer_num);
+ ps->mloopuv_stencil_eval = CustomData_get_layer_n(&ps->me_eval->ldata, CD_MLOOPUV, layer_num);
- if (ps->dm_mloopuv_stencil == NULL) {
+ if (ps->mloopuv_stencil_eval == NULL) {
/* get active instead */
- ps->dm_mloopuv_stencil = CustomData_get_layer(&ps->dm->loopData, CD_MLOOPUV);
+ ps->mloopuv_stencil_eval = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
}
if (ps->do_stencil_brush)
- mloopuv_base = ps->dm_mloopuv_stencil;
+ 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_non_cddm_init(ps);
-
proj_paint_state_cavity_init(ps);
}
- proj_paint_state_viewport_init(ps, symmetry_flag);
+ proj_paint_state_viewport_init(ps, CTX_data_depsgraph(C), symmetry_flag);
/* calculate vert screen coords
* run this early so we can calculate the x/y resolution of our bucket rect */
@@ -3944,14 +3934,17 @@ static void project_paint_end(ProjPaintState *ps)
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->dm_mloopuv || ps->is_shared_user);
- if (ps->dm_mloopuv)
- MEM_freeN((void *)ps->dm_mloopuv);
+ 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->dm_mloopuv_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);
@@ -3971,22 +3964,6 @@ static void project_paint_end(ProjPaintState *ps)
if (ps->do_mask_cavity) {
MEM_freeN(ps->cavities);
}
-
- /* copy for subsurf/multires, so throw away */
- if (ps->dm->type != DM_TYPE_CDDM) {
- if (ps->dm_mvert) MEM_freeN((void *)ps->dm_mvert);
- if (ps->dm_mpoly) MEM_freeN((void *)ps->dm_mpoly);
- if (ps->dm_mloop) MEM_freeN((void *)ps->dm_mloop);
- /* looks like these don't need copying */
-#if 0
- if (ps->dm_mloopuv) MEM_freeN(ps->dm_mloopuv);
- if (ps->dm_mloopuv_clone) MEM_freeN(ps->dm_mloopuv_clone);
- if (ps->dm_mloopuv_stencil) MEM_freeN(ps->dm_mloopuv_stencil);
-#endif
- }
-
- if (ps->dm_release)
- ps->dm->release(ps->dm);
}
if (ps->blurkernel) {
@@ -4398,7 +4375,7 @@ static void do_projectpaint_draw_f(ProjPaintState *ps, ProjPixel *projPixel, con
if (ps->is_texbrush)
mul_v3_v3(rgba, texrgb);
-
+
mul_v3_fl(rgba, mask);
rgba[3] = mask;
@@ -4607,7 +4584,7 @@ static void *do_projectpaint_thread(void *ph_v)
projPixel->newColor.ch, ps->blend);
}
}
-
+
if (lock_alpha) {
if (is_floatbuf) {
/* slightly more involved case since floats are in premultiplied space we need
@@ -4685,7 +4662,7 @@ static void *do_projectpaint_thread(void *ph_v)
/* 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;
@@ -4861,7 +4838,7 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
struct ImagePool *pool;
if (!project_bucket_iter_init(ps, pos)) {
- return 0;
+ return touch_any;
}
if (ps->thread_tot > 1)
@@ -4918,34 +4895,34 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
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->dm_mlooptri[tri_index];
+ 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->dm_mvert[lt_vtri[0]].co,
- ps->dm_mvert[lt_vtri[1]].co,
- ps->dm_mvert[lt_vtri[2]].co,
+ 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;
}
@@ -5012,7 +4989,7 @@ void paint_proj_stroke(
/* 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 *graph = CTX_data_depsgraph(C);
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
View3D *v3d = CTX_wm_view3d(C);
ARegion *ar = CTX_wm_region(C);
float *cursor = ED_view3d_cursor3d_get(scene, v3d)->location;
@@ -5020,7 +4997,7 @@ void paint_proj_stroke(
view3d_operator_needs_opengl(C);
- if (!ED_view3d_autodist(graph, ar, v3d, mval_i, cursor, false, NULL)) {
+ if (!ED_view3d_autodist(depsgraph, ar, v3d, mval_i, cursor, false, NULL)) {
return;
}
@@ -5084,9 +5061,9 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
ps->do_material_slots = (settings->imapaint.mode == IMAGEPAINT_MODE_MATERIAL);
ps->stencil_ima = settings->imapaint.stencil;
- ps->canvas_ima = (!ps->do_material_slots) ?
+ ps->canvas_ima = (!ps->do_material_slots) ?
settings->imapaint.canvas : NULL;
- ps->clone_ima = (!ps->do_material_slots) ?
+ 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;
@@ -5225,13 +5202,11 @@ void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int m
}
project_paint_begin(C, ps, is_multi_view, symmetry_flag_views[i]);
-
- paint_proj_begin_clone(ps, mouse);
-
- if (ps->dm == NULL) {
+ if (ps->me_eval == NULL) {
goto fail;
- return NULL;
}
+
+ paint_proj_begin_clone(ps, mouse);
}
paint_brush_init_tex(ps_handle->brush);
@@ -5318,7 +5293,7 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
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;
+ return OPERATOR_CANCELLED;
}
project_state_init(C, ob, &ps, BRUSH_STROKE_NORMAL);
@@ -5379,8 +5354,9 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
/* allocate and initialize spatial data structures */
project_paint_begin(C, &ps, false, 0);
- if (ps.dm == NULL) {
+ 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 {
@@ -5434,6 +5410,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
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;
@@ -5463,7 +5440,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- image = BKE_image_add_from_imbuf(ibuf, "image_view");
+ image = BKE_image_add_from_imbuf(bmain, ibuf, "image_view");
/* Drop reference to ibuf so that the image owns it */
IMB_freeImBuf(ibuf);
@@ -5518,7 +5495,7 @@ 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!",
+ BKE_reportf(reports, RPT_WARNING, "Missing%s%s%s%s detected!",
!uvs ? " UVs," : "",
!mat ? " Materials," : "",
!tex ? " Textures," : "",
@@ -5539,7 +5516,7 @@ bool BKE_paint_proj_mesh_data_check(Scene *scene, Object *ob, bool *uvs, bool *m
bool hasuvs = true;
imapaint->missing_data = 0;
-
+
BLI_assert(ob->type == OB_MESH);
if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
@@ -5553,16 +5530,16 @@ bool BKE_paint_proj_mesh_data_check(Scene *scene, Object *ob, bool *uvs, bool *m
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;
@@ -5582,7 +5559,7 @@ bool BKE_paint_proj_mesh_data_check(Scene *scene, Object *ob, bool *uvs, bool *m
hastex = false;
}
}
-
+
me = BKE_mesh_from_object(ob);
layernum = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
@@ -5603,7 +5580,7 @@ bool BKE_paint_proj_mesh_data_check(Scene *scene, Object *ob, bool *uvs, bool *m
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;
}
@@ -5616,7 +5593,7 @@ bool BKE_paint_proj_mesh_data_check(Scene *scene, Object *ob, bool *uvs, bool *m
if (stencil) {
*stencil = hasstencil;
}
-
+
return hasuvs && hasmat && hastex && hasstencil;
}
@@ -5653,13 +5630,13 @@ static Image *proj_paint_image_create(wmOperator *op, Main *bmain)
}
ima = BKE_image_add_generated(bmain, width, height, imagename, alpha ? 32 : 24, use_float,
gen_type, color, false);
-
+
return ima;
}
static bool proj_paint_add_slot(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = ED_object_active_context(C);
Scene *scene = CTX_data_scene(C);
Material *ma;
Image *ima = NULL;
@@ -5680,32 +5657,32 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
ED_node_shader_default(C, &ma->id);
ntree = ma->nodetree;
}
-
+
ma->use_nodes = true;
-
+
/* 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;
-
+
nodeSetActive(ntree, imanode);
-
+
ntreeUpdateTree(CTX_data_main(C), ntree);
-
+
if (ima) {
BKE_texpaint_slot_refresh_cache(scene, ma);
- BKE_image_signal(ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE);
+ 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(&ma->id, 0);
ED_area_tag_redraw(CTX_wm_area(C));
-
+
BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
-
+
return true;
}
}
-
+
return false;
}
@@ -5723,16 +5700,17 @@ static int texture_paint_add_texture_paint_slot_exec(bContext *C, wmOperator *op
static int texture_paint_add_texture_paint_slot_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
char imagename[MAX_ID_NAME - 2];
- Object *ob = CTX_data_active_object(C);
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_active_context(C);
Material *ma = give_current_material(ob, ob->actcol);
int type = RNA_enum_get(op->ptr, "type");
if (!ma) {
- ma = BKE_material_add(CTX_data_main(C), "Material");
+ ma = BKE_material_add(bmain, "Material");
/* no material found, just assign to first slot */
- assign_material(ob, ma, ob->actcol, BKE_MAT_ASSIGN_USERPREF);
+ assign_material(bmain, ob, ma, ob->actcol, BKE_MAT_ASSIGN_USERPREF);
}
-
+
type = RNA_enum_from_value(layer_type_items, type);
/* get the name of the texture layer type */
@@ -5761,7 +5739,7 @@ void PAINT_OT_add_texture_paint_slot(wmOperatorType *ot)
/* api callbacks */
ot->invoke = texture_paint_add_texture_paint_slot_invoke;
ot->exec = texture_paint_add_texture_paint_slot_exec;
- ot->poll = ED_operator_region_view3d_active;
+ ot->poll = ED_operator_object_active;
/* flags */
ot->flag = OPTYPE_UNDO;
@@ -5786,6 +5764,7 @@ void PAINT_OT_add_texture_paint_slot(wmOperatorType *ot)
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);
Mesh *me = ob->data;
@@ -5810,14 +5789,14 @@ static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op))
/* set the margin really quickly before the packing operation*/
scene->toolsettings->uvcalc_margin = 0.001f;
ED_uvedit_pack_islands(scene, ob, bm, false, false, true);
- BM_mesh_bm_to_me(bm, me, (&(struct BMeshToMeshParams){0}));
+ BM_mesh_bm_to_me(bmain, bm, me, (&(struct BMeshToMeshParams){0}));
BM_mesh_free(bm);
if (synch_selection)
scene->toolsettings->uv_flag |= UV_SYNC_SELECTION;
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);
@@ -5848,4 +5827,3 @@ void PAINT_OT_add_simple_uvs(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index a6d8a90e95a..8d94978f5c6 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index f22e6f514e6..4a338e65d79 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -45,7 +45,6 @@
#include "BKE_pbvh.h"
#include "BKE_ccg.h"
#include "BKE_context.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_multires.h"
#include "BKE_paint.h"
#include "BKE_subsurf.h"
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index 3afff02ec52..56908811008 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -47,6 +47,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_toolsystem.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -87,10 +88,10 @@ static void BRUSH_OT_add(wmOperatorType *ot)
ot->name = "Add Brush";
ot->description = "Add brush by mode type";
ot->idname = "BRUSH_OT_add";
-
+
/* api callbacks */
ot->exec = brush_add_exec;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -144,10 +145,10 @@ static void BRUSH_OT_scale_size(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -285,10 +286,10 @@ static void BRUSH_OT_reset(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -353,7 +354,7 @@ static Brush *brush_tool_toggle(Main *bmain, Brush *brush_orig, const int tool,
/* store the previously-selected brush */
if (br)
br->toggle_brush = brush_orig;
-
+
return br;
}
else if (brush_orig->toggle_brush) {
@@ -452,9 +453,23 @@ static int brush_select_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- return brush_generic_tool_set(bmain, paint, tool, tool_offset,
- paint_mode, tool_name, create_missing,
- toggle);
+ /* TODO(campbell): Use the toolsystem for now, ideally the toolsystem will display brushes directly
+ * so we don't need to sync between tools and brushes. */
+ if (false) {
+ return brush_generic_tool_set(
+ bmain, paint, tool, tool_offset,
+ paint_mode, tool_name, create_missing,
+ toggle);
+ }
+ else {
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ if (WM_toolsystem_ref_set_by_name(C, workspace, NULL, tool_name, true)) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+ }
}
static void PAINT_OT_brush_select(wmOperatorType *ot)
@@ -493,16 +508,17 @@ static void PAINT_OT_brush_select(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-static wmKeyMapItem *keymap_brush_select(wmKeyMap *keymap, int paint_mode,
- int tool, int keymap_type,
- int keymap_modifier)
+static wmKeyMapItem *keymap_brush_select(
+ wmKeyMap *keymap, int paint_mode,
+ int tool, int keymap_type,
+ int keymap_modifier)
{
wmKeyMapItem *kmi;
kmi = WM_keymap_add_item(keymap, "PAINT_OT_brush_select",
keymap_type, KM_PRESS, keymap_modifier, 0);
RNA_enum_set(kmi->ptr, "paint_mode", paint_mode);
-
+
switch (paint_mode) {
case OB_MODE_SCULPT:
RNA_enum_set(kmi->ptr, "sculpt_tool", tool);
@@ -914,7 +930,7 @@ static int stencil_reset_transform_exec(bContext *C, wmOperator *op)
if (!br)
return OPERATOR_CANCELLED;
-
+
if (do_mask) {
br->mask_stencil_pos[0] = 256;
br->mask_stencil_pos[1] = 256;
@@ -1080,20 +1096,6 @@ void ED_operatortypes_paint(void)
WM_operatortype_append(PAINT_OT_mask_lasso_gesture);
}
-
-static void ed_keymap_paint_brush_switch(wmKeyMap *keymap, const char *mode)
-{
- wmKeyMapItem *kmi;
- int i;
- /* index 0-9 (zero key is tenth), shift key for index 10-19 */
- for (i = 0; i < 20; i++) {
- kmi = WM_keymap_add_item(keymap, "BRUSH_OT_active_index_set",
- ZEROKEY + ((i + 1) % 10), KM_PRESS, i < 10 ? 0 : KM_SHIFT, 0);
- RNA_string_set(kmi->ptr, "mode", mode);
- RNA_int_set(kmi->ptr, "index", i);
- }
-}
-
static void ed_keymap_paint_brush_size(wmKeyMap *keymap, const char *UNUSED(path))
{
wmKeyMapItem *kmi;
@@ -1199,7 +1201,7 @@ static void ed_keymap_paint_brush_radial_control(wmKeyMap *keymap, const char *p
static void paint_partial_visibility_keys(wmKeyMap *keymap)
{
wmKeyMapItem *kmi;
-
+
/* Partial visibility */
kmi = WM_keymap_add_item(keymap, "PAINT_OT_hide_show", HKEY, KM_PRESS, KM_SHIFT, 0);
RNA_enum_set(kmi->ptr, "action", PARTIALVIS_SHOW);
@@ -1228,7 +1230,9 @@ static void paint_keymap_curve(wmKeyMap *keymap)
RNA_boolean_set(kmi->ptr, "toggle", true);
WM_keymap_add_item(keymap, "PAINTCURVE_OT_cursor", ACTIONMOUSE, KM_PRESS, 0, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "PAINTCURVE_OT_delete_point", XKEY, KM_PRESS, 0, 0);
+#endif
WM_keymap_add_item(keymap, "PAINTCURVE_OT_delete_point", DELKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "PAINTCURVE_OT_draw", RETKEY, KM_PRESS, 0, 0);
@@ -1245,7 +1249,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
wmKeyMap *keymap;
wmKeyMapItem *kmi;
int i;
-
+
keymap = WM_keymap_find(keyconf, "Paint Curve", 0, 0);
keymap->poll = paint_curve_poll;
@@ -1284,7 +1288,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "SCULPT_OT_dynamic_topology_toggle", DKEY, KM_PRESS, KM_CTRL, 0);
/* Dynamic-topology detail size
- *
+ *
* This should be improved further, perhaps by showing a triangle
* grid rather than brush alpha */
kmi = WM_keymap_add_item(keymap, "SCULPT_OT_set_detail_size", DKEY, KM_PRESS, KM_SHIFT, 0);
@@ -1298,7 +1302,6 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
RNA_int_set(kmi->ptr, "level", -1);
RNA_boolean_set(kmi->ptr, "relative", true);
- ed_keymap_paint_brush_switch(keymap, "sculpt");
ed_keymap_paint_brush_size(keymap, "tool_settings.sculpt.brush.size");
ed_keymap_paint_brush_radial_control(keymap, "sculpt", RC_ROTATION);
@@ -1338,7 +1341,6 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap,
"PAINT_OT_vertex_color_set", KKEY, KM_PRESS, KM_SHIFT, 0);
- ed_keymap_paint_brush_switch(keymap, "vertex_paint");
ed_keymap_paint_brush_size(keymap, "tool_settings.vertex_paint.brush.size");
ed_keymap_paint_brush_radial_control(keymap, "vertex_paint", RC_COLOR | RC_COLOR_OVERRIDE | RC_ROTATION);
@@ -1371,7 +1373,6 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap,
"PAINT_OT_weight_set", KKEY, KM_PRESS, KM_SHIFT, 0);
- ed_keymap_paint_brush_switch(keymap, "weight_paint");
ed_keymap_paint_brush_size(keymap, "tool_settings.weight_paint.brush.size");
ed_keymap_paint_brush_radial_control(keymap, "weight_paint", RC_WEIGHT);
@@ -1412,7 +1413,6 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "PAINT_OT_grab_clone", RIGHTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "PAINT_OT_sample_color", SKEY, KM_PRESS, 0, 0);
- ed_keymap_paint_brush_switch(keymap, "image_paint");
ed_keymap_paint_brush_size(keymap, "tool_settings.image_paint.brush.size");
ed_keymap_paint_brush_radial_control(
keymap, "image_paint",
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 3ded6326c67..ee888c71659 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -38,6 +38,8 @@
#include "BLI_rand.h"
#include "BLI_listbase.h"
+#include "PIL_time.h"
+
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
@@ -60,6 +62,7 @@
#include "BIF_glutil.h"
#include "GPU_immediate.h"
+#include "GPU_state.h"
#include "ED_screen.h"
#include "ED_view3d.h"
@@ -86,6 +89,7 @@ typedef struct PaintStroke {
void *mode_data;
void *stroke_cursor;
wmTimer *timer;
+ struct RNG *rng;
/* Cached values */
ViewContext vc;
@@ -126,7 +130,7 @@ typedef struct PaintStroke {
float zoom_2d;
int pen_flip;
-
+
/* line constraint */
bool constrain_line;
float constrained_pos[2];
@@ -146,8 +150,8 @@ static void paint_draw_smooth_cursor(bContext *C, int x, int y, void *customdata
PaintStroke *stroke = customdata;
if (stroke && brush) {
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
+ GPU_line_smooth(true);
+ GPU_blend(true);
ARegion *ar = stroke->vc.ar;
@@ -165,8 +169,8 @@ static void paint_draw_smooth_cursor(bContext *C, int x, int y, void *customdata
immUnbindProgram();
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
+ GPU_blend(false);
+ GPU_line_smooth(false);
}
}
@@ -175,14 +179,14 @@ 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;
- glEnable(GL_LINE_SMOOTH);
+ GPU_line_smooth(true);
uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
immUniform1i("num_colors", 2); /* "advanced" mode */
@@ -215,7 +219,7 @@ static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
immUnbindProgram();
- glDisable(GL_LINE_SMOOTH);
+ GPU_line_smooth(false);
}
static bool paint_tool_require_location(Brush *brush, ePaintMode mode)
@@ -403,17 +407,24 @@ static bool paint_brush_update(bContext *C,
}
}
+ 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)GET_INT_FROM_POINTER(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_frand();
+ 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_frand();
+ brush->mask_mtex.random_angle * BLI_rng_get_float(stroke->rng);
}
}
@@ -735,10 +746,10 @@ PaintStroke *paint_stroke_new(bContext *C,
/* 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)
@@ -785,6 +796,10 @@ static void stroke_done(struct bContext *C, struct wmOperator *op)
stroke->timer);
}
+ if (stroke->rng) {
+ BLI_rng_free(stroke->rng);
+ }
+
if (stroke->stroke_cursor)
WM_paint_cursor_end(CTX_wm_manager(C), stroke->stroke_cursor);
@@ -928,11 +943,11 @@ static void paint_stroke_sample_average(const PaintStroke *stroke,
PaintSample *average)
{
int i;
-
+
memset(average, 0, sizeof(*average));
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;
@@ -1096,17 +1111,17 @@ 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;
@@ -1114,7 +1129,7 @@ static void paint_stroke_line_constrain(PaintStroke *stroke, float mouse[2])
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];
}
@@ -1209,12 +1224,12 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
else if (br->flag & BRUSH_LINE) {
if (event->alt)
stroke->constrain_line = true;
- else
+ 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);
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index f8888ad9809..d6de9c235f1 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -50,19 +50,22 @@
#include "BKE_brush.h"
#include "BKE_context.h"
-#include "BKE_DerivedMesh.h"
+#include "BKE_customdata.h"
#include "BKE_image.h"
#include "BKE_material.h"
+#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_report.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "GPU_glew.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
@@ -219,10 +222,10 @@ void paint_stroke_operator_properties(wmOperatorType *ot)
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,
+ RNA_def_enum(ot->srna, "mode", stroke_mode_items, BRUSH_STROKE_NORMAL,
"Stroke Mode",
"Action taken when a paint stroke is made");
-
+
}
/* 3D Paint */
@@ -274,26 +277,26 @@ static void imapaint_tri_weights(float matrix[4][4], GLint view[4],
}
/* compute uv coordinates of mouse in face */
-static void imapaint_pick_uv(Depsgraph *depsgraph, Scene *scene, Object *ob, 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])
{
- DerivedMesh *dm = mesh_get_derived_final(depsgraph, scene, ob, CD_MASK_BAREMESH);
- const int tottri = dm->getNumLoopTri(dm);
+ const int tottri = me_eval->runtime.looptris.len;
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 = dm->getLoopTriArray(dm);
- const MPoly *mpoly = dm->getPolyArray(dm);
- const MLoop *mloop = dm->getLoopArray(dm);
- const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
+ const MLoopTri *lt = me_eval->runtime.looptris.array;
+ 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 */
- glGetIntegerv(GL_VIEWPORT, view);
+ GPU_viewport_size_geti(view);
gpuGetModelViewMatrix(matrix);
gpuGetProjectionMatrix(proj);
view[0] = view[1] = 0;
- mul_m4_m4m4(matrix, matrix, ob->obmat);
+ mul_m4_m4m4(matrix, matrix, ob_eval->obmat);
mul_m4_m4m4(matrix, proj, matrix);
minabsw = 1e10;
@@ -310,25 +313,25 @@ static void imapaint_pick_uv(Depsgraph *depsgraph, Scene *scene, Object *ob, uns
const MLoopUV *tri_uv[3];
float tri_co[3][3];
- dm->getVertCo(dm, mloop[lt->tri[0]].v, tri_co[0]);
- dm->getVertCo(dm, mloop[lt->tri[1]].v, tri_co[1]);
- dm->getVertCo(dm, mloop[lt->tri[2]].v, tri_co[2]);
+ 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 = dm->mat[mp->mat_nr];
+ ma = give_current_material(ob_eval, mp->mat_nr);
slot = &ma->texpaintslot[ma->paint_active_slot];
if (!(slot && slot->uvname &&
- (mloopuv = CustomData_get_layer_named(&dm->loopData, CD_MLOOPUV, slot->uvname))))
+ (mloopuv = CustomData_get_layer_named(&me_eval->ldata, CD_MLOOPUV, slot->uvname))))
{
- mloopuv = CustomData_get_layer(&dm->loopData, CD_MLOOPUV);
+ mloopuv = CustomData_get_layer(&me_eval->ldata, CD_MLOOPUV);
}
}
else {
- mloopuv = CustomData_get_layer(&dm->loopData, CD_MLOOPUV);
+ mloopuv = CustomData_get_layer(&me_eval->ldata, CD_MLOOPUV);
}
tri_uv[0] = &mloopuv[lt->tri[0]];
@@ -347,8 +350,6 @@ static void imapaint_pick_uv(Depsgraph *depsgraph, Scene *scene, Object *ob, uns
}
}
}
-
- dm->release(dm);
}
/* returns 0 if not found, otherwise 1 */
@@ -436,7 +437,7 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr
CLAMP(x, 0, ar->winx);
CLAMP(y, 0, ar->winy);
-
+
if (use_palette) {
if (!palette) {
palette = BKE_palette_add(CTX_data_main(C), "Palette");
@@ -452,49 +453,50 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr
/* 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) {
Mesh *me = (Mesh *)ob->data;
- DerivedMesh *dm = mesh_get_derived_final(depsgraph, scene, ob, CD_MASK_BAREMESH);
+ Mesh *me_eval = BKE_object_get_evaluated_mesh(depsgraph, ob); /* Or shall we just do ob_eval->mesh_eval ? */
ViewContext vc;
const int mval[2] = {x, y};
unsigned int faceindex;
unsigned int totpoly = me->totpoly;
- if (dm->getLoopDataArray(dm, CD_MLOOPUV)) {
+ 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, me, faceindex);
+
+ 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(depsgraph, scene, ob, faceindex, mval, uv);
+ 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);
@@ -520,12 +522,11 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr
}
}
}
-
+
BKE_image_release_ibuf(image, ibuf, NULL);
}
}
}
- dm->release(dm);
}
if (!sample_success) {
@@ -542,7 +543,7 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr
glReadBuffer(GL_BACK);
}
cp = (unsigned char *)&col;
-
+
if (use_palette) {
rgb_uchar_to_float(color->rgb, cp);
}
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 196505c9542..47bcbdb4a08 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -55,10 +55,10 @@
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_deform.h"
-#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
+#include "BKE_object.h"
#include "BKE_object_deform.h"
#include "BKE_paint.h"
#include "BKE_report.h"
@@ -69,6 +69,7 @@
#include "WM_api.h"
#include "WM_types.h"
#include "WM_message.h"
+#include "WM_toolsystem.h"
#include "ED_object.h"
#include "ED_mesh.h"
@@ -966,15 +967,20 @@ static void do_weight_paint_vertex(
/* 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)
+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);
- if (ob->sculpt == NULL) {
- ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session");
- BKE_sculpt_update_mesh_elements(depsgraph, scene, scene->toolsettings->sculpt, ob, 0, 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);
}
static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob)
@@ -985,12 +991,12 @@ static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob)
if (ob->mode == OB_MODE_VERTEX_PAINT) {
gmap = &ob->sculpt->mode.vpaint.gmap;
brush = BKE_paint_brush(&ts->vpaint->paint);
- ob->sculpt->mode_type = OB_MODE_VERTEX_PAINT;
+ BLI_assert(ob->sculpt->mode_type == OB_MODE_VERTEX_PAINT);
}
else if (ob->mode == OB_MODE_WEIGHT_PAINT) {
gmap = &ob->sculpt->mode.wpaint.gmap;
brush = BKE_paint_brush(&ts->wpaint->paint);
- ob->sculpt->mode_type = OB_MODE_WEIGHT_PAINT;
+ BLI_assert(ob->sculpt->mode_type == OB_MODE_WEIGHT_PAINT);
}
else {
ob->sculpt->mode_type = 0;
@@ -1060,12 +1066,18 @@ static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob)
* \{ */
static void ed_vwpaintmode_enter_generic(
- Depsgraph *depsgraph, wmWindowManager *wm, Scene *scene,
+ 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 = ePaintVertex;
ED_mesh_color_ensure(me, NULL);
@@ -1076,7 +1088,7 @@ static void ed_vwpaintmode_enter_generic(
Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
paint_cursor_start_explicit(paint, wm, vertex_paint_poll);
- BKE_paint_init(scene, paint_mode, PAINT_CURSOR_VERTEX_PAINT);
+ BKE_paint_init(bmain, scene, paint_mode, PAINT_CURSOR_VERTEX_PAINT);
}
else if (mode_flag == OB_MODE_WEIGHT_PAINT) {
const ePaintMode paint_mode = ePaintWeight;
@@ -1087,7 +1099,7 @@ static void ed_vwpaintmode_enter_generic(
Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
paint_cursor_start_explicit(paint, wm, weight_paint_poll);
- BKE_paint_init(scene, paint_mode, PAINT_CURSOR_WEIGHT_PAINT);
+ BKE_paint_init(bmain, scene, paint_mode, PAINT_CURSOR_WEIGHT_PAINT);
/* weight paint specific */
ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 's');
@@ -1106,39 +1118,44 @@ static void ed_vwpaintmode_enter_generic(
BKE_sculptsession_free(ob);
}
- vertex_paint_init_session(depsgraph, scene, ob);
+ vertex_paint_init_session(depsgraph, scene, ob, mode_flag);
+
+ /* Flush object mode. */
+ DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
}
void ED_object_vpaintmode_enter_ex(
- Depsgraph *depsgraph, wmWindowManager *wm,
+ Main *bmain, Depsgraph *depsgraph, wmWindowManager *wm,
Scene *scene, Object *ob)
{
ed_vwpaintmode_enter_generic(
- depsgraph, wm, scene, ob, OB_MODE_VERTEX_PAINT);
+ 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(depsgraph, wm, scene, ob);
+ ED_object_vpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
}
void ED_object_wpaintmode_enter_ex(
- Depsgraph *depsgraph, wmWindowManager *wm,
+ Main *bmain, Depsgraph *depsgraph, wmWindowManager *wm,
Scene *scene, Object *ob)
{
ed_vwpaintmode_enter_generic(
- depsgraph, wm, scene, ob, OB_MODE_WEIGHT_PAINT);
+ 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(depsgraph, wm, scene, ob);
+ ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
}
/** \} */
@@ -1187,6 +1204,12 @@ static void ed_vwpaintmode_exit_generic(
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, DEG_TAG_COPY_ON_WRITE);
}
void ED_object_vpaintmode_exit_ex(Object *ob)
@@ -1218,6 +1241,7 @@ 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;
@@ -1238,7 +1262,7 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
else {
Depsgraph *depsgraph = CTX_data_depsgraph_on_load(C);
wmWindowManager *wm = CTX_wm_manager(C);
- ED_object_wpaintmode_enter_ex(depsgraph, wm, scene, ob);
+ ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
}
/* Weightpaint works by overriding colors in mesh,
@@ -1252,6 +1276,8 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
+ WM_toolsystem_update_from_context_view3d(C);
+
return OPERATOR_FINISHED;
}
@@ -1535,7 +1561,7 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo
}
/* If not previously created, create vertex/weight paint mode session data */
- vertex_paint_init_session(depsgraph, scene, ob);
+ vertex_paint_init_stroke(depsgraph, scene, ob);
vwpaint_update_cache_invariants(C, vp, ss, op, mouse);
vertex_paint_init_session_data(ts, ob);
@@ -2353,6 +2379,7 @@ 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;
@@ -2374,7 +2401,7 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
else {
Depsgraph *depsgraph = CTX_data_depsgraph_on_load(C);
wmWindowManager *wm = CTX_wm_manager(C);
- ED_object_vpaintmode_enter_ex(depsgraph, wm, scene, ob);
+ ED_object_vpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
}
BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
@@ -2386,6 +2413,8 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
+ WM_toolsystem_update_from_context_view3d(C);
+
return OPERATOR_FINISHED;
}
@@ -2521,7 +2550,7 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f
}
/* If not previously created, create vertex/weight paint mode session data */
- vertex_paint_init_session(depsgraph, scene, ob);
+ vertex_paint_init_stroke(depsgraph, scene, ob);
vwpaint_update_cache_invariants(C, vp, ss, op, mouse);
vertex_paint_init_session_data(ts, ob);
@@ -2597,7 +2626,7 @@ static float tex_color_alpha_ubyte(
}
static void do_vpaint_brush_draw_task_cb_ex(
- void *__restrict userdata,
+ void *__restrict userdata,
const int n,
const ParallelRangeTLS *__restrict UNUSED(tls))
{
@@ -3132,6 +3161,10 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
* avoid this if we can! */
DEG_id_tag_update(ob->data, 0);
}
+ else {
+ /* Flush changes through DEG. */
+ DEG_id_tag_update(ob->data, DEG_TAG_COPY_ON_WRITE);
+ }
}
static void vpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
@@ -3225,4 +3258,3 @@ void PAINT_OT_vertex_paint(wmOperatorType *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 d7668a48139..8516d92214d 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
@@ -152,6 +152,7 @@ static bool vertex_paint_from_weight(Object *ob)
}
/* 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++) {
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_proj.c b/source/blender/editors/sculpt_paint/paint_vertex_proj.c
index c5c9aa48760..602bfe1ab8e 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_proj.c
@@ -28,7 +28,7 @@
* \ingroup edsculpt
*
* Utility functions for getting vertex locations while painting
- * (since they may be instanced multiple times in a DerivedMesh)
+ * (since they may be instanced multiple times in an evaluated mesh)
*/
#include "MEM_guardedalloc.h"
@@ -39,8 +39,10 @@
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
-#include "BKE_DerivedMesh.h"
+#include "BKE_DerivedMesh.h" /* XXX To be removed, only used for DMCoNo struct */
#include "BKE_context.h"
+#include "BKE_mesh_iterators.h"
+#include "BKE_mesh_runtime.h"
#include "DEG_depsgraph.h"
@@ -106,24 +108,10 @@ static void vpaint_proj_dm_map_cosnos_init(
struct VertProjHandle *vp_handle)
{
Mesh *me = ob->data;
- DerivedMesh *dm;
+ Mesh *me_eval = mesh_get_eval_final(depsgraph, scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX);
- dm = mesh_get_derived_final(depsgraph, scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX);
-
- if (dm->foreachMappedVert) {
- memset(vp_handle->vcosnos, 0, sizeof(DMCoNo) * me->totvert);
- dm->foreachMappedVert(dm, vpaint_proj_dm_map_cosnos_init__map_cb, vp_handle, DM_FOREACH_USE_NORMAL);
- }
- else {
- DMCoNo *v_co_no = vp_handle->vcosnos;
- int a;
- for (a = 0; a < me->totvert; a++, v_co_no++) {
- dm->getVertCo(dm, a, v_co_no->co);
- dm->getVertNo(dm, a, v_co_no->no);
- }
- }
-
- dm->release(dm);
+ 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);
}
@@ -184,21 +172,13 @@ static void vpaint_proj_dm_map_cosnos_update(
Scene *scene = vp_handle->scene;
Object *ob = vp_handle->ob;
Mesh *me = ob->data;
- DerivedMesh *dm;
+ Mesh *me_eval = mesh_get_eval_final(depsgraph, scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX);
/* quick sanity check - we shouldn't have to run this if there are no modifiers */
BLI_assert(BLI_listbase_is_empty(&ob->modifiers) == false);
- dm = mesh_get_derived_final(depsgraph, scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX);
-
- /* highly unlikely this will become unavailable once painting starts (perhaps with animated modifiers) */
- if (LIKELY(dm->foreachMappedVert)) {
- copy_vn_fl(vp_handle->dists_sq, me->totvert, FLT_MAX);
-
- dm->foreachMappedVert(dm, vpaint_proj_dm_map_cosnos_update__map_cb, &vp_update, DM_FOREACH_USE_NORMAL);
- }
-
- dm->release(dm);
+ 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);
}
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 e560a4cddff..126b3b42e8f 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
@@ -35,8 +35,8 @@
#include "IMB_imbuf_types.h"
#include "IMB_colormanagement.h"
-//#include "DNA_armature_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
#include "DNA_particle_types.h"
#include "DNA_brush_types.h"
#include "DNA_object_types.h"
@@ -46,12 +46,13 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_mesh.h"
+#include "BKE_mesh_iterators.h"
#include "BKE_mesh_mapping.h"
+#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
#include "BKE_object_deform.h"
#include "BKE_paint.h"
@@ -533,21 +534,21 @@ void PAINT_OT_weight_set(wmOperatorType *ot)
* \{ */
/* *** VGroups Gradient *** */
-typedef struct DMGradient_vertStore {
+typedef struct WPGradient_vertStore {
float sco[2];
float weight_orig;
enum {
VGRAD_STORE_NOP = 0,
VGRAD_STORE_DW_EXIST = (1 << 0)
} flag;
-} DMGradient_vertStore;
+} WPGradient_vertStore;
-typedef struct DMGradient_vertStoreBase {
+typedef struct WPGradient_vertStoreBase {
struct WPaintPrev wpp;
- DMGradient_vertStore elem[0];
-} DMGradient_vertStoreBase;
+ WPGradient_vertStore elem[0];
+} WPGradient_vertStoreBase;
-typedef struct DMGradient_userData {
+typedef struct WPGradient_userData {
struct ARegion *ar;
Scene *scene;
Mesh *me;
@@ -557,7 +558,7 @@ typedef struct DMGradient_userData {
float sco_line_div; /* store (1.0f / len_v2v2(sco_start, sco_end)) */
int def_nr;
bool is_init;
- DMGradient_vertStoreBase *vert_cache;
+ WPGradient_vertStoreBase *vert_cache;
/* only for init */
BLI_bitmap *vert_visit;
@@ -565,12 +566,12 @@ typedef struct DMGradient_userData {
short use_select;
short type;
float weightpaint;
-} DMGradient_userData;
+} WPGradient_userData;
-static void gradientVert_update(DMGradient_userData *grad_data, int index)
+static void gradientVert_update(WPGradient_userData *grad_data, int index)
{
Mesh *me = grad_data->me;
- DMGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
+ WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
float alpha;
if (grad_data->type == WPAINT_GRADIENT_TYPE_LINEAR) {
@@ -618,10 +619,10 @@ 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]))
{
- DMGradient_userData *grad_data = userData;
+ WPGradient_userData *grad_data = userData;
Mesh *me = grad_data->me;
if ((grad_data->use_select == false) || (me->mvert[index].flag & SELECT)) {
- DMGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
+ WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
if (vs->sco[0] != FLT_MAX) {
gradientVert_update(grad_data, index);
}
@@ -632,7 +633,7 @@ static void gradientVertInit__mapFunc(
void *userData, int index, const float co[3],
const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
{
- DMGradient_userData *grad_data = userData;
+ WPGradient_userData *grad_data = userData;
Mesh *me = grad_data->me;
if ((grad_data->use_select == false) || (me->mvert[index].flag & SELECT)) {
@@ -641,7 +642,7 @@ static void gradientVertInit__mapFunc(
* updating the mesh may move them about (entering feedback loop) */
if (BLI_BITMAP_TEST(grad_data->vert_visit, index) == 0) {
- DMGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
+ WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
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)
@@ -674,7 +675,7 @@ static void gradientVertInit__mapFunc(
static int paint_weight_gradient_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
wmGesture *gesture = op->customdata;
- DMGradient_vertStoreBase *vert_cache = gesture->userdata;
+ WPGradient_vertStoreBase *vert_cache = gesture->userdata;
int ret = WM_gesture_straightline_modal(C, op, event);
if (ret & OPERATOR_RUNNING_MODAL) {
@@ -710,7 +711,7 @@ static int paint_weight_gradient_modal(bContext *C, wmOperator *op, const wmEven
static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
{
wmGesture *gesture = op->customdata;
- DMGradient_vertStoreBase *vert_cache;
+ WPGradient_vertStoreBase *vert_cache;
struct ARegion *ar = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
@@ -725,20 +726,18 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
Depsgraph *depsgraph = CTX_data_depsgraph(C);
- DerivedMesh *dm = mesh_get_derived_final(depsgraph, scene, ob, scene->customdata_mask);
-
- DMGradient_userData data = {NULL};
+ WPGradient_userData data = {NULL};
if (is_interactive) {
if (gesture->userdata == NULL) {
gesture->userdata = MEM_mallocN(
- sizeof(DMGradient_vertStoreBase) +
- (sizeof(DMGradient_vertStore) * me->totvert),
+ sizeof(WPGradient_vertStoreBase) +
+ (sizeof(WPGradient_vertStore) * me->totvert),
__func__);
gesture->userdata_free = false;
data.is_init = true;
- wpaint_prev_create(&((DMGradient_vertStoreBase *)gesture->userdata)->wpp, me->dvert, me->totvert);
+ 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) {
@@ -755,8 +754,8 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
data.is_init = true;
vert_cache = MEM_mallocN(
- sizeof(DMGradient_vertStoreBase) +
- (sizeof(DMGradient_vertStore) * me->totvert),
+ sizeof(WPGradient_vertStoreBase) +
+ (sizeof(WPGradient_vertStore) * me->totvert),
__func__);
}
@@ -785,16 +784,17 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
ED_view3d_init_mats_rv3d(ob, ar->regiondata);
+ Mesh *me_eval = mesh_get_eval_final(depsgraph, scene, ob, scene->customdata_mask | CD_MASK_ORIGINDEX);
if (data.is_init) {
data.vert_visit = BLI_BITMAP_NEW(me->totvert, __func__);
- dm->foreachMappedVert(dm, gradientVertInit__mapFunc, &data, DM_FOREACH_NOP);
+ BKE_mesh_foreach_mapped_vert(me_eval, gradientVertInit__mapFunc, &data, MESH_FOREACH_NOP);
MEM_freeN(data.vert_visit);
data.vert_visit = NULL;
}
else {
- dm->foreachMappedVert(dm, gradientVertUpdate__mapFunc, &data, DM_FOREACH_NOP);
+ BKE_mesh_foreach_mapped_vert(me_eval, gradientVertUpdate__mapFunc, &data, MESH_FOREACH_NOP);
}
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 048555d3fcc..88cb6f548e8 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -77,6 +77,7 @@
#include "WM_api.h"
#include "WM_types.h"
#include "WM_message.h"
+#include "WM_toolsystem.h"
#include "ED_sculpt.h"
#include "ED_object.h"
@@ -630,7 +631,7 @@ bool sculpt_brush_test_cube(SculptBrushTest *test, const float co[3], float loca
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));
@@ -729,7 +730,7 @@ static float calc_overlap(StrokeCache *cache, const char symm, const char axis,
{
float mirror[3];
float distsq;
-
+
/* flip_v3_v3(mirror, cache->traced_location, symm); */
flip_v3_v3(mirror, cache->true_location, symm);
@@ -1118,7 +1119,7 @@ static float brush_strength(
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) {
@@ -1151,7 +1152,7 @@ static float brush_strength(
}
else {
/* reduce strength for DEEPEN, PEAKS, and CONTRAST */
- return 0.5f * alpha * flip * pressure * overlap * feather;
+ return 0.5f * alpha * flip * pressure * overlap * feather;
}
case SCULPT_TOOL_SMOOTH:
@@ -1208,7 +1209,7 @@ float tex_strength(SculptSession *ss, const Brush *br,
avg = 1;
}
else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
- /* Get strength by feeding the vertex
+ /* 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);
}
@@ -1218,7 +1219,7 @@ float tex_strength(SculptSession *ss, const Brush *br,
/* 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
+ * 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);
@@ -1278,16 +1279,16 @@ bool sculpt_search_sphere_cb(PBVHNode *node, void *data_v)
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];
+ nearest[i] = center[i];
}
-
+
sub_v3_v3v3(t, center, nearest);
return len_squared_v3(t) < data->radius_squared;
@@ -1398,7 +1399,7 @@ static void update_sculpt_normal(Sculpt *sd, Object *ob,
{
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)))
@@ -2040,7 +2041,7 @@ static void do_mask_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
{
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);
@@ -2191,7 +2192,7 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
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);
@@ -4039,7 +4040,7 @@ static void do_symmetrical_brush_actions(
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 */
+ /* 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;
@@ -4174,14 +4175,14 @@ static void sculpt_init_mirror_clipping(Object *ob, SculptSession *ss)
(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])
@@ -4202,6 +4203,7 @@ static void sculpt_update_cache_invariants(
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);
@@ -4269,11 +4271,11 @@ static void sculpt_update_cache_invariants(
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(ID_BR, "Smooth");
+ br = (Brush *)BKE_libblock_find_name(bmain, ID_BR, "Smooth");
if (br) {
BKE_paint_brush_set(p, br);
brush = br;
@@ -4365,7 +4367,7 @@ static void sculpt_update_cache_invariants(
#define PIXEL_INPUT_THRESHHOLD 5
if (brush->sculpt_tool == SCULPT_TOOL_ROTATE)
cache->dial = BLI_dial_initialize(cache->initial_mouse, PIXEL_INPUT_THRESHHOLD);
-
+
#undef PIXEL_INPUT_THRESHHOLD
}
@@ -4806,7 +4808,7 @@ static void sculpt_brush_init_tex(const Scene *scene, Sculpt *sd, SculptSession
sculpt_update_tex(scene, sd, ss);
}
-static bool sculpt_brush_stroke_init(bContext *C, wmOperator *op)
+static void sculpt_brush_stroke_init(bContext *C, wmOperator *op)
{
Depsgraph *depsgraph = CTX_data_depsgraph(C);
Scene *scene = CTX_data_scene(C);
@@ -4827,8 +4829,6 @@ static bool sculpt_brush_stroke_init(bContext *C, wmOperator *op)
is_smooth = sculpt_any_smooth_mode(brush, NULL, mode);
BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, is_smooth, need_mask);
-
- return 1;
}
static void sculpt_restore_mesh(Sculpt *sd, Object *ob)
@@ -4947,7 +4947,7 @@ static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *UNUSED(st
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);
@@ -5011,6 +5011,7 @@ static void sculpt_brush_exit_tex(Sculpt *sd)
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;
@@ -5032,7 +5033,7 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
}
else {
BKE_brush_size_set(scene, brush, ss->cache->saved_smooth_size);
- brush = (Brush *)BKE_libblock_find_name(ID_BR, ss->cache->saved_active_brush_name);
+ brush = (Brush *)BKE_libblock_find_name(bmain, ID_BR, ss->cache->saved_active_brush_name);
if (brush) {
BKE_paint_brush_set(&sd->paint, brush);
}
@@ -5045,7 +5046,7 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
sculpt_undo_push_end();
BKE_pbvh_update(ss->pbvh, PBVH_UpdateOriginalBB, NULL);
-
+
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH)
BKE_pbvh_bmesh_after_stroke(ss->pbvh);
@@ -5072,8 +5073,7 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent
int ignore_background_click;
int retval;
- if (!sculpt_brush_stroke_init(C, op))
- return OPERATOR_CANCELLED;
+ sculpt_brush_stroke_init(C, op);
stroke = paint_stroke_new(C, op, sculpt_stroke_get_location,
sculpt_stroke_test_start,
@@ -5089,7 +5089,7 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent
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;
@@ -5099,14 +5099,13 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent
OPERATOR_RETVAL_CHECK(retval);
BLI_assert(retval == OPERATOR_RUNNING_MODAL);
-
+
return OPERATOR_RUNNING_MODAL;
}
static int sculpt_brush_stroke_exec(bContext *C, wmOperator *op)
{
- if (!sculpt_brush_stroke_init(C, op))
- return OPERATOR_CANCELLED;
+ 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);
@@ -5146,7 +5145,7 @@ static void SCULPT_OT_brush_stroke(wmOperatorType *ot)
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;
@@ -5163,7 +5162,7 @@ static void SCULPT_OT_brush_stroke(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "ignore_background_click", 0,
"Ignore Background Click",
- "Clicks on the background do not start the stroke");
+ "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) ****/
@@ -5187,11 +5186,11 @@ static void SCULPT_OT_set_persistent_base(wmOperatorType *ot)
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;
-
+
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -5207,14 +5206,12 @@ static void sculpt_dynamic_topology_triangulate(BMesh *bm)
void sculpt_pbvh_clear(Object *ob)
{
SculptSession *ss = ob->sculpt;
- DerivedMesh *dm = ob->derivedFinal;
/* Clear out any existing DM and PBVH */
- if (ss->pbvh)
+ if (ss->pbvh) {
BKE_pbvh_free(ss->pbvh);
+ }
ss->pbvh = NULL;
- if (dm)
- dm->getPBVH(NULL, dm);
BKE_object_free_derived_caches(ob);
}
@@ -5295,7 +5292,7 @@ void sculpt_dynamic_topology_enable_ex(
/* Enable dynamic topology */
me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
-
+
/* Enable logging for undo/redo */
ss->bm_log = BM_log_create(ss->bm);
@@ -5519,12 +5516,12 @@ static void SCULPT_OT_dynamic_topology_toggle(wmOperatorType *ot)
ot->name = "Dynamic Topology Toggle";
ot->idname = "SCULPT_OT_dynamic_topology_toggle";
ot->description = "Dynamic topology alters the mesh topology while sculpting";
-
+
/* api callbacks */
ot->invoke = sculpt_dynamic_topology_toggle_invoke;
ot->exec = sculpt_dynamic_topology_toggle_exec;
ot->poll = sculpt_mode_poll;
-
+
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -5557,11 +5554,11 @@ static void SCULPT_OT_optimize(wmOperatorType *ot)
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;
-
+
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -5611,7 +5608,7 @@ static void SCULPT_OT_symmetrize(wmOperatorType *ot)
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;
@@ -5626,7 +5623,7 @@ static void sculpt_init_session(Depsgraph *depsgraph, Scene *scene, Object *ob)
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, 0, false);
+ 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)
@@ -5640,7 +5637,7 @@ static int ed_object_sculptmode_flush_recalc_flag(Scene *scene, Object *ob, Mult
}
void ED_object_sculptmode_enter_ex(
- Depsgraph *depsgraph,
+ Main *bmain, Depsgraph *depsgraph,
Scene *scene, Object *ob,
ReportList *reports)
{
@@ -5662,6 +5659,11 @@ void ED_object_sculptmode_enter_ex(
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 */
@@ -5681,9 +5683,9 @@ void ED_object_sculptmode_enter_ex(
}
Paint *paint = BKE_paint_get_active_from_paintmode(scene, ePaintSculpt);
- BKE_paint_init(scene, ePaintSculpt, PAINT_CURSOR_SCULPT);
+ BKE_paint_init(bmain, scene, ePaintSculpt, PAINT_CURSOR_SCULPT);
- paint_cursor_start_explicit(paint, G.main->wm.first, sculpt_poll_view3d);
+ paint_cursor_start_explicit(paint, bmain->wm.first, sculpt_poll_view3d);
/* Check dynamic-topology flag; re-enter dynamic-topology mode when changing modes,
* As long as no data was added that is not supported. */
@@ -5731,15 +5733,19 @@ void ED_object_sculptmode_enter_ex(
}
}
- // ED_workspace_object_mode_sync_from_object(G.main->wm.first, workspace, ob);
+ // ED_workspace_object_mode_sync_from_object(bmain->wm.first, workspace, ob);
+
+ /* Flush object mode. */
+ DEG_id_tag_update(&ob->id, DEG_TAG_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);
Object *ob = CTX_data_active_object(C);
Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ED_object_sculptmode_enter_ex(depsgraph, scene, ob, reports);
+ ED_object_sculptmode_enter_ex(bmain, depsgraph, scene, ob, reports);
}
void ED_object_sculptmode_exit_ex(
@@ -5779,11 +5785,17 @@ void ED_object_sculptmode_exit_ex(
/* Leave sculptmode */
ob->mode &= ~mode_flag;
- // ED_workspace_object_mode_sync_from_object(G.main->wm.first, workspace, ob);
+ // ED_workspace_object_mode_sync_from_object(G_MAIN->wm.first, workspace, ob);
BKE_sculptsession_free(ob);
paint_cursor_delete_textures();
+
+ /* Never leave derived meshes behind. */
+ BKE_object_free_derived_caches(ob);
+
+ /* Flush object mode. */
+ DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
}
void ED_object_sculptmode_exit(bContext *C)
@@ -5797,6 +5809,7 @@ void ED_object_sculptmode_exit(bContext *C)
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);
Object *ob = CTX_data_active_object(C);
@@ -5813,13 +5826,15 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
ED_object_sculptmode_exit_ex(depsgraph, scene, ob);
}
else {
- ED_object_sculptmode_enter_ex(depsgraph, scene, ob, op->reports);
+ ED_object_sculptmode_enter_ex(bmain, depsgraph, scene, ob, op->reports);
}
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;
}
@@ -5829,11 +5844,11 @@ static void SCULPT_OT_sculptmode_toggle(wmOperatorType *ot)
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;
-
+
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -5955,8 +5970,7 @@ static int sculpt_sample_detail_size_exec(bContext *C, wmOperator *op)
static int sculpt_sample_detail_size_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(e))
{
- ScrArea *sa = CTX_wm_area(C);
- ED_area_headerprint(sa, "Click on the mesh to set the detail");
+ 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;
@@ -5967,14 +5981,13 @@ static int sculpt_sample_detail_size_modal(bContext *C, wmOperator *op, const wm
switch (e->type) {
case LEFTMOUSE:
if (e->val == KM_PRESS) {
- ScrArea *sa = CTX_wm_area(C);
int ss_co[2] = {e->mval[0], e->mval[1]};
sample_detail(C, ss_co);
RNA_int_set_array(op->ptr, "location", ss_co);
WM_cursor_modal_restore(CTX_wm_window(C));
- ED_area_headerprint(sa, NULL);
+ ED_workspace_status_text(C, NULL);
WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL);
return OPERATOR_FINISHED;
@@ -5983,9 +5996,8 @@ static int sculpt_sample_detail_size_modal(bContext *C, wmOperator *op, const wm
case RIGHTMOUSE:
{
- ScrArea *sa = CTX_wm_area(C);
WM_cursor_modal_restore(CTX_wm_window(C));
- ED_area_headerprint(sa, NULL);
+ ED_workspace_status_text(C, NULL);
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index bca33ad8014..ff6b5a6f374 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -28,7 +28,7 @@
/** \file blender/editors/sculpt_paint/sculpt_intern.h
* \ingroup edsculpt
*/
-
+
#ifndef __SCULPT_INTERN_H__
#define __SCULPT_INTERN_H__
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index b819fe8e97d..bc22147b15d 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -58,6 +58,7 @@
#include "BKE_paint.h"
#include "BKE_key.h"
#include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
#include "BKE_subsurf.h"
#include "BKE_undo_system.h"
@@ -144,7 +145,7 @@ static bool sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoN
SculptSession *ss = ob->sculpt;
MVert *mvert;
int *index;
-
+
if (unode->maxvert) {
/* regular mesh restore */
@@ -157,7 +158,7 @@ static bool sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoN
if (kb) {
ob->shapenr = BLI_findindex(&key->block, kb) + 1;
- BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, 0, false);
+ BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, false, false);
WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob);
}
else {
@@ -197,7 +198,7 @@ static bool sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoN
/* pbvh uses it's own mvert array, so coords should be */
/* propagated to pbvh here */
- BKE_pbvh_apply_vertCos(ss->pbvh, vertCos);
+ BKE_pbvh_apply_vertCos(ss->pbvh, vertCos, unode->totvert);
MEM_freeN(vertCos);
}
@@ -261,7 +262,7 @@ static bool sculpt_undo_restore_hidden(
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)) {
@@ -273,12 +274,12 @@ static bool sculpt_undo_restore_hidden(
}
else if (unode->maxgrid && dm->getGridData) {
BLI_bitmap **grid_hidden = dm->getGridHidden(dm);
-
+
for (i = 0; i < unode->totgrid; i++) {
SWAP(BLI_bitmap *,
unode->grid_hidden[i],
grid_hidden[unode->grids[i]]);
-
+
}
}
@@ -292,7 +293,7 @@ static bool sculpt_undo_restore_mask(bContext *C, DerivedMesh *dm, SculptUndoNod
MVert *mvert;
float *vmask;
int *index, i, j;
-
+
if (unode->maxvert) {
/* regular mesh restore */
@@ -492,7 +493,9 @@ static void sculpt_undo_restore_list(bContext *C, ListBase *lb)
}
}
- BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, 0, need_mask);
+ DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
+
+ BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, false, need_mask);
/* call _after_ sculpt_update_mesh_elements() which may update 'ob->derivedFinal' */
dm = mesh_get_derived_final(depsgraph, scene, ob, 0);
@@ -558,7 +561,7 @@ static void sculpt_undo_restore_list(bContext *C, ListBase *lb)
else {
BKE_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb, &rebuild);
}
- BKE_pbvh_update(ss->pbvh, PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw, NULL);
+ BKE_pbvh_update(ss->pbvh, PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw | PBVH_UpdateNormals, NULL);
if (BKE_sculpt_multires_active(scene, ob)) {
if (rebuild)
@@ -671,10 +674,10 @@ static void sculpt_undo_alloc_and_store_hidden(PBVH *pbvh,
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");
-
+
for (i = 0; i < totgrid; i++) {
if (grid_hidden[grid_indices[i]])
unode->grid_hidden[i] = MEM_dupallocN(grid_hidden[grid_indices[i]]);
@@ -691,7 +694,7 @@ static SculptUndoNode *sculpt_undo_alloc_node(
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;
@@ -706,7 +709,7 @@ static SculptUndoNode *sculpt_undo_alloc_node(
}
else
maxgrid = 0;
-
+
/* we will use this while sculpting, is mapalloc slow to access then? */
/* general TODO, fix count_alloc */
@@ -722,7 +725,7 @@ static SculptUndoNode *sculpt_undo_alloc_node(
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");
@@ -736,7 +739,7 @@ static SculptUndoNode *sculpt_undo_alloc_node(
BLI_assert(!"Dynamic topology should've already been handled");
break;
}
-
+
BLI_addtail(&usculpt->nodes, unode);
if (maxgrid) {
@@ -788,7 +791,7 @@ static void sculpt_undo_store_hidden(Object *ob, SculptUndoNode *unode)
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++) {
@@ -927,7 +930,7 @@ SculptUndoNode *sculpt_undo_push_node(
}
unode = sculpt_undo_alloc_node(ob, node, type);
-
+
BLI_thread_unlock(LOCK_CUSTOM1);
/* copy threaded, hopefully this is the performance critical part */
diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c
index 6928610f280..1405de8cfa9 100644
--- a/source/blender/editors/sculpt_paint/sculpt_uv.c
+++ b/source/blender/editors/sculpt_paint/sculpt_uv.c
@@ -43,12 +43,13 @@
#include "DNA_meshdata_types.h"
#include "BKE_brush.h"
-#include "BKE_paint.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
-#include "BKE_mesh_mapping.h"
#include "BKE_customdata.h"
#include "BKE_editmesh.h"
+#include "BKE_main.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_paint.h"
#include "DEG_depsgraph.h"
@@ -58,6 +59,7 @@
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
+#include "GPU_state.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -138,7 +140,7 @@ typedef struct UvSculptData {
/* uvsmooth Paint for fast reference */
Paint *uvsculpt;
-
+
/* tool to use. duplicating here to change if modifier keys are pressed */
char tool;
@@ -217,11 +219,11 @@ static void brush_drawcursor_uvsculpt(bContext *C, int x, int y, void *UNUSED(cu
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3fvAlpha(brush->add_col, alpha);
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
+ GPU_line_smooth(true);
+ GPU_blend(true);
imm_draw_circle_wire_2d(pos, (float)x, (float)y, size, 40);
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
+ GPU_blend(false);
+ GPU_line_smooth(false);
immUnbindProgram();
}
@@ -230,7 +232,7 @@ static void brush_drawcursor_uvsculpt(bContext *C, int x, int y, void *UNUSED(cu
}
-void ED_space_image_uv_sculpt_update(wmWindowManager *wm, Scene *scene)
+void ED_space_image_uv_sculpt_update(Main *bmain, wmWindowManager *wm, Scene *scene)
{
ToolSettings *settings = scene->toolsettings;
if (settings->use_uv_sculpt) {
@@ -243,7 +245,7 @@ void ED_space_image_uv_sculpt_update(wmWindowManager *wm, Scene *scene)
settings->uvsculpt->paint.flags |= PAINT_SHOW_BRUSH;
}
- BKE_paint_init(scene, ePaintSculptUV, PAINT_CURSOR_SCULPT);
+ BKE_paint_init(bmain, scene, ePaintSculptUV, PAINT_CURSOR_SCULPT);
settings->uvsculpt->paint.paint_cursor = WM_paint_cursor_activate(wm, uv_sculpt_brush_poll,
brush_drawcursor_uvsculpt, NULL);
diff --git a/source/blender/editors/sound/sound_intern.h b/source/blender/editors/sound/sound_intern.h
index ace173abdee..d95f473e4d9 100644
--- a/source/blender/editors/sound/sound_intern.h
+++ b/source/blender/editors/sound/sound_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -34,4 +34,3 @@
#endif /* __SOUND_INTERN_H__ */
-
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index eaf101b1083..049feea2d8a 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2007 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -375,7 +375,7 @@ static int sound_mixdown_exec(bContext *C, wmOperator *op)
specs.rate = scene->r.ffcodecdata.audio_mixrate;
BLI_strncpy(filename, path, sizeof(filename));
- BLI_path_abs(filename, bmain->name);
+ 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,
@@ -455,10 +455,10 @@ static bool sound_mixdown_check(bContext *UNUSED(C), wmOperator *op)
prop = RNA_struct_find_property(op->ptr, "filepath");
RNA_property_string_get(op->ptr, prop, filepath);
- if (BLI_testextensie_array(filepath, snd_ext_sound))
- check = BLI_replace_extension(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_ensure_extension(filepath, FILE_MAX, extension);
+ check = BLI_path_extension_ensure(filepath, FILE_MAX, extension);
if (!check)
return check;
diff --git a/source/blender/editors/space_action/action_buttons.c b/source/blender/editors/space_action/action_buttons.c
index 3ba59b3be75..55ad773f4df 100644
--- a/source/blender/editors/space_action/action_buttons.c
+++ b/source/blender/editors/space_action/action_buttons.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2016 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation, Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
@@ -75,9 +75,9 @@ 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"));
@@ -85,7 +85,7 @@ void action_buttons_register(ARegionType *UNUSED(art))
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"));
@@ -93,7 +93,7 @@ void action_buttons_register(ARegionType *UNUSED(art))
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"));
@@ -108,7 +108,7 @@ static int action_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = action_has_buttons_region(sa);
-
+
if (ar)
ED_region_toggle_hidden(C, ar);
@@ -117,10 +117,10 @@ static int action_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
void ACTION_OT_properties(wmOperatorType *ot)
{
- ot->name = "Properties";
+ 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;
diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c
index f1153b5bed0..74c9f2f8cfb 100644
--- a/source/blender/editors/space_action/action_data.c
+++ b/source/blender/editors/space_action/action_data.c
@@ -87,7 +87,7 @@ 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... */
@@ -101,7 +101,7 @@ AnimData *ED_actedit_animdata_from_context(bContext *C)
adt = key->adt;
}
}
-
+
return adt;
}
@@ -112,7 +112,7 @@ 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)
@@ -125,24 +125,24 @@ static bAction *action_create_new(bContext *C, bAction *oldact)
/* 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),
+
+ /* 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;
}
@@ -151,17 +151,17 @@ static void actedit_change_action(bContext *C, bAction *act)
{
bScreen *screen = CTX_wm_screen(C);
SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
-
+
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");
-
+
/* 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);
@@ -178,13 +178,13 @@ static void actedit_change_action(bContext *C, bAction *act)
static int 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... */
+ /* 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 */
@@ -206,7 +206,7 @@ static int action_new_poll(bContext *C)
return true;
}
}
-
+
/* something failed... */
return false;
}
@@ -215,18 +215,18 @@ 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;
@@ -234,7 +234,7 @@ static int action_new_exec(bContext *C, wmOperator *UNUSED(op))
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 */
@@ -255,10 +255,10 @@ static int action_new_exec(bContext *C, wmOperator *UNUSED(op))
//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
*/
@@ -266,24 +266,24 @@ static int action_new_exec(bContext *C, wmOperator *UNUSED(op))
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";
-
+
/* api callbacks */
ot->exec = action_new_exec;
ot->poll = action_new_poll;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -291,7 +291,7 @@ void ACTION_OT_new(wmOperatorType *ot)
/* ******************* Action Push-Down Operator ******************** */
/* Criteria:
- * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions
+ * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions
* 2) There must be an action active
* 3) The associated AnimData block must not be in tweakmode
*/
@@ -300,7 +300,7 @@ static int 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,
@@ -310,7 +310,7 @@ static int action_pushdown_poll(bContext *C)
return true;
}
}
-
+
/* something failed... */
return false;
}
@@ -319,7 +319,7 @@ 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
@@ -334,13 +334,13 @@ static int action_pushdown_exec(bContext *C, wmOperator *op)
/* 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;
@@ -352,11 +352,11 @@ void ACTION_OT_push_down(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -367,7 +367,7 @@ 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... */
@@ -390,12 +390,12 @@ static int action_stash_exec(bContext *C, wmOperator *op)
/* 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;
@@ -407,30 +407,30 @@ void ACTION_OT_stash(wmOperatorType *ot)
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",
+ 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");
}
/* ----------------- */
/* Criteria:
- * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions
+ * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions
* 2) The associated AnimData block must not be in tweakmode
*/
static int 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) {
@@ -439,19 +439,19 @@ static int action_stash_create_poll(bContext *C)
}
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
+ * (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;
}
@@ -460,7 +460,7 @@ 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 */
@@ -478,10 +478,10 @@ static int action_stash_create_exec(bContext *C, wmOperator *op)
/* 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
@@ -497,7 +497,7 @@ static int action_stash_create_exec(bContext *C, wmOperator *op)
}
}
}
-
+
/* Send notifiers that stuff has changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
return OPERATOR_FINISHED;
@@ -509,11 +509,11 @@ void ACTION_OT_stash_and_create(wmOperatorType *ot)
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;
}
@@ -533,7 +533,7 @@ void ACTION_OT_stash_and_create(wmOperatorType *ot)
void ED_animedit_unlink_action(bContext *C, ID *id, AnimData *adt, bAction *act, ReportList *reports, bool force_delete)
{
ScrArea *sa = CTX_wm_area(C);
-
+
/* If the old action only has a single user (that it's about to lose),
* warn user about it
*
@@ -545,7 +545,7 @@ void ED_animedit_unlink_action(bContext *C, ID *id, AnimData *adt, bAction *act,
"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 */
@@ -556,18 +556,18 @@ void ED_animedit_unlink_action(bContext *C, ID *id, AnimData *adt, bAction *act,
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);
-
+
if (nlt->strips.first == NULL) {
BLI_assert(nstrip == NULL);
BKE_nlatrack_free(&adt->nla_tracks, nlt);
@@ -577,18 +577,18 @@ void ED_animedit_unlink_action(bContext *C, ID *id, AnimData *adt, bAction *act,
}
}
}
-
+
/* Clear Fake User */
id_fake_user_clear(&act->id);
}
-
- /* If in Tweak Mode, don't unlink. Instead, this
+
+ /* 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);
@@ -604,11 +604,11 @@ void ED_animedit_unlink_action(bContext *C, ID *id, AnimData *adt, bAction *act,
/* 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);
@@ -623,12 +623,12 @@ static int 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);
-
+
/* Only when there's an active action, in the right modes... */
if (saction->action && adt)
return true;
}
-
+
/* something failed... */
return false;
}
@@ -637,11 +637,11 @@ 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");
-
+
if (adt && adt->action) {
ED_animedit_unlink_action(C, NULL, adt, adt->action, op->reports, force_delete);
}
-
+
return OPERATOR_FINISHED;
}
@@ -655,17 +655,17 @@ static int action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *evt)
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");
@@ -679,7 +679,7 @@ void ACTION_OT_unlink(wmOperatorType *ot)
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)) {
@@ -695,7 +695,7 @@ static NlaStrip *action_layer_get_nlastrip(ListBase *strips, float ctime)
return strip;
}
}
-
+
/* nothing suitable found... */
return NULL;
}
@@ -709,18 +709,18 @@ static void action_layer_switch_strip(AnimData *adt,
* 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) {
@@ -733,15 +733,15 @@ static void action_layer_switch_strip(AnimData *adt,
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);
@@ -762,7 +762,7 @@ static int action_layer_next_poll(bContext *C)
*/
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.
@@ -780,7 +780,7 @@ static int action_layer_next_poll(bContext *C)
}
}
}
-
+
/* something failed... */
return false;
}
@@ -789,26 +789,26 @@ 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;
@@ -820,7 +820,7 @@ static int action_layer_next_exec(bContext *C, wmOperator *op)
* NOTE: This will mean exiting tweakmode...
*/
BKE_nla_tweakmode_exit(adt);
-
+
/* Deal with solo flags...
* Assume: Solo Track == NLA Muting
*/
@@ -828,14 +828,14 @@ static int action_layer_next_exec(bContext *C, wmOperator *op)
/* 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
*/
@@ -849,11 +849,11 @@ void ACTION_OT_layer_next(wmOperatorType *ot)
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;
}
@@ -870,7 +870,7 @@ static int action_layer_prev_poll(bContext *C)
/* 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,
@@ -890,7 +890,7 @@ static int action_layer_prev_poll(bContext *C)
}
}
}
-
+
/* something failed... */
return false;
}
@@ -900,19 +900,19 @@ 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 */
@@ -922,17 +922,17 @@ static int action_layer_prev_exec(bContext *C, wmOperator *op)
/* 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
*/
@@ -946,11 +946,11 @@ void ACTION_OT_layer_prev(wmOperatorType *ot)
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 3e9b742480a..6105652a4c7 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -53,12 +53,13 @@
#include "BKE_pointcache.h"
-/* Everything from source (BIF, BDR, BSE) ------------------------------ */
+/* Everything from source (BIF, BDR, BSE) ------------------------------ */
#include "BIF_gl.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -73,41 +74,41 @@
/* Channel List */
/* left hand part */
-void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
+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)
+ /* 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) )
@@ -115,7 +116,7 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
/* 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++;
@@ -124,13 +125,13 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
{ /* 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) )
@@ -138,16 +139,16 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
/* draw all channels using standard channel-drawing API */
ANIM_channel_draw_widgets(C, ac, ale, block, yminc, ymaxc, 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);
}
@@ -163,50 +164,50 @@ 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 act_start, act_end, y;
-
+
unsigned char col1[3], col2[3];
unsigned char col1a[3], col2a[3];
unsigned char col1b[3], col2b[3];
-
+
const bool show_group_colors = !(saction->flag & SACTION_NODRAWGCOLORS);
-
-
+
+
/* get theme colors */
UI_GetThemeColor3ubv(TH_BACK, col2);
UI_GetThemeColor3ubv(TH_HILITE, col1);
-
+
UI_GetThemeColor3ubv(TH_GROUP, col2a);
UI_GetThemeColor3ubv(TH_GROUP_ACTIVE, col1a);
-
+
UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELOB, col1b);
UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELSUBOB, col2b);
-
+
/* set view-mapping rect (only used for x-axis), for NLA-scaling mapping with less calculation */
/* if in NLA there's a strip active, map the view */
if (ac->datatype == ANIMCONT_ACTION) {
/* adt = ANIM_nla_mapping_get(ac, NULL); */ /* UNUSED */
-
+
/* start and end of action itself */
calc_action_range(ac->data, &act_start, &act_end, 0);
}
-
+
/* 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)
+ /* 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));
@@ -215,19 +216,19 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- glEnable(GL_BLEND);
-
+ 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 */
@@ -287,10 +288,10 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
immUniformColor3ubvAlpha(sel ? col1 : col2, 0x22);
}
}
-
+
/* 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));
-
+
if (ac->datatype == ANIMCONT_ACTION)
immRectf(pos, act_start, (float)y - ACHANNEL_HEIGHT_HALF(ac), act_end, (float)y + ACHANNEL_HEIGHT_HALF(ac));
}
@@ -298,7 +299,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
/* frames less than one get less saturated background */
immUniformColor3ubvAlpha(sel ? col1 : col2, 0x22);
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(sel ? col1 : col2, 0x44);
immRectf(pos, v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF(ac));
@@ -315,11 +316,11 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
}
}
}
-
+
/* Increment the step */
y -= ACHANNEL_STEP(ac);
}
- glDisable(GL_BLEND);
+ GPU_blend(false);
/* black line marking 'current frame' for Time-Slide transform mode */
if (saction->flag & SACTION_MOVING) {
@@ -335,7 +336,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
/* 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
+ * 2) Keyframes which are out of view horizontally are disregarded
*/
y = (float)(-ACHANNEL_HEIGHT(ac));
@@ -397,7 +398,7 @@ void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene)
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;
@@ -436,9 +437,9 @@ void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene)
continue;
gpuPushMatrix();
- gpuTranslate2f(0.0, (float)V2D_SCROLL_HEIGHT + yoffs);
+ gpuTranslate2f(0.0, (float)V2D_SCROLL_HEIGHT_TEXT + yoffs);
gpuScale2f(1.0, cache_draw_height);
-
+
switch (pid->type) {
case PTCACHE_TYPE_SOFTBODY:
col[0] = 1.0; col[1] = 0.4; col[2] = 0.02;
@@ -475,7 +476,7 @@ void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene)
const int sta = pid->cache->startframe, end = pid->cache->endframe;
const int len = (end - sta + 1) * 6;
- glEnable(GL_BLEND);
+ GPU_blend(true);
immUniformColor4fv(col);
immRectf(pos, (float)sta, 0.0, (float)end, 1.0);
@@ -509,7 +510,7 @@ void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene)
immEnd();
}
- glDisable(GL_BLEND);
+ GPU_blend(false);
gpuPopMatrix();
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
index 1c15a7c5950..a9f9488d049 100644
--- a/source/blender/editors/space_action/action_edit.c
+++ b/source/blender/editors/space_action/action_edit.c
@@ -57,8 +57,9 @@
#include "BKE_fcurve.h"
#include "BKE_gpencil.h"
#include "BKE_global.h"
-#include "BKE_library.h"
#include "BKE_key.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
#include "BKE_nla.h"
#include "BKE_context.h"
#include "BKE_report.h"
@@ -95,56 +96,56 @@
static int act_markers_make_local_poll(bContext *C)
{
SpaceAction *sact = CTX_wm_space_action(C);
-
+
/* 1) */
if (sact == 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;
-
+
/* 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);
-
+
SpaceAction *sact = CTX_wm_space_action(C);
bAction *act = (sact) ? sact->action : NULL;
-
+
TimeMarker *marker, *markern = NULL;
-
+
/* sanity checks */
if (ELEM(NULL, markers, act))
return OPERATOR_CANCELLED;
-
+
/* 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);
}
}
-
+
/* 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);
-
+
return OPERATOR_FINISHED;
}
@@ -154,11 +155,11 @@ void ACTION_OT_markers_make_local(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -175,17 +176,17 @@ static bool get_keyframe_extents(bAnimContext *ac, float *min, float *max, const
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 */
@@ -268,7 +269,7 @@ 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;
@@ -276,7 +277,7 @@ static int actkeys_previewrange_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
else
scene = ac.scene;
-
+
/* set the range directly */
get_keyframe_extents(&ac, &min, &max, false);
scene->r.flag |= SCER_PRV_RANGE;
@@ -286,25 +287,25 @@ static int actkeys_previewrange_exec(bContext *C, wmOperator *UNUSED(op))
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";
-
+
/* api callbacks */
ot->exec = actkeys_previewrange_exec;
ot->poll = ED_operator_action_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -323,31 +324,31 @@ static bool actkeys_channels_get_selected_extents(bAnimContext *ac, float *min,
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
-
+
short found = 0; /* NOTE: not bool, since we want prioritise individual channels over expanders */
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) &&
+ 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
*/
@@ -355,14 +356,14 @@ static bool actkeys_channels_get_selected_extents(bAnimContext *ac, float *min,
break;
}
}
-
+
/* adjust y-position for next one */
y -= ACHANNEL_STEP(ac);
}
-
+
/* free all temp data */
ANIM_animdata_freelist(&anim_data);
-
+
return (found != 0);
}
@@ -372,25 +373,35 @@ static int actkeys_viewall(bContext *C, const bool only_sel)
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;
- v2d->cur.xmin = min;
- v2d->cur.xmax = max;
+ 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;
+ }
- 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... */
@@ -401,30 +412,30 @@ static int actkeys_viewall(bContext *C, const bool only_sel)
/* 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);
}
@@ -443,11 +454,11 @@ void ACTION_OT_view_all(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -458,11 +469,11 @@ void ACTION_OT_view_selected(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -473,7 +484,7 @@ 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);
-
+
return OPERATOR_FINISHED;
}
@@ -483,11 +494,11 @@ void ACTION_OT_view_frame(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -499,20 +510,20 @@ void ACTION_OT_view_frame(wmOperatorType *ot)
/* NOTE: the backend code for this is shared with the graph editor */
static short copy_action_keys(bAnimContext *ac)
-{
+{
ListBase anim_data = {NULL, NULL};
int filter, ok = 0;
-
+
/* 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);
-
+
/* copy keyframes */
ok = copy_animedit_keys(ac, &anim_data);
-
+
/* clean up */
ANIM_animdata_freelist(&anim_data);
@@ -522,21 +533,21 @@ static short copy_action_keys(bAnimContext *ac)
static short paste_action_keys(bAnimContext *ac,
const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode, bool flip)
-{
+{
ListBase anim_data = {NULL, NULL};
int filter, ok = 0;
-
- /* filter data
- * - First time we try to filter more strictly, allowing only selected channels
+
+ /* 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);
-
+
/* paste keyframes */
ok = paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode, flip);
@@ -551,7 +562,7 @@ static short paste_action_keys(bAnimContext *ac,
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;
@@ -574,17 +585,17 @@ static int actkeys_copy_exec(bContext *C, wmOperator *op)
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";
-
+
/* api callbacks */
ot->exec = actkeys_copy_exec;
ot->poll = ED_operator_action_active;
@@ -600,14 +611,14 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op)
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) {
@@ -629,10 +640,10 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op)
/* 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;
@@ -640,15 +651,15 @@ void ACTION_OT_paste(wmOperatorType *ot)
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");
@@ -667,39 +678,40 @@ static const EnumPropertyItem prop_actkeys_insertkey_types[] = {
};
/* this function is responsible for inserting new keyframes */
-static void insert_action_keys(bAnimContext *ac, short mode)
+static void insert_action_keys(bAnimContext *ac, short mode)
{
ListBase anim_data = {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) {
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
FCurve *fcu = (FCurve *)ale->key_data;
float cfra;
-
+
/* adjust current frame for NLA-scaling */
if (adt)
cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
- else
+ else
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,
@@ -707,16 +719,17 @@ static void insert_action_keys(bAnimContext *ac, short mode)
* (TODO: add the full-blown PointerRNA relative parsing case here...)
*/
if (ale->id && !ale->owner) {
- insert_keyframe(reports, ale->id, NULL, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, ts->keyframe_type, flag);
+ 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, flag);
}
else {
const float curval = evaluate_fcurve(fcu, cfra);
insert_vert_fcurve(fcu, cfra, curval, ts->keyframe_type, 0);
}
-
+
ale->update |= ANIM_UPDATE_DEFAULT;
}
-
+
ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
@@ -727,31 +740,31 @@ 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);
}
@@ -762,19 +775,19 @@ static int actkeys_insertkey_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
short mode;
-
+
/* 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;
}
-
+
/* what channels to affect? */
mode = RNA_enum_get(op->ptr, "type");
-
+
/* insert keyframes */
if (ac.datatype == ANIMCONT_GPENCIL) {
insert_gpencil_keys(&ac, mode);
@@ -785,7 +798,7 @@ static int actkeys_insertkey_exec(bContext *C, wmOperator *op)
/* set notifier that keyframes have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -795,15 +808,15 @@ void ACTION_OT_keyframe_insert(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* id-props */
ot->prop = RNA_def_enum(ot->srna, "type", prop_actkeys_insertkey_types, 0, "Type", "");
}
@@ -815,14 +828,14 @@ 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))
@@ -846,31 +859,31 @@ static void duplicate_action_keys(bAnimContext *ac)
static int actkeys_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
{
bAnimContext ac;
-
+
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
+
/* duplicate keyframes */
duplicate_action_keys(&ac);
/* set notifier that keyframes have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
-
+
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";
-
+
/* api callbacks */
ot->exec = actkeys_duplicate_exec;
ot->poll = ED_operator_action_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -904,26 +917,26 @@ static bool delete_action_keys(bAnimContext *ac)
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;
}
@@ -932,33 +945,33 @@ static bool delete_action_keys(bAnimContext *ac)
static int actkeys_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
bAnimContext ac;
-
+
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
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);
-
+
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;
}
@@ -966,15 +979,15 @@ void ACTION_OT_delete(wmOperatorType *ot)
/* ******************** Clean Keyframes Operator ************************* */
static void clean_action_keys(bAnimContext *ac, float thresh, bool clean_chan)
-{
+{
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 filtered data and clean curves */
for (ale = anim_data.first; ale; ale = ale->next) {
clean_fcurve(ac, ale, thresh, clean_chan);
@@ -993,44 +1006,44 @@ static int actkeys_clean_exec(bContext *C, wmOperator *op)
bAnimContext ac;
float thresh;
bool clean_chan;
-
+
/* 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;
}
-
+
/* 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);
-
+
/* set notifier that keyframes have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
-
+
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->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", "");
@@ -1040,15 +1053,15 @@ 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;
-
+
/* 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);
@@ -1065,36 +1078,36 @@ static void sample_action_keys(bAnimContext *ac)
static int actkeys_sample_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
-
+
/* 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;
}
-
+
/* sample keyframes */
sample_action_keys(&ac);
-
+
/* set notifier that keyframes have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
-
+
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";
-
+
/* api callbacks */
ot->exec = actkeys_sample_exec;
ot->poll = ED_operator_action_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1112,33 +1125,33 @@ void ACTION_OT_sample(wmOperatorType *ot)
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}
};
/* this function is responsible for setting extrapolation mode for keyframes */
-static void setexpo_action_keys(bAnimContext *ac, short mode)
+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
+ /* 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) {
@@ -1151,10 +1164,10 @@ static void setexpo_action_keys(bAnimContext *ac, short mode)
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);
}
@@ -1174,43 +1187,43 @@ static int actkeys_expo_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
short mode;
-
+
/* 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;
}
-
+
/* get handle setting mode */
mode = RNA_enum_get(op->ptr, "type");
-
+
/* 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);
-
+
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";
-
+
/* 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;
-
+
/* id-props */
ot->prop = RNA_def_enum(ot->srna, "type", prop_actkeys_expo_types, 0, "Type", "");
}
@@ -1218,17 +1231,17 @@ void ACTION_OT_extrapolation_type(wmOperatorType *ot)
/* ******************** Set Interpolation-Type Operator *********************** */
/* this function is responsible for setting interpolation mode for keyframes */
-static void setipo_action_keys(bAnimContext *ac, short mode)
+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...
*/
@@ -1248,43 +1261,43 @@ static int actkeys_ipo_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
short mode;
-
+
/* 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;
}
-
+
/* get handle setting mode */
mode = RNA_enum_get(op->ptr, "type");
-
+
/* 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);
-
+
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", "");
}
@@ -1292,25 +1305,25 @@ void ACTION_OT_interpolation_type(wmOperatorType *ot)
/* ******************** Set Handle-Type Operator *********************** */
/* this function is responsible for setting handle-type of selected keyframes */
-static void sethandles_action_keys(bAnimContext *ac, short mode)
+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
+
+ /* 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 */
@@ -1330,43 +1343,43 @@ static int actkeys_handletype_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
short mode;
-
+
/* 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;
}
-
+
/* get handle setting mode */
mode = RNA_enum_get(op->ptr, "type");
-
+
/* 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);
-
+
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";
-
+
/* 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;
-
+
/* id-props */
ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_keyframe_handle_type_items, 0, "Type", "");
}
@@ -1374,17 +1387,17 @@ void ACTION_OT_handle_type(wmOperatorType *ot)
/* ******************** Set Keyframe-Type Operator *********************** */
/* this function is responsible for setting keyframe type for keyframes */
-static void setkeytype_action_keys(bAnimContext *ac, short mode)
+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...
*/
@@ -1404,11 +1417,11 @@ 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) {
@@ -1427,19 +1440,19 @@ static int actkeys_keytype_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
short mode;
-
+
/* 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;
}
-
+
/* get handle setting mode */
mode = RNA_enum_get(op->ptr, "type");
-
+
/* set handle type */
if (ac.datatype == ANIMCONT_GPENCIL) {
setkeytype_gpencil_keys(&ac, mode);
@@ -1447,28 +1460,28 @@ static int actkeys_keytype_exec(bContext *C, wmOperator *op)
else {
setkeytype_action_keys(&ac, mode);
}
-
+
/* set notifier that keyframe properties have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
-
+
return OPERATOR_FINISHED;
}
-
+
void ACTION_OT_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";
-
+
/* 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;
-
+
/* id-props */
ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_beztriple_keyframe_type_items, 0, "Type", "");
}
@@ -1495,39 +1508,39 @@ static int actkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op))
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_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;
}
@@ -1537,11 +1550,11 @@ void ACTION_OT_frame_jump(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1562,22 +1575,22 @@ static const EnumPropertyItem prop_actkeys_snap_types[] = {
};
/* this function is responsible for snapping keyframes to frame-times */
-static void snap_action_keys(bAnimContext *ac, short mode)
+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);
@@ -1586,11 +1599,11 @@ static void snap_action_keys(bAnimContext *ac, short mode)
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);
}
@@ -1598,7 +1611,7 @@ static void snap_action_keys(bAnimContext *ac, short mode)
ED_masklayer_snap_frames(ale->data, ac->scene, mode);
}
else if (adt) {
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
+ 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);
}
@@ -1619,38 +1632,38 @@ static int actkeys_snap_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
short mode;
-
+
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
+
/* get snapping mode */
mode = RNA_enum_get(op->ptr, "type");
-
+
/* 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);
-
+
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";
-
+
/* 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;
-
+
/* id-props */
ot->prop = RNA_def_enum(ot->srna, "type", prop_actkeys_snap_types, 0, "Type", "");
}
@@ -1669,42 +1682,42 @@ static const EnumPropertyItem prop_actkeys_mirror_types[] = {
};
/* this function is responsible for mirroring keyframes */
-static void mirror_action_keys(bAnimContext *ac, short mode)
+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);
}
@@ -1712,14 +1725,14 @@ static void mirror_action_keys(bAnimContext *ac, short mode)
/* TODO */
}
else if (adt) {
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
+ 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;
}
@@ -1733,38 +1746,38 @@ static int actkeys_mirror_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
short mode;
-
+
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
+
/* get mirroring mode */
mode = RNA_enum_get(op->ptr, "type");
-
+
/* 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);
-
+
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";
-
+
/* 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;
-
+
/* 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 6ec6f0561c2..fc1f40cdb5a 100644
--- a/source/blender/editors/space_action/action_intern.h
+++ b/source/blender/editors/space_action/action_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -54,7 +54,7 @@ void ACTION_OT_properties(struct wmOperatorType *ot);
/* ***************************************** */
/* action_draw.c */
-void draw_channel_names(struct bContext *C, struct bAnimContext *ac, struct ARegion *ar);
+void draw_channel_names(struct bContext *C, struct bAnimContext *ac, struct ARegion *ar);
void draw_channel_strips(struct bAnimContext *ac, struct SpaceAction *saction, struct ARegion *ar);
void timeline_draw_cache(struct SpaceAction *saction, struct Object *ob, struct Scene *scene);
@@ -127,7 +127,7 @@ void ACTION_OT_layer_prev(struct wmOperatorType *ot);
void ACTION_OT_markers_make_local(struct wmOperatorType *ot);
-/* defines for snap keyframes
+/* defines for snap keyframes
* NOTE: keep in sync with eEditKeyframes_Snap (in ED_keyframes_edit.h)
*/
enum eActKeys_Snap_Mode {
@@ -137,7 +137,7 @@ enum eActKeys_Snap_Mode {
ACTKEYS_SNAP_NEAREST_MARKER,
};
-/* defines for mirror keyframes
+/* defines for mirror keyframes
* NOTE: keep in sync with eEditKeyframes_Mirror (in ED_keyframes_edit.h)
*/
enum eActKeys_Mirror_Mode {
@@ -146,11 +146,10 @@ enum eActKeys_Mirror_Mode {
ACTKEYS_MIRROR_XAXIS,
ACTKEYS_MIRROR_MARKER,
};
-
+
/* ***************************************** */
/* action_ops.c */
void action_operatortypes(void);
void action_keymap(struct wmKeyConfig *keyconf);
#endif /* __ACTION_INTERN_H__ */
-
diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c
index 718a4fd3c38..d32ab8f1db8 100644
--- a/source/blender/editors/space_action/action_ops.c
+++ b/source/blender/editors/space_action/action_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -53,7 +53,7 @@ void action_operatortypes(void)
{
/* view */
WM_operatortype_append(ACTION_OT_properties);
-
+
/* keyframes */
/* selection */
WM_operatortype_append(ACTION_OT_clickselect);
@@ -66,7 +66,7 @@ void action_operatortypes(void)
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);
@@ -82,17 +82,17 @@ void action_operatortypes(void)
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);
@@ -105,7 +105,7 @@ 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);
@@ -120,7 +120,7 @@ void ED_operatormacros_action(void)
static void action_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
{
wmKeyMapItem *kmi;
-
+
/* action_select.c - selection tools */
/* click-select: keyframe (replace) */
kmi = WM_keymap_add_item(keymap, "ACTION_OT_clickselect", SELECTMOUSE, KM_PRESS, 0, 0);
@@ -152,7 +152,7 @@ static void action_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
RNA_boolean_set(kmi->ptr, "extend", true);
RNA_boolean_set(kmi->ptr, "column", false);
RNA_boolean_set(kmi->ptr, "channel", true);
-
+
/* click-select: left/right */
kmi = WM_keymap_add_item(keymap, "ACTION_OT_select_leftright", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "extend", false);
@@ -160,71 +160,76 @@ static void action_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
kmi = WM_keymap_add_item(keymap, "ACTION_OT_select_leftright", SELECTMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "extend", true);
RNA_enum_set(kmi->ptr, "mode", ACTKEYS_LRSEL_TEST);
-
+
kmi = WM_keymap_add_item(keymap, "ACTION_OT_select_leftright", LEFTBRACKETKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "extend", false);
RNA_enum_set(kmi->ptr, "mode", ACTKEYS_LRSEL_LEFT);
kmi = WM_keymap_add_item(keymap, "ACTION_OT_select_leftright", RIGHTBRACKETKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "extend", false);
RNA_enum_set(kmi->ptr, "mode", ACTKEYS_LRSEL_RIGHT);
-
+
/* deselect all */
kmi = WM_keymap_add_item(keymap, "ACTION_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "invert", false);
kmi = WM_keymap_add_item(keymap, "ACTION_OT_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "invert", true);
-
+
/* borderselect */
kmi = WM_keymap_add_item(keymap, "ACTION_OT_select_border", BKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "axis_range", false);
kmi = WM_keymap_add_item(keymap, "ACTION_OT_select_border", BKEY, KM_PRESS, KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "axis_range", true);
-
+
/* region select */
kmi = WM_keymap_add_item(keymap, "ACTION_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "deselect", false);
kmi = WM_keymap_add_item(keymap, "ACTION_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "deselect", true);
-
+
WM_keymap_add_item(keymap, "ACTION_OT_select_circle", CKEY, KM_PRESS, 0, 0);
-
+
/* column select */
RNA_enum_set(WM_keymap_add_item(keymap, "ACTION_OT_select_column", KKEY, KM_PRESS, 0, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_KEYS);
RNA_enum_set(WM_keymap_add_item(keymap, "ACTION_OT_select_column", KKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_CFRA);
RNA_enum_set(WM_keymap_add_item(keymap, "ACTION_OT_select_column", KKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_MARKERS_COLUMN);
RNA_enum_set(WM_keymap_add_item(keymap, "ACTION_OT_select_column", KKEY, KM_PRESS, KM_ALT, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_MARKERS_BETWEEN);
-
+
/* select more/less */
WM_keymap_add_item(keymap, "ACTION_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "ACTION_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
-
+
/* select linked */
WM_keymap_add_item(keymap, "ACTION_OT_select_linked", LKEY, KM_PRESS, 0, 0);
-
-
+
+
/* action_edit.c */
/* jump to selected keyframes */
WM_keymap_add_item(keymap, "ACTION_OT_frame_jump", GKEY, KM_PRESS, KM_CTRL, 0);
-
+
/* menu + single-step transform */
WM_keymap_add_item(keymap, "ACTION_OT_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "ACTION_OT_mirror", MKEY, KM_PRESS, KM_SHIFT, 0);
-
+
/* menu + set setting */
WM_keymap_add_item(keymap, "ACTION_OT_handle_type", VKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "ACTION_OT_interpolation_type", TKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "ACTION_OT_extrapolation_type", EKEY, KM_PRESS, KM_SHIFT, 0);
- WM_keymap_add_item(keymap, "ACTION_OT_keyframe_type", RKEY, KM_PRESS, 0, 0);
-
+ WM_keymap_add_item(keymap, "ACTION_OT_extrapolation_type", EKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "ACTION_OT_keyframe_type", RKEY, KM_PRESS, 0, 0);
+
+ /* specials */
+ WM_keymap_add_menu(keymap, "DOPESHEET_MT_specials", WKEY, KM_PRESS, 0, 0);
+
/* destructive */
WM_keymap_add_item(keymap, "ACTION_OT_sample", OKEY, KM_PRESS, KM_SHIFT, 0);
-
+
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_menu(keymap, "DOPESHEET_MT_delete", XKEY, KM_PRESS, 0, 0);
+#endif
WM_keymap_add_menu(keymap, "DOPESHEET_MT_delete", DELKEY, KM_PRESS, 0, 0);
-
+
WM_keymap_add_item(keymap, "ACTION_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "ACTION_OT_keyframe_insert", IKEY, KM_PRESS, 0, 0);
-
+
/* copy/paste */
WM_keymap_add_item(keymap, "ACTION_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "ACTION_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0);
@@ -246,19 +251,19 @@ static void action_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
WM_keymap_add_item(keymap, "ACTION_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "ACTION_OT_view_frame", PAD0, KM_PRESS, 0, 0);
-
+
/* animation module */
/* channels list
* NOTE: these operators were originally for the channels list, but are added here too for convenience...
*/
WM_keymap_add_item(keymap, "ANIM_OT_channels_editable_toggle", TABKEY, KM_PRESS, 0, 0);
-
+
/* find (i.e. a shortcut for setting the name filter) */
WM_keymap_add_item(keymap, "ANIM_OT_channels_find", FKEY, KM_PRESS, KM_CTRL, 0);
-
+
/* transform system */
transform_keymap_for_space(keyconf, keymap, SPACE_ACTION);
-
+
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", OKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_proportional_action");
@@ -271,22 +276,21 @@ static void action_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
void action_keymap(wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
-
+
/* keymap for all regions */
keymap = WM_keymap_find(keyconf, "Dopesheet Generic", SPACE_ACTION, 0);
-
+
/* region management... */
WM_keymap_add_item(keymap, "ACTION_OT_properties", NKEY, KM_PRESS, 0, 0);
-
-
+
+
/* channels */
- /* Channels are not directly handled by the Action Editor module, but are inherited from the Animation module.
+ /* 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 */
keymap = WM_keymap_find(keyconf, "Dopesheet", SPACE_ACTION, 0);
action_keymap_keyframes(keyconf, keymap);
}
-
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index 2b974ac73d7..11145e29627 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -89,22 +89,22 @@ 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) {
@@ -128,10 +128,10 @@ static void deselect_action_keys(bAnimContext *ac, short test, short sel)
}
}
}
-
+
/* 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)
@@ -139,9 +139,9 @@ static void deselect_action_keys(bAnimContext *ac, short test, short sel)
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);
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL);
}
-
+
/* Cleanup */
ANIM_animdata_freelist(&anim_data);
}
@@ -151,37 +151,37 @@ static void deselect_action_keys(bAnimContext *ac, short test, short sel)
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 */
if (RNA_boolean_get(op->ptr, "invert"))
deselect_action_keys(&ac, 0, SELECT_INVERT);
else
deselect_action_keys(&ac, 1, SELECT_ADD);
-
+
/* 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_toggle(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Select All";
ot->idname = "ACTION_OT_select_all_toggle";
ot->description = "Toggle selection of all keyframes";
-
+
/* api callbacks */
ot->exec = actkeys_deselectall_exec;
ot->poll = ED_operator_action_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* props */
ot->prop = RNA_def_boolean(ot->srna, "invert", 0, "Invert", "");
RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
@@ -208,39 +208,39 @@ static void borderselect_action(bAnimContext *ac, const rcti rect, short mode, s
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 border 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 */
@@ -255,7 +255,7 @@ static void borderselect_action(bAnimContext *ac, const rcti rect, short mode, s
ked.f2 = rectf.xmax;
}
}
-
+
/* perform vertical suitability check (if applicable) */
if ((mode == ACTKEYS_BORDERSEL_FRAMERANGE) ||
!((ymax < rectf.ymin) || (ymin > rectf.ymax)))
@@ -293,11 +293,11 @@ static void borderselect_action(bAnimContext *ac, const rcti rect, short mode, s
break;
}
}
-
+
/* set minimum extent to be the maximum of the next channel */
ymax = ymin;
}
-
+
/* cleanup */
ANIM_animdata_freelist(&anim_data);
}
@@ -311,7 +311,7 @@ static int actkeys_borderselect_exec(bContext *C, wmOperator *op)
short mode = 0, 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;
@@ -320,7 +320,7 @@ static int actkeys_borderselect_exec(bContext *C, wmOperator *op)
if (!extend) {
deselect_action_keys(&ac, 1, SELECT_SUBTRACT);
}
-
+
/* get settings from operator */
WM_operator_properties_border_to_rcti(op, &rect);
@@ -330,10 +330,10 @@ static int actkeys_borderselect_exec(bContext *C, wmOperator *op)
else {
selectmode = SELECT_SUBTRACT;
}
-
+
/* selection 'mode' depends on whether borderselect 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
+ /* 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...
@@ -343,17 +343,17 @@ static int actkeys_borderselect_exec(bContext *C, wmOperator *op)
else
mode = ACTKEYS_BORDERSEL_CHANNELS;
}
- else
+ else
mode = ACTKEYS_BORDERSEL_ALLKEYS;
-
+
/* apply borderselect action */
borderselect_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_border(wmOperatorType *ot)
{
@@ -361,27 +361,27 @@ void ACTION_OT_select_border(wmOperatorType *ot)
ot->name = "Border Select";
ot->idname = "ACTION_OT_select_border";
ot->description = "Select all keyframes within the specified region";
-
+
/* api callbacks */
ot->invoke = WM_gesture_border_invoke;
ot->exec = actkeys_borderselect_exec;
ot->modal = WM_gesture_border_modal;
ot->cancel = WM_gesture_border_cancel;
-
+
ot->poll = ED_operator_action_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* rna */
WM_operator_properties_gesture_border_select(ot);
-
+
ot->prop = RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
}
/* ******************** Region Select Operators ***************************** */
/* "Region Select" operators include the Lasso and Circle Select operators.
- * These two ended up being lumped together, as it was easier in the
+ * These two ended up being lumped together, as it was easier in the
* original Graph Editor implementation of these to do it this way.
*/
@@ -390,24 +390,24 @@ static void region_select_action_keys(bAnimContext *ac, const rctf *rectf_view,
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) {
@@ -423,17 +423,17 @@ static void region_select_action_keys(bAnimContext *ac, const rctf *rectf_view,
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
@@ -450,16 +450,16 @@ static void region_select_action_keys(bAnimContext *ac, const rctf *rectf_view,
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
+ * 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)))
@@ -501,59 +501,59 @@ static void region_select_action_keys(bAnimContext *ac, const rctf *rectf_view,
break;
}
}
-
+
/* set minimum extent to be the maximum of the next channel */
ymax = ymin;
}
-
+
/* cleanup */
ANIM_animdata_freelist(&anim_data);
}
-
+
/* ----------------------------------- */
-
+
static int actkeys_lassoselect_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
-
+
KeyframeEdit_LassoData data_lasso;
rcti rect;
rctf rect_fl;
-
+
short selectmode;
bool extend;
-
+
/* 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;
-
+
/* clear all selection if not extending selection */
extend = RNA_boolean_get(op->ptr, "extend");
if (!extend)
deselect_action_keys(&ac, 1, SELECT_SUBTRACT);
-
+
if (!RNA_boolean_get(op->ptr, "deselect"))
selectmode = SELECT_ADD;
else
selectmode = SELECT_SUBTRACT;
-
+
/* get settings from operator */
BLI_lasso_boundbox(&rect, data_lasso.mcords, data_lasso.mcords_tot);
BLI_rctf_rcti_copy(&rect_fl, &rect);
-
+
/* apply borderselect action */
region_select_action_keys(&ac, &rect_fl, BEZT_OK_CHANNEL_LASSO, selectmode, &data_lasso);
-
+
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);
-
+
return OPERATOR_FINISHED;
}
@@ -563,17 +563,17 @@ void ACTION_OT_select_lasso(wmOperatorType *ot)
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_select(ot);
}
@@ -585,10 +585,10 @@ static int action_circle_select_exec(bContext *C, wmOperator *op)
bAnimContext ac;
const bool select = !RNA_boolean_get(op->ptr, "deselect");
const short selectmode = select ? SELECT_ADD : SELECT_SUBTRACT;
-
+
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");
@@ -596,23 +596,23 @@ static int action_circle_select_exec(bContext *C, wmOperator *op)
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
+
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;
-
+
/* 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);
-
+
return OPERATOR_FINISHED;
}
@@ -621,13 +621,13 @@ 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;
@@ -652,7 +652,7 @@ static const EnumPropertyItem prop_column_select_types[] = {
{0, NULL, 0, NULL, NULL}
};
-/* ------------------- */
+/* ------------------- */
/* Selects all visible keyframes between the specified markers */
/* TODO, this is almost an _exact_ duplicate of a function of the same name in graph_select.c
@@ -662,31 +662,31 @@ 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);
@@ -702,7 +702,7 @@ static void markers_selectkeys_between(bAnimContext *ac)
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
}
}
-
+
/* Cleanup */
ANIM_animdata_freelist(&anim_data);
}
@@ -714,52 +714,52 @@ 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
*/
@@ -768,10 +768,10 @@ static void columnselect_action_keys(bAnimContext *ac, short mode)
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
*/
@@ -781,7 +781,7 @@ static void columnselect_action_keys(bAnimContext *ac, short mode)
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);
@@ -791,7 +791,7 @@ static void columnselect_action_keys(bAnimContext *ac, short mode)
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
}
}
-
+
/* free elements */
BLI_freelistN(&ked.list);
ANIM_animdata_freelist(&anim_data);
@@ -803,39 +803,39 @@ static int actkeys_columnselect_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
short mode;
-
+
/* 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");
-
+
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);
-
+
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)";
-
+
/* api callbacks */
ot->exec = actkeys_columnselect_exec;
ot->poll = ED_operator_action_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* props */
ot->prop = RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", "");
}
@@ -845,38 +845,38 @@ void ACTION_OT_select_column(wmOperatorType *ot)
static int actkeys_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
{
bAnimContext ac;
-
+
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);
-
+
/* 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);
-
+
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);
}
}
-
+
/* 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);
-
+
return OPERATOR_FINISHED;
}
@@ -886,11 +886,11 @@ void ACTION_OT_select_linked(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -903,37 +903,37 @@ 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;
-
-
+
+
/* 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);
-
+
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;
-
+
/* 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);
-
+
/* free the selmap used here */
MEM_freeN(ked.data);
ked.data = NULL;
}
-
+
/* Cleanup */
ANIM_animdata_freelist(&anim_data);
}
@@ -943,17 +943,17 @@ static void select_moreless_action_keys(bAnimContext *ac, short mode)
static int actkeys_select_more_exec(bContext *C, wmOperator *UNUSED(op))
{
bAnimContext ac;
-
+
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
+
/* 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);
-
+
return OPERATOR_FINISHED;
}
@@ -963,11 +963,11 @@ void ACTION_OT_select_more(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -977,17 +977,17 @@ void ACTION_OT_select_more(wmOperatorType *ot)
static int actkeys_select_less_exec(bContext *C, wmOperator *UNUSED(op))
{
bAnimContext ac;
-
+
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
+
/* 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);
-
+
return OPERATOR_FINISHED;
}
@@ -997,11 +997,11 @@ void ACTION_OT_select_less(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1024,25 +1024,25 @@ static void actkeys_select_leftright(bAnimContext *ac, short leftright, short se
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);
@@ -1051,18 +1051,18 @@ static void actkeys_select_leftright(bAnimContext *ac, short leftright, short se
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);
@@ -1075,15 +1075,15 @@ static void actkeys_select_leftright(bAnimContext *ac, short leftright, short se
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)))
@@ -1108,28 +1108,28 @@ static int actkeys_select_leftright_exec(bContext *C, wmOperator *op)
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;
-
+
/* 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;
-
+
/* 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);
-
+
return OPERATOR_FINISHED;
}
@@ -1137,11 +1137,11 @@ static int actkeys_select_leftright_invoke(bContext *C, wmOperator *op, const wm
{
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;
@@ -1156,7 +1156,7 @@ static int actkeys_select_leftright_invoke(bContext *C, wmOperator *op, const wm
else
RNA_enum_set(op->ptr, "mode", ACTKEYS_LRSEL_RIGHT);
}
-
+
/* perform selection */
return actkeys_select_leftright_exec(C, op);
}
@@ -1164,24 +1164,24 @@ static int actkeys_select_leftright_invoke(bContext *C, wmOperator *op, const wm
void ACTION_OT_select_leftright(wmOperatorType *ot)
{
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";
-
+
/* 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;
-
+
/* 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);
}
@@ -1193,24 +1193,24 @@ void ACTION_OT_select_leftright(wmOperatorType *ot)
* - 3) column select all keyframes in frame under mouse - CTRL modifier
* - 4) all keyframes in channel under mouse - CTRL+ALT modifiers
*
- * In addition to these basic options, the SHIFT modifier can be used to toggle the
+ * In addition to these basic options, the SHIFT modifier can be used to toggle the
* selection mode between replacing the selection (without) and inverting the selection (with).
*/
/* ------------------- */
-
+
/* option 1) select keyframe directly under mouse */
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);
@@ -1224,10 +1224,10 @@ static void actkeys_mselect_single(bAnimContext *ac, bAnimListElem *ale, short s
{
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);
@@ -1236,7 +1236,7 @@ static void actkeys_mselect_single(bAnimContext *ac, bAnimListElem *ale, short s
ED_mask_select_frame(ale->data, selx, select_mode);
}
}
-
+
ANIM_animdata_freelist(&anim_data);
}
else {
@@ -1254,14 +1254,14 @@ static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float se
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
*/
@@ -1270,16 +1270,16 @@ static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float se
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);
@@ -1288,7 +1288,7 @@ static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float se
else
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
}
-
+
/* free elements */
BLI_freelistN(&ked.list);
ANIM_animdata_freelist(&anim_data);
@@ -1298,10 +1298,10 @@ static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float se
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);
@@ -1315,10 +1315,10 @@ static void actkeys_mselect_channel_only(bAnimContext *ac, bAnimListElem *ale, s
{
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);
@@ -1327,7 +1327,7 @@ static void actkeys_mselect_channel_only(bAnimContext *ac, bAnimListElem *ale, s
ED_mask_select_frames(ale->data, select_mode);
}
}
-
+
ANIM_animdata_freelist(&anim_data);
}
else {
@@ -1335,7 +1335,7 @@ static void actkeys_mselect_channel_only(bAnimContext *ac, bAnimListElem *ale, s
}
}
}
-
+
/* ------------------- */
static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_mode, bool column, bool same_channel)
@@ -1344,7 +1344,7 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
DLRBT_Tree anim_keys;
bAnimListElem *ale;
int filter;
-
+
View2D *v2d = &ac->ar->v2d;
bDopeSheet *ads = NULL;
int channel_index;
@@ -1354,28 +1354,28 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
float key_hsize;
float x, y;
rctf rectf;
-
+
/* get dopesheet info */
if (ac->datatype == ANIMCONT_DOPESHEET)
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)
*/
key_hsize = ACHANNEL_HEIGHT(ac) * 0.8f; /* standard channel height (to allow for some slop) */
key_hsize = roundf(key_hsize / 2.0f); /* half-size (for either side), but rounded up to nearest int (for easier targetting) */
-
+
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) {
@@ -1388,10 +1388,10 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
/* 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:
@@ -1443,7 +1443,7 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
/* 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
+ /* 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...
*/
@@ -1457,41 +1457,41 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
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);
-
+
/* 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)) {
/* 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);
}
@@ -1500,11 +1500,11 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
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);
}
@@ -1522,28 +1522,28 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
}
}
}
-
+
/* 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
+ /* 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
+ * 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);
+ 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);
}
}
-
+
/* free this channel */
MEM_freeN(ale);
}
@@ -1556,11 +1556,11 @@ static int actkeys_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent
/* ARegion *ar; */ /* UNUSED */
short selectmode;
bool column, channel;
-
+
/* 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 */
@@ -1569,48 +1569,48 @@ static int actkeys_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent
selectmode = SELECT_INVERT;
else
selectmode = SELECT_REPLACE;
-
+
/* 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);
-
+
/* 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;
}
-
+
void ACTION_OT_clickselect(wmOperatorType *ot)
{
PropertyRNA *prop;
-
+
/* identifiers */
- ot->name = "Mouse Select Keys";
+ 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",
+ 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",
+
+ 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",
+
+ 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 5353c250d1e..876b73a4a76 100644
--- a/source/blender/editors/space_action/space_action.c
+++ b/source/blender/editors/space_action/space_action.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -47,6 +47,8 @@
#include "BKE_screen.h"
#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -63,30 +65,31 @@
#include "ED_markers.h"
#include "action_intern.h" /* own include */
+#include "GPU_framebuffer.h"
/* ******************** manage regions ********************* */
ARegion *action_has_buttons_region(ScrArea *sa)
{
ARegion *ar, *arnew;
-
+
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);
-
+
/* is error! */
if (ar == NULL) return NULL;
-
+
arnew = MEM_callocN(sizeof(ARegion), "buttons for action");
-
+
BLI_insertlinkafter(&sa->regionbase, ar, arnew);
arnew->regiontype = RGN_TYPE_UI;
arnew->alignment = RGN_ALIGN_RIGHT;
-
+
arnew->flag = RGN_FLAG_HIDDEN;
-
+
return arnew;
}
@@ -96,62 +99,63 @@ static SpaceLink *action_new(const ScrArea *sa, const Scene *scene)
{
SpaceAction *saction;
ARegion *ar;
-
+
saction = MEM_callocN(sizeof(SpaceAction), "initaction");
saction->spacetype = SPACE_ACTION;
-
+
saction->autosnap = SACTSNAP_FRAME;
saction->mode = SACTCONT_DOPESHEET;
-
+ saction->mode_prev = SACTCONT_DOPESHEET;
+
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;
-
+
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for action");
-
+
BLI_addtail(&saction->regionbase, ar);
ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = RGN_ALIGN_BOTTOM;
-
+ ar->alignment = 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;
-
+
/* 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");
-
+
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");
-
+
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.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;
@@ -163,13 +167,13 @@ static SpaceLink *action_new(const ScrArea *sa, const Scene *scene)
ar->v2d.keepofs = V2D_KEEPOFS_Y;
ar->v2d.align = V2D_ALIGN_NO_POS_Y;
ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
-
+
return (SpaceLink *)saction;
}
/* not spacelink itself */
static void action_free(SpaceLink *UNUSED(sl))
-{
+{
// SpaceAction *saction = (SpaceAction *) sl;
}
@@ -178,16 +182,16 @@ static void action_free(SpaceLink *UNUSED(sl))
static void action_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
{
SpaceAction *saction = sa->spacedata.first;
-
+
saction->flag |= SACTION_TEMP_NEEDCHANSYNC;
}
static SpaceLink *action_duplicate(SpaceLink *sl)
{
SpaceAction *sactionn = MEM_dupallocN(sl);
-
+
/* clear or remove stuff from old */
-
+
return (SpaceLink *)sactionn;
}
@@ -197,9 +201,9 @@ static SpaceLink *action_duplicate(SpaceLink *sl)
static void action_main_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
-
+
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
-
+
/* own keymap */
keymap = WM_keymap_find(wm->defaultconf, "Dopesheet", SPACE_ACTION, 0);
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
@@ -220,44 +224,44 @@ static void action_main_region_draw(const bContext *C, ARegion *ar)
short marker_flag = 0;
short cfra_flag = 0;
short unit = 0;
-
+
/* clear and setup matrix */
UI_ThemeClearColor(TH_BACK);
- glClear(GL_COLOR_BUFFER_BIT);
-
+ 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;
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);
@@ -265,15 +269,15 @@ static void action_main_region_draw(const bContext *C, ARegion *ar)
/* callback */
UI_view2d_view_ortho(v2d);
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
-
+
/* reset view matrix */
UI_view2d_view_restore(C);
-
+
/* scrollers */
scrollers = UI_view2d_scrollers_calc(C, v2d, 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);
@@ -285,16 +289,18 @@ static void action_main_region_draw(const bContext *C, ARegion *ar)
static void action_channel_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
-
+
/* 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);
-
+
/* own keymap */
keymap = WM_keymap_find(wm->defaultconf, "Animation Channels", 0, 0);
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
-
+
+ WM_keymap_add_menu(keymap, "DOPESHEET_MT_specials_channels", WKEY, KM_PRESS, 0, 0);
+
keymap = WM_keymap_find(wm->defaultconf, "Dopesheet Generic", SPACE_ACTION, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
@@ -304,21 +310,21 @@ 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;
-
+
/* clear and setup matrix */
UI_ThemeClearColor(TH_BACK);
- glClear(GL_COLOR_BUFFER_BIT);
-
+ GPU_clear(GPU_COLOR_BIT);
+
UI_view2d_view_ortho(v2d);
-
+
/* data */
if (ANIM_animdata_get_context(C, &ac)) {
draw_channel_names((bContext *)C, &ac, ar);
}
-
+
/* reset view matrix */
UI_view2d_view_restore(C);
-
+
/* no scrollers here */
}
@@ -379,6 +385,52 @@ static void action_channel_region_listener(
}
}
+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__);
+ }
+ }
+}
+
static void action_main_region_listener(
bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
wmNotifier *wmn, const Scene *UNUSED(scene))
@@ -435,8 +487,8 @@ static void action_main_region_listener(
}
static void saction_main_region_message_subscribe(
- const struct bContext *UNUSED(C),
- struct WorkSpace *UNUSED(workspace), struct Scene *scene,
+ const struct bContext *C,
+ struct WorkSpace *workspace, struct Scene *scene,
struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar,
struct wmMsgBus *mbus)
{
@@ -472,6 +524,9 @@ static void saction_main_region_message_subscribe(
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 */
@@ -480,7 +535,7 @@ static void action_listener(
WorkSpace *UNUSED(workspace))
{
SpaceAction *saction = (SpaceAction *)sa->spacedata.first;
-
+
/* context changes */
switch (wmn->category) {
case NC_GPENCIL:
@@ -501,7 +556,7 @@ static void action_listener(
saction->flag |= SACTION_TEMP_NEEDCHANSYNC;
ED_area_tag_refresh(sa);
}
- /* autocolor only really needs to change when channels are added/removed, or previously hidden stuff appears
+ /* 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)) ||
@@ -509,7 +564,7 @@ static void action_listener(
{
ED_area_tag_refresh(sa);
}
- /* for simple edits to the curve data though (or just plain selections), a simple redraw should work
+ /* 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 {
@@ -549,7 +604,7 @@ static void action_listener(
saction->flag |= SACTION_TEMP_NEEDCHANSYNC;
ED_area_tag_refresh(sa);
break;
-
+
default: /* just redrawing the view will do */
ED_area_tag_redraw(sa);
break;
@@ -672,12 +727,12 @@ static void action_header_region_listener(
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
+ /* 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);
@@ -692,16 +747,16 @@ static void action_header_region_listener(
static void action_buttons_area_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
-
+
ED_region_panels_init(wm, ar);
-
+
keymap = WM_keymap_find(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, NULL, -1, true);
+ ED_region_panels(C, ar);
}
static void action_region_listener(
@@ -741,19 +796,19 @@ static void action_region_listener(
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
+
+ /* 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->flag & SACTION_TEMP_NEEDCHANSYNC) {
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->flag &= ~SACTION_TEMP_NEEDCHANSYNC;
-
+
/* Tag everything for redraw
* - Regions (such as header) need to be manually tagged for redraw too
* or else they don't update [#28962]
@@ -762,7 +817,7 @@ static void action_refresh(const bContext *C, ScrArea *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?
}
@@ -776,7 +831,7 @@ static void action_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, I
}
if ((ID *)sact->ads.filter_grp == old_id) {
- sact->ads.filter_grp = (Group *)new_id;
+ sact->ads.filter_grp = (Collection *)new_id;
}
if ((ID *)sact->ads.source == old_id) {
sact->ads.source = new_id;
@@ -784,15 +839,46 @@ static void action_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, I
}
+/**
+ * \note Used for splitting out a subset of modes is more involved,
+ * The previous non-timeline mode is stored so switching back to the
+ * dope-sheet doesn't always reset the sub-mode.
+ */
+static int action_space_subtype_get(ScrArea *sa)
+{
+ 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;
+ }
+}
+
+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);
+}
+
/* 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;
@@ -802,6 +888,9 @@ void ED_spacetype_action(void)
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");
@@ -813,31 +902,32 @@ void ED_spacetype_action(void)
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;
@@ -846,11 +936,10 @@ void ED_spacetype_action(void)
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/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index 12f16f1fe42..2ee791e81d6 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -79,7 +79,7 @@ void ED_spacetypes_init(void)
/* 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();
@@ -97,9 +97,10 @@ void ED_spacetypes_init(void)
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_workspace();
ED_operatortypes_scene();
@@ -122,10 +123,12 @@ void ED_spacetypes_init(void)
ED_operatortypes_render();
ED_operatortypes_mask();
ED_operatortypes_io();
-
+
ED_operatortypes_view2d();
ED_operatortypes_ui();
+ ED_screen_user_menu_register();
+
/* manipulator types */
ED_manipulatortypes_button_2d();
ED_manipulatortypes_dial_3d();
@@ -222,32 +225,32 @@ void ED_spacetypes_keymap(wmKeyConfig *keyconf)
typedef struct RegionDrawCB {
struct RegionDrawCB *next, *prev;
-
+
void (*draw)(const struct bContext *, struct ARegion *, void *);
void *customdata;
-
+
int type;
-
+
} RegionDrawCB;
-void *ED_region_draw_cb_activate(ARegionType *art,
+void *ED_region_draw_cb_activate(ARegionType *art,
void (*draw)(const struct bContext *, struct ARegion *, void *),
void *customdata, int type)
{
RegionDrawCB *rdc = MEM_callocN(sizeof(RegionDrawCB), "RegionDrawCB");
-
+
BLI_addtail(&art->drawcalls, rdc);
rdc->draw = draw;
rdc->customdata = customdata;
rdc->type = type;
-
+
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);
@@ -265,7 +268,7 @@ void *ED_region_draw_cb_customdata(void *handle)
void ED_region_draw_cb_draw(const bContext *C, ARegion *ar, int type)
{
RegionDrawCB *rdc;
-
+
for (rdc = ar->type->drawcalls.first; rdc; rdc = rdc->next) {
if (rdc->type == type) {
rdc->draw(C, ar, rdc->customdata);
@@ -294,17 +297,17 @@ 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 */
-
+
/* define how many regions, the order and types */
-
+
/* add types to regions */
}
static SpaceLink *xxx_duplicate(SpaceLink *UNUSED(sl))
{
-
+
return NULL;
}
@@ -322,16 +325,16 @@ static void xxx_keymap(wmKeyConfig *UNUSED(keyconf))
void ED_spacetype_xxx(void)
{
static SpaceType st;
-
+
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;
-
+
BKE_spacetype_register(&st);
}
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index 6793f0a0195..dd943e7988d 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -144,7 +144,7 @@ static int buttons_context_path_world(ButsContextPath *path)
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++;
@@ -191,40 +191,6 @@ static int buttons_context_path_workspace(ButsContextPath *path)
return RNA_struct_is_a(ptr->type, &RNA_WorkSpace);
}
-static int buttons_context_path_collection(ButsContextPath *path, eSpaceButtons_Collection_Context collection_context)
-{
- PointerRNA *ptr = &path->ptr[path->len - 1];
-
- /* if we already have a (pinned) Collection, we're done */
- if (RNA_struct_is_a(ptr->type, &RNA_LayerCollection)) {
- return 1;
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_ViewLayer)) {
- ViewLayer *view_layer = ptr->data;
-
- if (collection_context == SB_COLLECTION_CTX_GROUP) {
- Object *ob = OBACT(view_layer);
- if (ob && ob->dup_group) {
- view_layer = ob->dup_group->view_layer;
-
- /* Replace the view layer by the group in the context path. */
- RNA_pointer_create(NULL, &RNA_Group, ob->dup_group, &path->ptr[path->len - 1]);
- }
- }
-
- LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
-
- if (layer_collection) {
- RNA_pointer_create(NULL, &RNA_LayerCollection, layer_collection, &path->ptr[path->len]);
- path->len++;
- return 1;
- }
- }
-
- /* no path to a collection possible */
- return 0;
-}
-
static int buttons_context_path_object(ButsContextPath *path)
{
PointerRNA *ptr = &path->ptr[path->len - 1];
@@ -455,7 +421,7 @@ static int buttons_context_path_texture(const bContext *C, ButsContextPath *path
if (!ct->user)
return 0;
-
+
id = ct->user->id;
if (id) {
@@ -523,7 +489,7 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma
}
/* No pinned root, use scene as initial root. */
else {
- if (mainb == BCONTEXT_WORKSPACE) {
+ if (ELEM(mainb, BCONTEXT_WORKSPACE, BCONTEXT_TOOL)) {
RNA_id_pointer_create(&workspace->id, &path->ptr[0]);
path->len++;
}
@@ -559,12 +525,10 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma
case BCONTEXT_WORLD:
found = buttons_context_path_world(path);
break;
+ case BCONTEXT_TOOL:
case BCONTEXT_WORKSPACE:
found = buttons_context_path_workspace(path);
break;
- case BCONTEXT_COLLECTION:
- found = buttons_context_path_collection(path, sbuts->collection_context);
- break;
case BCONTEXT_OBJECT:
case BCONTEXT_PHYSICS:
case BCONTEXT_CONSTRAINT:
@@ -609,7 +573,7 @@ static int buttons_shading_context(const bContext *C, int mainb)
return 1;
if (mainb == BCONTEXT_DATA && ob && ELEM(ob->type, OB_LAMP, OB_CAMERA))
return 1;
-
+
return 0;
}
@@ -623,7 +587,7 @@ static int buttons_shading_new_context(const bContext *C, int flag)
return BCONTEXT_DATA;
else if (flag & (1 << BCONTEXT_WORLD))
return BCONTEXT_WORLD;
-
+
return BCONTEXT_RENDER;
}
@@ -895,7 +859,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
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;
@@ -903,7 +867,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
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);
@@ -943,7 +907,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
return 1;
}
}
-
+
else if (CTX_data_equals(member, "smoke")) {
PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
@@ -982,10 +946,6 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
set_pointer_type(path, result, &RNA_FreestyleLineStyle);
return 1;
}
- else if (CTX_data_equals(member, "collection")) {
- set_pointer_type(path, result, &RNA_LayerCollection);
- return 1;
- }
else {
return 0; /* not found */
}
@@ -1004,7 +964,7 @@ static void pin_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
}
else
sbuts->pinid = NULL;
-
+
ED_area_tag_redraw(CTX_wm_area(C));
}
diff --git a/source/blender/editors/space_buttons/buttons_intern.h b/source/blender/editors/space_buttons/buttons_intern.h
index 84c935dd737..aab7b39484d 100644
--- a/source/blender/editors/space_buttons/buttons_intern.h
+++ b/source/blender/editors/space_buttons/buttons_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -45,19 +45,6 @@ struct bNodeTree;
struct uiLayout;
struct wmOperatorType;
-/* buts->scaflag */
-#define BUTS_SENS_SEL 1
-#define BUTS_SENS_ACT 2
-#define BUTS_SENS_LINK 4
-#define BUTS_CONT_SEL 8
-#define BUTS_CONT_ACT 16
-#define BUTS_CONT_LINK 32
-#define BUTS_ACT_SEL 64
-#define BUTS_ACT_ACT 128
-#define BUTS_ACT_LINK 256
-#define BUTS_SENS_STATE 512
-#define BUTS_ACT_STATE 1024
-
/* context data */
typedef struct ButsContextPath {
@@ -111,7 +98,6 @@ void buttons_texture_context_compute(const struct bContext *C, struct SpaceButs
/* buttons_ops.c */
void BUTTONS_OT_file_browse(struct wmOperatorType *ot);
void BUTTONS_OT_directory_browse(struct wmOperatorType *ot);
-void BUTTONS_OT_toolbox(struct wmOperatorType *ot);
+void BUTTONS_OT_context_menu(struct wmOperatorType *ot);
#endif /* __BUTTONS_INTERN_H__ */
-
diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c
index 2a703ebb46c..93670919d4c 100644
--- a/source/blender/editors/space_buttons/buttons_ops.c
+++ b/source/blender/editors/space_buttons/buttons_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -60,9 +60,9 @@
#include "buttons_intern.h" /* own include */
-/********************** toolbox operator *********************/
+/********************** context_menu operator *********************/
-static int toolbox_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
+static int context_menu_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
bScreen *sc = CTX_wm_screen(C);
SpaceButs *sbuts = CTX_wm_space_buts(C);
@@ -80,15 +80,15 @@ static int toolbox_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UN
return OPERATOR_INTERFACE;
}
-void BUTTONS_OT_toolbox(wmOperatorType *ot)
+void BUTTONS_OT_context_menu(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Toolbox";
- ot->description = "Display button panel toolbox";
- ot->idname = "BUTTONS_OT_toolbox";
-
+ ot->name = "Context Menu";
+ ot->description = "Display button panel context_menu";
+ ot->idname = "BUTTONS_OT_context_menu";
+
/* api callbacks */
- ot->invoke = toolbox_invoke;
+ ot->invoke = context_menu_invoke;
ot->poll = ED_operator_buttons_active;
}
@@ -102,14 +102,15 @@ typedef struct 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 */
@@ -118,14 +119,14 @@ static int file_browse_exec(bContext *C, wmOperator *op)
id = fbo->ptr.id.data;
BLI_strncpy(path, str, FILE_MAX);
- BLI_path_abs(path, id ? ID_BLEND_PATH(G.main, id) : G.main->name);
-
+ 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, G.main->name);
+ BLI_path_rel(path, BKE_main_blendfile_path(bmain));
str = MEM_reallocN(str, strlen(path) + 2);
BLI_strncpy(str, path, FILE_MAX);
}
@@ -255,7 +256,7 @@ void BUTTONS_OT_file_browse(wmOperatorType *ot)
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;
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index 078ab540ace..5feb74edef7 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -78,7 +78,7 @@
/************************* Texture User **************************/
-static void buttons_texture_user_property_add(ListBase *users, ID *id,
+static void buttons_texture_user_property_add(ListBase *users, ID *id,
PointerRNA ptr, PropertyRNA *prop,
const char *category, int icon, const char *name)
{
@@ -95,7 +95,7 @@ static void buttons_texture_user_property_add(ListBase *users, ID *id,
BLI_addtail(users, user);
}
-static void buttons_texture_user_node_add(ListBase *users, ID *id,
+static void buttons_texture_user_node_add(ListBase *users, ID *id,
bNodeTree *ntree, bNode *node,
const char *category, int icon, const char *name)
{
@@ -122,10 +122,10 @@ static void buttons_texture_users_find_nodetree(ListBase *users, ID *id,
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);
}
@@ -449,7 +449,7 @@ static void template_texture_show(bContext *C, void *data_p, void *prop_p)
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);
@@ -479,12 +479,12 @@ void uiTemplateTextureShow(uiLayout *layout, bContext *C, PointerRNA *ptr, Prope
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_BUTS, 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 d3fab82f7ff..a951c2a8524 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -47,6 +47,12 @@
#include "WM_message.h"
#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "UI_resources.h"
+
+#include "GPU_glew.h"
#include "buttons_intern.h" /* own include */
@@ -56,18 +62,20 @@ static SpaceLink *buttons_new(const ScrArea *UNUSED(area), const Scene *UNUSED(s
{
ARegion *ar;
SpaceButs *sbuts;
-
+
sbuts = MEM_callocN(sizeof(SpaceButs), "initbuts");
sbuts->spacetype = SPACE_BUTS;
sbuts->align = BUT_VERTICAL;
+ sbuts->mainb = sbuts->mainbuser = BCONTEXT_OBJECT;
+
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for buts");
-
+
BLI_addtail(&sbuts->regionbase, ar);
ar->regiontype = RGN_TYPE_HEADER;
ar->alignment = RGN_ALIGN_TOP;
-
+
#if 0
/* context region */
ar = MEM_callocN(sizeof(ARegion), "context region for buts");
@@ -78,7 +86,7 @@ static SpaceLink *buttons_new(const ScrArea *UNUSED(area), const Scene *UNUSED(s
/* main region */
ar = MEM_callocN(sizeof(ARegion), "main region for buts");
-
+
BLI_addtail(&sbuts->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
@@ -87,12 +95,12 @@ static SpaceLink *buttons_new(const ScrArea *UNUSED(area), const Scene *UNUSED(s
/* not spacelink itself */
static void buttons_free(SpaceLink *sl)
-{
+{
SpaceButs *sbuts = (SpaceButs *) sl;
if (sbuts->path)
MEM_freeN(sbuts->path);
-
+
if (sbuts->texuser) {
ButsContextTexture *ct = sbuts->texuser;
BLI_freelistN(&ct->users);
@@ -117,11 +125,11 @@ static void buttons_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
static SpaceLink *buttons_duplicate(SpaceLink *sl)
{
SpaceButs *sbutsn = MEM_dupallocN(sl);
-
+
/* clear or remove stuff from old */
sbutsn->path = NULL;
sbutsn->texuser = NULL;
-
+
return (SpaceLink *)sbutsn;
}
@@ -136,46 +144,139 @@ static void buttons_main_region_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
-static void buttons_main_region_draw(const bContext *C, ARegion *ar)
+static void buttons_main_region_layout_properties(const bContext *C, SpaceButs *sbuts, ARegion *ar)
{
- /* draw entirely, view changes should be handled here */
- SpaceButs *sbuts = CTX_wm_space_buts(C);
const bool vertical = (sbuts->align == BUT_VERTICAL);
buttons_context_compute(C, sbuts);
- if (sbuts->mainb == BCONTEXT_SCENE)
- ED_region_panels(C, ar, "scene", sbuts->mainb, vertical);
- else if (sbuts->mainb == BCONTEXT_RENDER)
- ED_region_panels(C, ar, "render", sbuts->mainb, vertical);
- else if (sbuts->mainb == BCONTEXT_VIEW_LAYER)
- ED_region_panels(C, ar, "view_layer", sbuts->mainb, vertical);
- else if (sbuts->mainb == BCONTEXT_WORLD)
- ED_region_panels(C, ar, "world", sbuts->mainb, vertical);
- else if (sbuts->mainb == BCONTEXT_WORKSPACE)
- ED_region_panels(C, ar, "workspace", sbuts->mainb, vertical);
- else if (sbuts->mainb == BCONTEXT_COLLECTION)
- ED_region_panels(C, ar, "collection", sbuts->mainb, vertical);
- else if (sbuts->mainb == BCONTEXT_OBJECT)
- ED_region_panels(C, ar, "object", sbuts->mainb, vertical);
- else if (sbuts->mainb == BCONTEXT_DATA)
- ED_region_panels(C, ar, "data", sbuts->mainb, vertical);
- else if (sbuts->mainb == BCONTEXT_MATERIAL)
- ED_region_panels(C, ar, "material", sbuts->mainb, vertical);
- else if (sbuts->mainb == BCONTEXT_TEXTURE)
- ED_region_panels(C, ar, "texture", sbuts->mainb, vertical);
- else if (sbuts->mainb == BCONTEXT_PARTICLE)
- ED_region_panels(C, ar, "particle", sbuts->mainb, vertical);
- else if (sbuts->mainb == BCONTEXT_PHYSICS)
- ED_region_panels(C, ar, "physics", sbuts->mainb, vertical);
- else if (sbuts->mainb == BCONTEXT_BONE)
- ED_region_panels(C, ar, "bone", sbuts->mainb, vertical);
- else if (sbuts->mainb == BCONTEXT_MODIFIER)
- ED_region_panels(C, ar, "modifier", sbuts->mainb, vertical);
- else if (sbuts->mainb == BCONTEXT_CONSTRAINT)
- ED_region_panels(C, ar, "constraint", sbuts->mainb, vertical);
- else if (sbuts->mainb == BCONTEXT_BONE_CONSTRAINT)
- ED_region_panels(C, ar, "bone_constraint", sbuts->mainb, vertical);
+ 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_VIEW_LAYER:
+ contexts[0] = "view_layer";
+ break;
+ case BCONTEXT_WORLD:
+ contexts[0] = "world";
+ break;
+ case BCONTEXT_WORKSPACE:
+ contexts[0] = "workspace";
+ 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_CONSTRAINT:
+ contexts[0] = "constraint";
+ break;
+ case BCONTEXT_BONE_CONSTRAINT:
+ contexts[0] = "bone_constraint";
+ break;
+ case BCONTEXT_TOOL:
+ contexts[0] = "tool";
+ break;
+ }
+
+ ED_region_panels_layout_ex(C, ar, contexts, sbuts->mainb, vertical);
+}
+
+static void buttons_main_region_layout_tool(const bContext *C, SpaceButs *sbuts, ARegion *ar)
+{
+ const bool vertical = (sbuts->align == BUT_VERTICAL);
+ const char *contexts[3] = {NULL};
+
+ const WorkSpace *workspace = CTX_wm_workspace(C);
+ if (workspace->tools_space_type == SPACE_VIEW3D) {
+ const int mode = CTX_data_mode_enum(C);
+ 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, ".todo");
+ break;
+ case CTX_MODE_EDIT_ARMATURE:
+ ARRAY_SET_ITEMS(contexts, ".armature_edit");
+ break;
+ case CTX_MODE_EDIT_METABALL:
+ ARRAY_SET_ITEMS(contexts, ".todo");
+ break;
+ case CTX_MODE_EDIT_LATTICE:
+ ARRAY_SET_ITEMS(contexts, ".todo");
+ 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, ".particlemode");
+ break;
+ case CTX_MODE_OBJECT:
+ ARRAY_SET_ITEMS(contexts, ".todo");
+ break;
+ }
+ }
+ else if (workspace->tools_space_type == SPACE_IMAGE) {
+ /* TODO */
+ }
+
+ ED_region_panels_layout_ex(C, ar, contexts, -1, vertical);
+}
+
+static void buttons_main_region_layout(const bContext *C, ARegion *ar)
+{
+ /* draw entirely, view changes should be handled here */
+ SpaceButs *sbuts = CTX_wm_space_buts(C);
+
+ if (sbuts->mainb == BCONTEXT_TOOL) {
+ buttons_main_region_layout_tool(C, sbuts, ar);
+ }
+ else {
+ buttons_main_region_layout_properties(C, sbuts, ar);
+ }
sbuts->re_align = 0;
sbuts->mainbo = sbuts->mainb;
@@ -197,7 +298,7 @@ static void buttons_main_region_listener(
static void buttons_operatortypes(void)
{
- WM_operatortype_append(BUTTONS_OT_toolbox);
+ WM_operatortype_append(BUTTONS_OT_context_menu);
WM_operatortype_append(BUTTONS_OT_file_browse);
WM_operatortype_append(BUTTONS_OT_directory_browse);
}
@@ -205,8 +306,8 @@ static void buttons_operatortypes(void)
static void buttons_keymap(struct wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_find(keyconf, "Property Editor", SPACE_BUTS, 0);
-
- WM_keymap_add_item(keymap, "BUTTONS_OT_toolbox", RIGHTMOUSE, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "BUTTONS_OT_context_menu", RIGHTMOUSE, KM_PRESS, 0, 0);
}
/* add handlers, stuff you only do once or on area/region changes */
@@ -252,7 +353,7 @@ static void buttons_header_region_message_subscribe(
static void buttons_area_redraw(ScrArea *sa, short buttons)
{
SpaceButs *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);
@@ -492,10 +593,10 @@ void ED_spacetype_buttons(void)
{
SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype buttons");
ARegionType *art;
-
+
st->spaceid = SPACE_BUTS;
strncpy(st->name, "Buttons", BKE_ST_MAXNAME);
-
+
st->new = buttons_new;
st->free = buttons_free;
st->init = buttons_init;
@@ -510,19 +611,20 @@ void ED_spacetype_buttons(void)
art = MEM_callocN(sizeof(ARegionType), "spacetype buttons region");
art->regionid = RGN_TYPE_WINDOW;
art->init = buttons_main_region_init;
- art->draw = buttons_main_region_draw;
+ 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;
BLI_addhead(&st->regiontypes, art);
buttons_context_register(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;
-
+
art->init = buttons_header_region_init;
art->draw = buttons_header_region_draw;
art->message_subscribe = buttons_header_region_message_subscribe;
@@ -530,4 +632,3 @@ void ED_spacetype_buttons(void)
BKE_spacetype_register(st);
}
-
diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c
index 469d94fed3a..f2fe06874d7 100644
--- a/source/blender/editors/space_clip/clip_buttons.c
+++ b/source/blender/editors/space_clip/clip_buttons.c
@@ -387,7 +387,7 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P
else
tip = TIP_("Marker is enabled at current frame");
- bt = uiDefIconButBitI(block, UI_BTYPE_TOGGLE_N, MARKER_DISABLED, 0, ICON_RESTRICT_VIEW_OFF, 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ 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);
}
diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c
index 7ff7ea73628..d50d10d5cc3 100644
--- a/source/blender/editors/space_clip/clip_dopesheet_draw.c
+++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c
@@ -54,6 +54,7 @@
#include "GPU_draw.h"
#include "GPU_immediate.h"
+#include "GPU_state.h"
#include "clip_intern.h" /* own include */
@@ -91,7 +92,7 @@ static void clip_draw_dopesheet_background(ARegion *ar, MovieClip *clip, unsigne
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)
@@ -147,7 +148,7 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene)
strip[3] = 0.5f;
selected_strip[3] = 1.0f;
- glEnable(GL_BLEND);
+ GPU_blend(true);
clip_draw_dopesheet_background(ar, clip, pos_id);
@@ -279,7 +280,7 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene)
immUnbindProgram();
}
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
}
@@ -291,7 +292,7 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar)
MovieClip *clip = ED_space_clip_get_clip(sc);
uiStyle *style = UI_style_get();
int fontid = style->widget.uifont_id;
-
+
if (!clip)
return;
@@ -378,7 +379,7 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar)
PropertyRNA *chan_prop_lock = RNA_struct_type_find_property(&RNA_MovieTrackingTrack, "lock");
BLI_assert(chan_prop_lock);
- glEnable(GL_BLEND);
+ 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);
@@ -403,7 +404,7 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar)
/* adjust y-position for next one */
y -= CHANNEL_STEP;
}
- glDisable(GL_BLEND);
+ 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 d2f2fdd0b46..c8675fc390b 100644
--- a/source/blender/editors/space_clip/clip_dopesheet_ops.c
+++ b/source/blender/editors/space_clip/clip_dopesheet_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index 5962bfe33f3..d91e039ecb6 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -60,6 +60,7 @@
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "WM_types.h"
@@ -156,8 +157,8 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
MovieTrackingPlaneTrack *act_plane_track = BKE_tracking_plane_track_get_active(&clip->tracking);
MovieTrackingReconstruction *reconstruction = BKE_tracking_get_active_reconstruction(tracking);
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
/* cache background */
ED_region_cache_draw_background(ar);
@@ -235,7 +236,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
}
}
- glDisable(GL_BLEND);
+ GPU_blend(false);
/* current frame */
x = (sc->user.framenr - sfra) / (efra - sfra + 1) * ar->winx;
@@ -313,8 +314,8 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar,
/* checkerboard for case alpha */
if (ibuf->planes == 32) {
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
imm_draw_box_checker_2d(x, y, x + zoomx * ibuf->x, y + zoomy * ibuf->y);
}
@@ -335,7 +336,7 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar,
}
if (ibuf->planes == 32)
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
static void draw_stabilization_border(SpaceClip *sc, ARegion *ar, int width, int height, float zoomx, float zoomy)
@@ -364,7 +365,7 @@ static void draw_stabilization_border(SpaceClip *sc, ARegion *ar, int width, int
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
immUniform1i("num_colors", 0); /* "simple" mode */
@@ -460,7 +461,7 @@ static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackin
if (TRACK_VIEW_SELECTED(sc, track)) {
if ((b - a - 1) >= 1) {
- glPointSize(5.0f);
+ GPU_point_size(5.0f);
immBegin(GWN_PRIM_POINTS, b - a - 1);
@@ -475,7 +476,7 @@ static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackin
}
if ((b - a) >= 2) {
- glLineWidth(3.0f);
+ GPU_line_width(3.0f);
immBegin(GWN_PRIM_LINE_STRIP, b - a);
@@ -488,7 +489,7 @@ static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackin
}
if (TRACK_VIEW_SELECTED(sc, track)) {
- glPointSize(3.0f);
+ GPU_point_size(3.0f);
if ((curindex - a) >= 1) {
immUniformThemeColor(TH_PATH_BEFORE);
@@ -515,7 +516,7 @@ static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackin
}
}
- glLineWidth(1);
+ GPU_line_width(1);
if ((curindex - a + 1) >= 2) {
immUniformThemeColor(TH_PATH_BEFORE);
@@ -559,7 +560,7 @@ static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieT
px[0] = 1.0f / width / sc->zoom;
px[1] = 1.0f / height / sc->zoom;
- glLineWidth(tiny ? 1.0f : 3.0f);
+ GPU_line_width(tiny ? 1.0f : 3.0f);
immUniformThemeColor(TH_MARKER_OUTLINE);
@@ -576,7 +577,7 @@ static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieT
if (isect_point_quad_v2(p, marker->pattern_corners[0], marker->pattern_corners[1],
marker->pattern_corners[2], marker->pattern_corners[3]))
{
- glPointSize(tiny ? 3.0f : 4.0f);
+ GPU_point_size(tiny ? 3.0f : 4.0f);
immBegin(GWN_PRIM_POINTS, 1);
immVertex2f(position, pos[0], pos[1]);
@@ -660,7 +661,7 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
px[0] = 1.0f / width / sc->zoom;
px[1] = 1.0f / height / sc->zoom;
- glLineWidth(1.0f);
+ 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();
@@ -668,7 +669,7 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
immUniform1i("num_colors", 0); /* "simple" mode */
@@ -700,7 +701,7 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
if (isect_point_quad_v2(p, marker->pattern_corners[0], marker->pattern_corners[1],
marker->pattern_corners[2], marker->pattern_corners[3]))
{
- glPointSize(tiny ? 1.0f : 2.0f);
+ GPU_point_size(tiny ? 1.0f : 2.0f);
immUniform1f("dash_factor", 2.0f); /* Solid "line" */
@@ -932,7 +933,7 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo
BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
- glLineWidth(outline ? 3.0f : 1.0f);
+ GPU_line_width(outline ? 3.0f : 1.0f);
immBegin(GWN_PRIM_LINES, 2);
immVertex2f(pos, 0.0f, 0.0f);
@@ -1125,8 +1126,8 @@ static void draw_plane_marker_image(Scene *scene,
if (plane_track->image_opacity != 1.0f || ibuf->planes == 32) {
transparent = true;
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
}
glGenTextures(1, (GLuint *)&texid);
@@ -1174,7 +1175,7 @@ static void draw_plane_marker_image(Scene *scene,
glBindTexture(GL_TEXTURE_2D, 0);
if (transparent) {
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
}
@@ -1210,7 +1211,7 @@ static void draw_plane_marker_ex(SpaceClip *sc, Scene *scene, MovieTrackingPlane
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
immUniform1i("num_colors", 0); /* "simple" mode */
@@ -1219,7 +1220,7 @@ static void draw_plane_marker_ex(SpaceClip *sc, Scene *scene, MovieTrackingPlane
const bool stipple = !draw_outline && tiny;
const bool thick = draw_outline && !tiny;
- glLineWidth(thick ? 3.0f : 1.0f);
+ GPU_line_width(thick ? 3.0f : 1.0f);
if (stipple) {
immUniform1f("dash_width", 6.0f);
@@ -1483,7 +1484,7 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie
MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
float pos[4], vec[4], mat[4][4], aspy;
- glPointSize(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);
@@ -1711,8 +1712,8 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
immUniformColor4fv(layer->color);
- glLineWidth(layer->thickness);
- glPointSize((float)(layer->thickness + 2));
+ GPU_line_width(layer->thickness);
+ GPU_point_size((float)(layer->thickness + 2));
while (frame) {
bGPDstroke *stroke = frame->strokes.first;
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index 942bc2661c3..67aa7e19de7 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -297,7 +297,7 @@ bool ED_space_clip_color_sample(SpaceClip *sc, ARegion *ar, int mval[2], float r
ret = true;
}
}
-
+
IMB_freeImBuf(ibuf);
return ret;
diff --git a/source/blender/editors/space_clip/clip_graph_draw.c b/source/blender/editors/space_clip/clip_graph_draw.c
index 8d29cb73a68..d463f585470 100644
--- a/source/blender/editors/space_clip/clip_graph_draw.c
+++ b/source/blender/editors/space_clip/clip_graph_draw.c
@@ -45,6 +45,7 @@
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "WM_types.h"
@@ -80,11 +81,11 @@ static void tracking_segment_start_cb(void *userdata, MovieTrackingTrack *track,
if (track == data->act_track) {
col[3] = 1.0f;
- glLineWidth(2.0f);
+ GPU_line_width(2.0f);
}
else {
col[3] = 0.5f;
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
}
immUniformColor4fv(col);
@@ -152,13 +153,13 @@ static void draw_tracks_motion_curves(View2D *v2d, SpaceClip *sc, unsigned int p
(sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
&userdata, tracking_segment_knot_cb, NULL, NULL);
/* draw graph lines */
- glEnable(GL_BLEND);
+ 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);
- glDisable(GL_BLEND);
+ GPU_blend(false);
/* selected knot handles on top of curves */
userdata.sel = true;
@@ -226,11 +227,11 @@ static void tracking_error_segment_start_cb(void *userdata, MovieTrackingTrack *
if (track == data->active_track) {
col[3] = 1.0f;
- glLineWidth(2.0f);
+ GPU_line_width(2.0f);
}
else {
col[3] = 0.5f;
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
}
immUniformColor4fv(col);
@@ -330,7 +331,7 @@ void clip_draw_graph(SpaceClip *sc, ARegion *ar, Scene *scene)
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- glPointSize(3.0f);
+ GPU_point_size(3.0f);
if (sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION) {
draw_tracks_motion_curves(v2d, sc, pos);
diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c
index e5a3cb6b57b..02ea340eb57 100644
--- a/source/blender/editors/space_clip/clip_graph_ops.c
+++ b/source/blender/editors/space_clip/clip_graph_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h
index ab8a7add009..e5c4f567d5c 100644
--- a/source/blender/editors/space_clip/clip_intern.h
+++ b/source/blender/editors/space_clip/clip_intern.h
@@ -145,6 +145,8 @@ void clip_view_center_to_point(SpaceClip *sc, float x, float y);
void clip_draw_sfra_efra(struct View2D *v2d, struct Scene *scene);
+void clip_on_marker_selection_changed(struct bContext *C);
+
/* 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);
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index 0d9371a7784..c026ce8d063 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -318,7 +318,7 @@ static int reload_exec(bContext *C, wmOperator *UNUSED(op))
if (!clip)
return OPERATOR_CANCELLED;
- BKE_movieclip_reload(clip);
+ BKE_movieclip_reload(CTX_data_main(C), clip);
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
@@ -468,7 +468,7 @@ static void view_pan_cancel(bContext *C, wmOperator *op)
void CLIP_OT_view_pan(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "View Pan";
+ ot->name = "Pan View";
ot->idname = "CLIP_OT_view_pan";
ot->description = "Pan the view";
@@ -1315,7 +1315,7 @@ static void proxy_endjob(void *pjv)
if (pj->clip->source == MCLIP_SRC_MOVIE) {
/* Timecode might have changed, so do a full reload to deal with this. */
- BKE_movieclip_reload(pj->clip);
+ BKE_movieclip_reload(pj->main, pj->clip);
}
else {
/* For image sequences we'll preserve original cache. */
diff --git a/source/blender/editors/space_clip/clip_toolbar.c b/source/blender/editors/space_clip/clip_toolbar.c
index 61bd8df3dbf..3e4d0cd5bb4 100644
--- a/source/blender/editors/space_clip/clip_toolbar.c
+++ b/source/blender/editors/space_clip/clip_toolbar.c
@@ -106,7 +106,7 @@ static int properties_exec(bContext *C, wmOperator *UNUSED(op))
void CLIP_OT_properties(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Properties";
+ ot->name = "Toggle Sidebar";
ot->description = "Toggle the properties region visibility";
ot->idname = "CLIP_OT_properties";
@@ -170,7 +170,7 @@ static int tools_exec(bContext *C, wmOperator *UNUSED(op))
void CLIP_OT_tools(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Tools";
+ ot->name = "Toggle Toolbar";
ot->description = "Toggle clip tools panel";
ot->idname = "CLIP_OT_tools";
diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c
index eeb2526921f..c3208260b3b 100644
--- a/source/blender/editors/space_clip/clip_utils.c
+++ b/source/blender/editors/space_clip/clip_utils.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -46,6 +46,7 @@
#include "GPU_immediate.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -269,8 +270,8 @@ void clip_draw_sfra_efra(View2D *v2d, Scene *scene)
UI_view2d_view_ortho(v2d);
/* currently clip editor supposes that editing clip length is equal to scene frame range */
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -279,12 +280,12 @@ void clip_draw_sfra_efra(View2D *v2d, Scene *scene)
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);
- glDisable(GL_BLEND);
+ GPU_blend(false);
immUniformThemeColorShade(TH_BACK, -60);
/* thin lines where the actual frames are */
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
immBegin(GWN_PRIM_LINES, 4);
immVertex2f(pos, (float)SFRA, v2d->cur.ymin);
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index 77ebbd990d8..e9acd7320d0 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -63,6 +63,7 @@
#include "GPU_glew.h"
#include "GPU_matrix.h"
+#include "GPU_framebuffer.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -246,7 +247,7 @@ static SpaceLink *clip_new(const ScrArea *sa, const Scene *scene)
BLI_addtail(&sc->regionbase, ar);
ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = RGN_ALIGN_BOTTOM;
+ ar->alignment = RGN_ALIGN_TOP;
/* tools view */
ar = MEM_callocN(sizeof(ARegion), "tools for clip");
@@ -661,7 +662,9 @@ static void clip_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "CLIP_OT_add_marker_slide", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "CLIP_OT_delete_marker", DELKEY, KM_PRESS, KM_SHIFT, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "CLIP_OT_delete_marker", XKEY, KM_PRESS, KM_SHIFT, 0);
+#endif
WM_keymap_add_item(keymap, "CLIP_OT_slide_marker", LEFTMOUSE, KM_PRESS, 0, 0);
@@ -670,7 +673,9 @@ static void clip_keymap(struct wmKeyConfig *keyconf)
/* tracks */
WM_keymap_add_item(keymap, "CLIP_OT_delete_track", DELKEY, KM_PRESS, 0, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "CLIP_OT_delete_track", XKEY, KM_PRESS, 0, 0);
+#endif
kmi = WM_keymap_add_item(keymap, "CLIP_OT_lock_tracks", LKEY, KM_PRESS, KM_CTRL, 0);
RNA_enum_set(kmi->ptr, "action", 0); /* lock */
@@ -770,10 +775,14 @@ static void clip_keymap(struct wmKeyConfig *keyconf)
/* delete */
WM_keymap_add_item(keymap, "CLIP_OT_graph_delete_curve", DELKEY, KM_PRESS, 0, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "CLIP_OT_graph_delete_curve", XKEY, KM_PRESS, 0, 0);
+#endif
WM_keymap_add_item(keymap, "CLIP_OT_graph_delete_knot", DELKEY, KM_PRESS, KM_SHIFT, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "CLIP_OT_graph_delete_knot", XKEY, KM_PRESS, KM_SHIFT, 0);
+#endif
/* view */
WM_keymap_add_item(keymap, "CLIP_OT_graph_view_all", HOMEKEY, KM_PRESS, 0, 0);
@@ -1146,7 +1155,7 @@ static void clip_main_region_draw(const bContext *C, ARegion *ar)
/* clear and setup matrix */
UI_ThemeClearColor(TH_BACK);
- glClear(GL_COLOR_BUFFER_BIT);
+ GPU_clear(GPU_COLOR_BIT);
/* data... */
movieclip_main_area_set_view2d(C, ar);
@@ -1253,7 +1262,7 @@ static void graph_region_draw(const bContext *C, ARegion *ar)
/* clear and setup matrix */
UI_ThemeClearColor(TH_BACK);
- glClear(GL_COLOR_BUFFER_BIT);
+ GPU_clear(GPU_COLOR_BIT);
UI_view2d_view_ortho(v2d);
@@ -1273,7 +1282,7 @@ static void graph_region_draw(const bContext *C, ARegion *ar)
scrollers = UI_view2d_scrollers_calc(C, v2d, unitx, V2D_GRID_NOCLAMP, unity, V2D_GRID_NOCLAMP);
UI_view2d_scrollers_draw(C, v2d, scrollers);
UI_view2d_scrollers_free(scrollers);
-
+
/* currnt frame indicator */
if (sc->flag & SC_SHOW_SECONDS) cfra_flag |= DRAWCFRA_UNIT_SECONDS;
UI_view2d_view_orthoSpecial(ar, v2d, 1);
@@ -1295,7 +1304,7 @@ static void dopesheet_region_draw(const bContext *C, ARegion *ar)
/* clear and setup matrix */
UI_ThemeClearColor(TH_BACK);
- glClear(GL_COLOR_BUFFER_BIT);
+ GPU_clear(GPU_COLOR_BIT);
UI_view2d_view_ortho(v2d);
@@ -1320,7 +1329,7 @@ static void dopesheet_region_draw(const bContext *C, ARegion *ar)
scrollers = UI_view2d_scrollers_calc(C, v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
UI_view2d_scrollers_draw(C, v2d, scrollers);
UI_view2d_scrollers_free(scrollers);
-
+
/* currnt frame number indicator */
UI_view2d_view_orthoSpecial(ar, v2d, 1);
ANIM_draw_cfra_number(C, v2d, cfra_flag);
@@ -1368,7 +1377,7 @@ static void clip_channels_region_draw(const bContext *C, ARegion *ar)
/* clear and setup matrix */
UI_ThemeClearColor(TH_BACK);
- glClear(GL_COLOR_BUFFER_BIT);
+ GPU_clear(GPU_COLOR_BIT);
UI_view2d_view_ortho(v2d);
@@ -1435,7 +1444,7 @@ static void clip_tools_region_init(wmWindowManager *wm, ARegion *ar)
static void clip_tools_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
/****************** tool properties region ******************/
@@ -1484,7 +1493,7 @@ static void clip_properties_region_draw(const bContext *C, ARegion *ar)
BKE_movieclip_update_scopes(sc->clip, &sc->user, &sc->scopes);
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
static void clip_properties_region_listener(
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c
index bfce5a862d0..1572b9b8f78 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -155,8 +155,8 @@ static int add_marker_at_click_invoke(bContext *C,
wmOperator *op,
const wmEvent *UNUSED(event))
{
- ED_area_headerprint(
- CTX_wm_area(C),
+ ED_workspace_status_text(
+ C,
IFACE_("Use LMB click to define location where place the marker"));
/* Add modal handler for ESC. */
@@ -180,7 +180,7 @@ static int add_marker_at_click_modal(bContext *C,
ARegion *ar = CTX_wm_region(C);
float pos[2];
- ED_area_headerprint(CTX_wm_area(C), NULL);
+ ED_workspace_status_text(C, NULL);
ED_clip_point_stable_pos(sc, ar,
event->x - ar->winrct.xmin,
@@ -196,7 +196,7 @@ static int add_marker_at_click_modal(bContext *C,
}
case ESCKEY:
- ED_area_headerprint(CTX_wm_area(C), NULL);
+ ED_workspace_status_text(C, NULL);
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/space_clip/tracking_ops_intern.h b/source/blender/editors/space_clip/tracking_ops_intern.h
index 6ac9287c914..b53799b88d8 100644
--- a/source/blender/editors/space_clip/tracking_ops_intern.h
+++ b/source/blender/editors/space_clip/tracking_ops_intern.h
@@ -50,4 +50,4 @@ void clip_tracking_hide_cursor(struct bContext *C);
void ed_tracking_delect_all_tracks(struct ListBase *tracks_base);
void ed_tracking_delect_all_plane_tracks(struct ListBase *plane_tracks_base);
-#endif /* __TRACKING_OPS_INTERN_H__ */ \ No newline at end of file
+#endif /* __TRACKING_OPS_INTERN_H__ */
diff --git a/source/blender/editors/space_clip/tracking_ops_orient.c b/source/blender/editors/space_clip/tracking_ops_orient.c
index 2c6ef20f1c4..3db52e6a39b 100644
--- a/source/blender/editors/space_clip/tracking_ops_orient.c
+++ b/source/blender/editors/space_clip/tracking_ops_orient.c
@@ -145,7 +145,8 @@ static int count_selected_bundles(bContext *C)
return tot;
}
-static void object_solver_inverted_matrix(Scene *scene,
+static void object_solver_inverted_matrix(Depsgraph *depsgraph,
+ Scene *scene,
Object *ob,
float invmat[4][4])
{
@@ -162,7 +163,7 @@ static void object_solver_inverted_matrix(Scene *scene,
bObjectSolverConstraint *data = (bObjectSolverConstraint *)con->data;
if (!found) {
Object *cam = data->camera ? data->camera : scene->camera;
- BKE_object_where_is_calc_mat4(scene, cam, invmat);
+ BKE_object_where_is_calc_mat4(depsgraph, scene, cam, invmat);
}
mul_m4_m4m4(invmat, invmat, data->invmat);
found = true;
@@ -200,6 +201,7 @@ static int set_origin_exec(bContext *C, wmOperator *op)
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
Object *camera = get_camera_with_movieclip(scene, clip);
int selected_count = count_selected_bundles(C);
@@ -236,14 +238,14 @@ static int set_origin_exec(bContext *C, wmOperator *op)
mul_v3_fl(median, 1.0f / selected_count);
float mat[4][4], vec[3];
- BKE_tracking_get_camera_object_matrix(scene, camera, mat);
+ BKE_tracking_get_camera_object_matrix(depsgraph, 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);
+ object_solver_inverted_matrix(depsgraph, scene, object, mat);
mul_v3_m4v3(vec, mat, vec);
copy_v3_v3(object->loc, vec);
}
@@ -278,7 +280,8 @@ void CLIP_OT_set_origin(wmOperatorType *ot)
/********************** set floor operator *********************/
-static void set_axis(Scene *scene,
+static void set_axis(Depsgraph *depsgraph,
+ Scene *scene,
Object *ob,
MovieClip *clip,
MovieTrackingObject *tracking_object,
@@ -292,14 +295,14 @@ static void set_axis(Scene *scene,
BKE_object_to_mat4(ob, obmat);
- BKE_tracking_get_camera_object_matrix(scene, camera, mat);
+ BKE_tracking_get_camera_object_matrix(depsgraph, 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);
+ object_solver_inverted_matrix(depsgraph, scene, ob, imat);
mul_v3_m4v3(vec, imat, vec);
invert_m4_m4(imat, obmat);
@@ -430,7 +433,7 @@ static int set_plane_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- BKE_tracking_get_camera_object_matrix(scene, camera, mat);
+ BKE_tracking_get_camera_object_matrix(depsgraph, scene, camera, mat);
/* Get 3 bundles to use as reference. */
track = tracksbase->first;
@@ -493,7 +496,7 @@ static int set_plane_exec(bContext *C, wmOperator *op)
}
BKE_object_where_is_calc(depsgraph, scene, object);
- set_axis(scene, object, clip, tracking_object, axis_track, 'X');
+ set_axis(depsgraph, scene, object, clip, tracking_object, axis_track, 'X');
DEG_id_tag_update(&clip->id, 0);
DEG_id_tag_update(&object->id, OB_RECALC_OB);
@@ -539,6 +542,7 @@ static int set_axis_exec(bContext *C, wmOperator *op)
MovieTracking *tracking = &clip->tracking;
MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
Object *object;
int axis = RNA_enum_get(op->ptr, "axis");
@@ -567,7 +571,7 @@ static int set_axis_exec(bContext *C, wmOperator *op)
track = track->next;
}
- set_axis(scene, object, clip, tracking_object, track, axis == 0 ? 'X' : 'Y');
+ set_axis(depsgraph, scene, object, clip, tracking_object, track, axis == 0 ? 'X' : 'Y');
DEG_id_tag_update(&clip->id, 0);
DEG_id_tag_update(&object->id, OB_RECALC_OB);
@@ -618,6 +622,7 @@ static int do_set_scale(bContext *C,
MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
MovieTrackingTrack *track;
Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
Object *object = NULL;
Object *camera = get_camera_with_movieclip(scene, clip);
ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
@@ -642,7 +647,7 @@ static int do_set_scale(bContext *C,
}
}
- BKE_tracking_get_camera_object_matrix(scene, camera, mat);
+ BKE_tracking_get_camera_object_matrix(depsgraph, scene, camera, mat);
track = tracksbase->first;
while (track) {
diff --git a/source/blender/editors/space_clip/tracking_ops_stabilize.c b/source/blender/editors/space_clip/tracking_ops_stabilize.c
index 4eb6a4fbb24..cb9b40f8a10 100644
--- a/source/blender/editors/space_clip/tracking_ops_stabilize.c
+++ b/source/blender/editors/space_clip/tracking_ops_stabilize.c
@@ -345,4 +345,3 @@ void CLIP_OT_stabilize_2d_rotation_select(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
diff --git a/source/blender/editors/space_console/console_draw.c b/source/blender/editors/space_console/console_draw.c
index c8a06545e0f..66b203ff612 100644
--- a/source/blender/editors/space_console/console_draw.c
+++ b/source/blender/editors/space_console/console_draw.c
@@ -74,7 +74,7 @@ void console_scrollback_prompt_begin(struct SpaceConsole *sc, ConsoleLine *cl_du
/* 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;
@@ -83,7 +83,7 @@ void console_scrollback_prompt_begin(struct SpaceConsole *sc, ConsoleLine *cl_du
memcpy(cl_dummy->line + prompt_len, cl->line, cl->len + 1);
BLI_addtail(&sc->scrollback, cl_dummy);
}
-void console_scrollback_prompt_end(struct SpaceConsole *sc, ConsoleLine *cl_dummy)
+void console_scrollback_prompt_end(struct SpaceConsole *sc, ConsoleLine *cl_dummy)
{
MEM_freeN(cl_dummy->line);
BLI_remlink(&sc->scrollback, cl_dummy);
@@ -98,10 +98,10 @@ static int console_textview_begin(TextViewContext *tvc)
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;
-
+
return (tvc->iter != NULL);
}
@@ -109,7 +109,7 @@ static void console_textview_end(TextViewContext *tvc)
{
SpaceConsole *sc = (SpaceConsole *)tvc->arg1;
(void)sc;
-
+
}
static int console_textview_step(TextViewContext *tvc)
@@ -199,7 +199,7 @@ static int console_textview_main__internal(struct SpaceConsole *sc, ARegion *ar,
{
ConsoleLine cl_dummy = {NULL};
int ret = 0;
-
+
View2D *v2d = &ar->v2d;
TextViewContext tvc = {0};
diff --git a/source/blender/editors/space_console/console_intern.h b/source/blender/editors/space_console/console_intern.h
index f523cf0d476..c0ef6e95d2e 100644
--- a/source/blender/editors/space_console/console_intern.h
+++ b/source/blender/editors/space_console/console_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c
index b740ff4b397..32cf5ea2055 100644
--- a/source/blender/editors/space_console/console_ops.c
+++ b/source/blender/editors/space_console/console_ops.c
@@ -92,9 +92,9 @@ void console_scrollback_free(SpaceConsole *sc, ConsoleLine *cl)
static void console_scrollback_limit(SpaceConsole *sc)
{
int tot;
-
+
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);
}
@@ -122,16 +122,16 @@ static bool console_line_cursor_set(ConsoleLine *cl, int cursor)
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;
@@ -147,7 +147,7 @@ static void console_history_debug(const bContext *C)
{
SpaceConsole *sc = CTX_wm_space_console(C);
-
+
console_lb_debug__internal(&sc->history);
}
#endif
@@ -155,7 +155,7 @@ static void console_history_debug(const bContext *C)
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);
@@ -168,7 +168,7 @@ static ConsoleLine *console_lb_add__internal(ListBase *lb, ConsoleLine *from)
ci->len_alloc = 64;
ci->len = 0;
}
-
+
BLI_addtail(lb, ci);
return ci;
}
@@ -182,7 +182,7 @@ static ConsoleLine *console_history_add(SpaceConsole *sc, ConsoleLine *from)
static ConsoleLine *console_scrollback_add(const bContext *C, ConsoleLine *from)
{
SpaceConsole *sc = CTX_wm_space_console(C);
-
+
return console_lb_add__internal(&sc->scrollback, from);
}
#endif
@@ -192,9 +192,9 @@ static ConsoleLine *console_lb_add_str__internal(ListBase *lb, char *str, bool o
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;
}
@@ -215,7 +215,7 @@ ConsoleLine *console_history_verify(const bContext *C)
ConsoleLine *ci = sc->history.last;
if (ci == NULL)
ci = console_history_add(sc, NULL);
-
+
return ci;
}
@@ -233,7 +233,7 @@ static void console_line_verify_length(ConsoleLine *ci, int len)
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;
}
@@ -242,7 +242,7 @@ static void console_line_verify_length(ConsoleLine *ci, int len)
static int console_line_insert(ConsoleLine *ci, char *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--;
@@ -250,15 +250,15 @@ static int console_line_insert(ConsoleLine *ci, char *str)
if (len == 0)
return 0;
-
+
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);
-
+
ci->len += len;
ci->cursor += len;
-
+
return len;
}
@@ -312,11 +312,11 @@ static const EnumPropertyItem console_move_type_items[] = {
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;
@@ -364,7 +364,7 @@ static int console_move_exec(bContext *C, wmOperator *op)
done = console_line_cursor_set(ci, pos);
break;
}
-
+
if (done) {
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
@@ -383,7 +383,7 @@ void CONSOLE_OT_move(wmOperatorType *ot)
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;
@@ -410,9 +410,9 @@ static int console_insert_exec(bContext *C, wmOperator *op)
}
len = console_line_insert(ci, str);
-
+
MEM_freeN(str);
-
+
if (len == 0) {
return OPERATOR_CANCELLED;
}
@@ -442,7 +442,7 @@ static int console_insert_invoke(bContext *C, wmOperator *op, const wmEvent *eve
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);
@@ -466,7 +466,7 @@ void CONSOLE_OT_insert(wmOperatorType *ot)
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;
@@ -588,11 +588,11 @@ static int console_delete_exec(bContext *C, wmOperator *op)
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:
@@ -640,7 +640,7 @@ static int console_delete_exec(bContext *C, wmOperator *op)
ED_area_tag_redraw(CTX_wm_area(C));
console_scroll_bottom(ar);
-
+
return OPERATOR_FINISHED;
}
@@ -651,7 +651,7 @@ void CONSOLE_OT_delete(wmOperatorType *ot)
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;
@@ -700,17 +700,17 @@ static int console_clear_exec(bContext *C, wmOperator *op)
{
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");
-
+
/*ConsoleLine *ci = */ console_history_verify(C);
-
+
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);
@@ -729,11 +729,11 @@ void CONSOLE_OT_clear(wmOperatorType *ot)
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");
@@ -778,7 +778,7 @@ static int console_history_cycle_exec(bContext *C, wmOperator *op)
console_history_add(sc, (ConsoleLine *)sc->history.last);
}
-
+
ci = sc->history.last;
console_select_offset(sc, ci->len - prev_len);
@@ -797,11 +797,11 @@ void CONSOLE_OT_history_cycle(wmOperatorType *ot)
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;
-
+
/* properties */
RNA_def_boolean(ot->srna, "reverse", 0, "Reverse", "Reverse cycle history");
}
@@ -852,11 +852,11 @@ void CONSOLE_OT_history_append(wmOperatorType *ot)
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);
@@ -870,15 +870,15 @@ 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;
-
+
char *str = RNA_string_get_alloc(op->ptr, "text", NULL, 0); /* own this text in the new line, don't free */
int type = RNA_enum_get(op->ptr, "type");
console_history_verify(C);
-
+
ci = console_scrollback_add_str(sc, str, 1); /* own the string */
ci->type = type;
-
+
console_scrollback_limit(sc);
/* 'ar' can be null depending on the operator that runs
@@ -888,7 +888,7 @@ static int console_scrollback_append_exec(bContext *C, wmOperator *op)
}
ED_area_tag_redraw(CTX_wm_area(C));
-
+
return OPERATOR_FINISHED;
}
@@ -907,11 +907,11 @@ void CONSOLE_OT_scrollback_append(wmOperatorType *ot)
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");
@@ -924,7 +924,7 @@ static int console_copy_exec(bContext *C, wmOperator *UNUSED(op))
DynStr *buf_dyn;
char *buf_str;
-
+
ConsoleLine *cl;
int sel[2];
int offset = 0;
@@ -1088,7 +1088,7 @@ static void console_modal_select_apply(bContext *C, wmOperator *op, const wmEven
sel_prev[0] = sc->sel_start;
sel_prev[1] = sc->sel_end;
-
+
console_cursor_set_to_pos(sc, ar, scu, mval, true);
/* only redraw if the selection changed */
@@ -1140,8 +1140,11 @@ static int console_modal_select(bContext *C, wmOperator *op, const wmEvent *even
case LEFTMOUSE:
case MIDDLEMOUSE:
case RIGHTMOUSE:
- console_cursor_set_exit(C, op);
- return OPERATOR_FINISHED;
+ 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;
diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c
index c49df387707..74bc7e95643 100644
--- a/source/blender/editors/space_console/space_console.c
+++ b/source/blender/editors/space_console/space_console.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
+ *
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
@@ -49,6 +49,7 @@
#include "UI_view2d.h"
#include "console_intern.h" // own include
+#include "GPU_framebuffer.h"
/* ******************** default callbacks for console space ***************** */
@@ -56,26 +57,26 @@ static SpaceLink *console_new(const ScrArea *UNUSED(area), const Scene *UNUSED(s
{
ARegion *ar;
SpaceConsole *sconsole;
-
+
sconsole = MEM_callocN(sizeof(SpaceConsole), "initconsole");
sconsole->spacetype = SPACE_CONSOLE;
-
+
sconsole->lheight = 14;
-
+
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for console");
-
+
BLI_addtail(&sconsole->regionbase, ar);
ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = RGN_ALIGN_BOTTOM;
-
-
+ ar->alignment = RGN_ALIGN_TOP;
+
+
/* main region */
ar = MEM_callocN(sizeof(ARegion), "main region for text");
-
+
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 */
@@ -94,10 +95,10 @@ static SpaceLink *console_new(const ScrArea *UNUSED(area), const Scene *UNUSED(s
static void console_free(SpaceLink *sl)
{
SpaceConsole *sc = (SpaceConsole *) sl;
-
+
while (sc->scrollback.first)
console_scrollback_free(sc, sc->scrollback.first);
-
+
while (sc->history.first)
console_history_free(sc, sc->history.first);
}
@@ -112,13 +113,13 @@ static void console_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa)
static SpaceLink *console_duplicate(SpaceLink *sl)
{
SpaceConsole *sconsolen = MEM_dupallocN(sl);
-
+
/* 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);
-
+
return (SpaceLink *)sconsolen;
}
@@ -147,10 +148,10 @@ static void console_main_region_init(wmWindowManager *wm, ARegion *ar)
/* own keymap */
keymap = WM_keymap_find(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);
-
+
WM_event_add_dropbox_handler(&ar->handlers, lb);
}
@@ -208,7 +209,7 @@ static void path_drop_copy(wmDrag *drag, wmDropBox *drop)
static void console_dropboxes(void)
{
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);
}
@@ -227,7 +228,7 @@ static void console_main_region_draw(const bContext *C, ARegion *ar)
/* clear and setup matrix */
UI_ThemeClearColor(TH_BACK);
- glClear(GL_COLOR_BUFFER_BIT);
+ GPU_clear(GPU_COLOR_BIT);
/* worlks best with no view2d matrix set */
UI_view2d_view_ortho(v2d);
@@ -236,10 +237,10 @@ static void console_main_region_draw(const bContext *C, ARegion *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);
-
+
/* scrollers */
scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_GRID_CLAMP);
UI_view2d_scrollers_draw(C, v2d, scrollers);
@@ -255,9 +256,9 @@ static void console_operatortypes(void)
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_history_append);
WM_operatortype_append(CONSOLE_OT_scrollback_append);
WM_operatortype_append(CONSOLE_OT_clear);
@@ -273,7 +274,7 @@ static void console_keymap(struct wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_find(keyconf, "Console", SPACE_CONSOLE, 0);
wmKeyMapItem *kmi;
-
+
#ifdef __APPLE__
RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", LEFTARROWKEY, KM_PRESS, KM_OSKEY, 0)->ptr, "type", LINE_BEGIN);
RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", RIGHTARROWKEY, KM_PRESS, KM_OSKEY, 0)->ptr, "type", LINE_END);
@@ -281,14 +282,14 @@ static void console_keymap(struct wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", PREV_WORD);
RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", NEXT_WORD);
-
+
RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", HOMEKEY, KM_PRESS, 0, 0)->ptr, "type", LINE_BEGIN);
RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", ENDKEY, KM_PRESS, 0, 0)->ptr, "type", LINE_END);
-
+
kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", WHEELUPMOUSE, KM_PRESS, KM_CTRL, 0);
RNA_string_set(kmi->ptr, "data_path", "space_data.font_size");
RNA_boolean_set(kmi->ptr, "reverse", false);
-
+
kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL, 0);
RNA_string_set(kmi->ptr, "data_path", "space_data.font_size");
RNA_boolean_set(kmi->ptr, "reverse", true);
@@ -296,17 +297,17 @@ static void console_keymap(struct wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
RNA_string_set(kmi->ptr, "data_path", "space_data.font_size");
RNA_boolean_set(kmi->ptr, "reverse", false);
-
+
kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", PADMINUS, KM_PRESS, KM_CTRL, 0);
RNA_string_set(kmi->ptr, "data_path", "space_data.font_size");
RNA_boolean_set(kmi->ptr, "reverse", true);
RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", LEFTARROWKEY, KM_PRESS, 0, 0)->ptr, "type", PREV_CHAR);
RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", RIGHTARROWKEY, KM_PRESS, 0, 0)->ptr, "type", NEXT_CHAR);
-
+
RNA_boolean_set(WM_keymap_add_item(keymap, "CONSOLE_OT_history_cycle", UPARROWKEY, KM_PRESS, 0, 0)->ptr, "reverse", true);
RNA_boolean_set(WM_keymap_add_item(keymap, "CONSOLE_OT_history_cycle", DOWNARROWKEY, KM_PRESS, 0, 0)->ptr, "reverse", false);
-
+
#if 0
RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", PREV_WORD);
RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", NEXT_WORD);
@@ -315,7 +316,7 @@ static void console_keymap(struct wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", PAGEUPKEY, KM_PRESS, 0, 0)->ptr, "type", PREV_PAGE);
RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", PAGEDOWNKEY, KM_PRESS, 0, 0)->ptr, "type", NEXT_PAGE);
#endif
-
+
RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", DELKEY, KM_PRESS, 0, 0)->ptr, "type", DEL_NEXT_CHAR);
RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", BACKSPACEKEY, KM_PRESS, 0, 0)->ptr, "type", DEL_PREV_CHAR);
RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", BACKSPACEKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", DEL_PREV_CHAR); /* same as above [#26623] */
@@ -331,7 +332,7 @@ static void console_keymap(struct wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "interactive", true);
kmi = WM_keymap_add_item(keymap, "CONSOLE_OT_execute", PADENTER, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "interactive", true);
-
+
//WM_keymap_add_item(keymap, "CONSOLE_OT_autocomplete", TABKEY, KM_PRESS, 0, 0); /* python operator - space_text.py */
WM_keymap_add_item(keymap, "CONSOLE_OT_autocomplete", SPACEKEY, KM_PRESS, KM_CTRL, 0); /* python operator - space_text.py */
#endif
@@ -343,7 +344,7 @@ static void console_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "CONSOLE_OT_copy", CKEY, KM_PRESS, KM_OSKEY, 0);
WM_keymap_add_item(keymap, "CONSOLE_OT_paste", VKEY, KM_PRESS, KM_OSKEY, 0);
#endif
-
+
WM_keymap_add_item(keymap, "CONSOLE_OT_select_set", LEFTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "CONSOLE_OT_select_word", LEFTMOUSE, KM_DBL_CLICK, 0, 0);
@@ -401,10 +402,10 @@ 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;
@@ -412,7 +413,7 @@ void ED_spacetype_console(void)
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;
@@ -422,20 +423,20 @@ void ED_spacetype_console(void)
art->draw = console_main_region_draw;
art->cursor = console_cursor;
art->listener = console_main_region_listener;
-
-
+
+
BLI_addhead(&st->regiontypes, art);
-
+
/* 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;
-
+
art->init = console_header_region_init;
art->draw = console_header_region_draw;
-
+
BLI_addhead(&st->regiontypes, art);
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index 043f32c56e7..4d4845c41b9 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -74,6 +74,7 @@
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
+#include "GPU_state.h"
#include "filelist.h"
@@ -86,7 +87,7 @@ static char *file_draw_tooltip_func(bContext *UNUSED(C), void *argN, const char
return BLI_strdup(dyn_tooltip);
}
-/* Note: This function uses pixelspace (0, 0, winx, winy), not view2d.
+/* Note: This function uses pixelspace (0, 0, winx, winy), not view2d.
* The controls are laid out as follows:
*
* -------------------------------------------
@@ -121,14 +122,14 @@ void file_draw_buttons(const bContext *C, ARegion *ar)
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);
@@ -212,11 +213,11 @@ void file_draw_buttons(const bContext *C, ARegion *ar)
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);
@@ -233,7 +234,7 @@ void file_draw_buttons(const bContext *C, ARegion *ar)
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;
@@ -254,7 +255,7 @@ void file_draw_buttons(const bContext *C, ARegion *ar)
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);
}
@@ -274,10 +275,10 @@ static void file_draw_icon(uiBlock *block, const char *path, int sx, int sy, int
uiBut *but;
int x, y;
// float alpha = 1.0f;
-
+
x = sx;
y = sy - height;
-
+
/*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);
@@ -323,7 +324,7 @@ void file_calc_previews(const bContext *C, ARegion *ar)
{
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);
}
@@ -377,14 +378,14 @@ static void file_draw_preview(
xco = sx + (int)dx;
yco = sy - layout->prv_h + (int)dy;
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
/* shadow */
if (use_dropshadow) {
UI_draw_box_shadow(220, (float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey));
}
- glEnable(GL_BLEND);
+ GPU_blend(true);
/* the image */
if (!is_icon && typeflags & FILE_TYPE_FTFONT) {
@@ -419,11 +420,12 @@ static void file_draw_preview(
UI_but_drag_set_image(but, BLI_strdup(path), icon, imb, scale, true);
}
- glDisable(GL_BLEND);
+ 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];
@@ -432,10 +434,11 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname)
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
- BLI_make_file_string(G.main->name, orgname, sfile->params->dir, oldname);
+ 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->renameedit, sizeof(filename));
BLI_filename_make_safe(filename);
- BLI_make_file_string(G.main->name, newname, sfile->params->dir, filename);
+ BLI_make_file_string(blendfile_path, newname, sfile->params->dir, filename);
if (!STREQ(orgname, newname)) {
if (!BLI_exists(newname)) {
@@ -556,11 +559,11 @@ void file_draw_list(const bContext *C, ARegion *ar)
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);
}
diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h
index 71e38f72a7a..6eaf2dda084 100644
--- a/source/blender/editors/space_file/file_intern.h
+++ b/source/blender/editors/space_file/file_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -109,9 +109,9 @@ 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(struct wmOperator *op, struct SpaceFile *sfile, char *filepath);
-void file_sfile_to_operator(struct wmOperator *op, struct SpaceFile *sfile);
-void file_operator_to_sfile(struct SpaceFile *sfile, struct wmOperator *op);
+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);
/* filesel.c */
@@ -130,4 +130,3 @@ void file_panels_register(struct ARegionType *art);
void file_tile_boundbox(const ARegion *ar, FileLayout *layout, const int file, rcti *r_bounds);
#endif /* __FILE_INTERN_H__ */
-
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index 217ce8f1d9a..ad77463300d 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Andrea Weikert (c) 2008 Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -75,7 +75,7 @@
static FileSelection find_file_mouse_rect(SpaceFile *sfile, ARegion *ar, const rcti *rect_region)
{
FileSelection sel;
-
+
View2D *v2d = &ar->v2d;
rcti rect_view;
rctf rect_view_fl;
@@ -92,7 +92,7 @@ static FileSelection find_file_mouse_rect(SpaceFile *sfile, ARegion *ar, const r
(int)(v2d->tot.ymax - rect_view_fl.ymax));
sel = ED_fileselect_layout_offset_rect(sfile->layout, &rect_view);
-
+
return sel;
}
@@ -101,14 +101,14 @@ static void file_deselect_all(SpaceFile *sfile, unsigned int flag)
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);
}
typedef enum FileSelect {
FILE_SELECT_NOTHING = 0,
- FILE_SELECT_DIR = 1,
- FILE_SELECT_FILE = 2
+ FILE_SELECT_DIR = 1,
+ FILE_SELECT_FILE = 2
} FileSelect;
static void clamp_to_filelist(int numfiles, FileSelection *sel)
@@ -122,7 +122,7 @@ static void clamp_to_filelist(int numfiles, FileSelection *sel)
sel->first = -1;
sel->last = -1;
}
-
+
/* fix if last file invalid */
if ( (sel->first > 0) && (sel->last < 0) )
sel->last = numfiles - 1;
@@ -176,6 +176,7 @@ static FileSelection file_selection_get(bContext *C, const rcti *rect, bool fill
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);
@@ -213,7 +214,7 @@ static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen)
}
}
else {
- BLI_cleanup_dir(G.main->name, params->dir);
+ BLI_cleanup_dir(BKE_main_blendfile_path(bmain), params->dir);
strcat(params->dir, file->relpath);
BLI_add_slash(params->dir);
}
@@ -298,10 +299,10 @@ static FileSelect file_select(bContext *C, const rcti *rect, FileSelType select,
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;
@@ -333,7 +334,7 @@ static FileSelect file_select(bContext *C, const rcti *rect, FileSelType select,
/* update operator for name change event */
file_draw_check(C);
-
+
return retval;
}
@@ -457,10 +458,10 @@ static int file_border_select_exec(bContext *C, wmOperator *op)
void FILE_OT_select_border(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Activate/Select File";
+ ot->name = "Border Select";
ot->description = "Activate/select the file(s) contained in the border";
ot->idname = "FILE_OT_select_border";
-
+
/* api callbacks */
ot->invoke = WM_gesture_border_invoke;
ot->exec = file_border_select_exec;
@@ -526,10 +527,10 @@ void FILE_OT_select(wmOperatorType *ot)
PropertyRNA *prop;
/* identifiers */
- ot->name = "Activate/Select File";
+ 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;
@@ -777,7 +778,7 @@ static int file_select_all_exec(bContext *C, wmOperator *UNUSED(op))
const int numfiles = filelist_files_ensure(sfile->files);
const bool has_selection = file_is_any_selected(sfile->files);
- sel.first = 0;
+ sel.first = 0;
sel.last = numfiles - 1;
/* select all only if previously no file was selected */
@@ -813,7 +814,7 @@ void FILE_OT_select_all_toggle(wmOperatorType *ot)
ot->name = "(De)select All Files";
ot->description = "Select or deselect all files";
ot->idname = "FILE_OT_select_all_toggle";
-
+
/* api callbacks */
ot->exec = file_select_all_exec;
ot->poll = ED_operator_file_active;
@@ -826,6 +827,7 @@ void FILE_OT_select_all_toggle(wmOperatorType *ot)
/* Note we could get rid of this one, but it's used by some addon so... 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;
@@ -835,12 +837,12 @@ static int bookmark_select_exec(bContext *C, wmOperator *op)
RNA_property_string_get(op->ptr, prop, entry);
BLI_strncpy(params->dir, entry, sizeof(params->dir));
- BLI_cleanup_dir(G.main->name, 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);
}
-
+
return OPERATOR_FINISHED;
}
@@ -852,7 +854,7 @@ void FILE_OT_select_bookmark(wmOperatorType *ot)
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;
@@ -871,7 +873,7 @@ static int bookmark_add_exec(bContext *C, wmOperator *UNUSED(op))
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);
@@ -888,7 +890,7 @@ void FILE_OT_bookmark_add(wmOperatorType *ot)
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;
@@ -913,7 +915,7 @@ static int bookmark_delete_exec(bContext *C, wmOperator *op)
}
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);
@@ -933,7 +935,7 @@ void FILE_OT_bookmark_delete(wmOperatorType *ot)
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;
@@ -1080,7 +1082,7 @@ 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();
-
+
while (ED_fsmenu_get_entry(fsmenu, FS_CATEGORY_RECENT, 0) != NULL) {
fsmenu_remove_entry(fsmenu, FS_CATEGORY_RECENT, 0);
}
@@ -1097,7 +1099,7 @@ void FILE_OT_reset_recent(wmOperatorType *ot)
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;
@@ -1148,7 +1150,7 @@ static int file_highlight_invoke(bContext *C, wmOperator *UNUSED(op), const wmEv
return OPERATOR_CANCELLED;
ED_area_tag_redraw(CTX_wm_area(C));
-
+
return OPERATOR_FINISHED;
}
@@ -1158,7 +1160,7 @@ void FILE_OT_highlight(struct wmOperatorType *ot)
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;
@@ -1169,11 +1171,11 @@ int file_cancel_exec(bContext *C, wmOperator *UNUSED(unused))
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
wmOperator *op = sfile->op;
-
+
sfile->op = NULL;
WM_event_fileselect_event(wm, op, EVT_FILESELECT_CANCEL);
-
+
return OPERATOR_FINISHED;
}
@@ -1193,22 +1195,23 @@ void FILE_OT_cancel(struct wmOperatorType *ot)
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;
}
-void file_sfile_to_operator_ex(wmOperator *op, SpaceFile *sfile, char *filepath)
+void file_sfile_to_operator_ex(bContext *C, wmOperator *op, SpaceFile *sfile, char *filepath)
{
+ Main *bmain = CTX_data_main(C);
PropertyRNA *prop;
BLI_join_dirfile(filepath, FILE_MAX, sfile->params->dir, sfile->params->file); /* XXX, not real length */
if ((prop = RNA_struct_find_property(op->ptr, "relative_path"))) {
if (RNA_property_boolean_get(op->ptr, prop)) {
- BLI_path_rel(filepath, G.main->name);
+ BLI_path_rel(filepath, BKE_main_blendfile_path(bmain));
}
}
@@ -1221,7 +1224,7 @@ void file_sfile_to_operator_ex(wmOperator *op, SpaceFile *sfile, char *filepath)
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. */
@@ -1259,7 +1262,7 @@ void file_sfile_to_operator_ex(wmOperator *op, SpaceFile *sfile, char *filepath)
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);
@@ -1270,15 +1273,16 @@ void file_sfile_to_operator_ex(wmOperator *op, SpaceFile *sfile, char *filepath)
}
}
-void file_sfile_to_operator(wmOperator *op, SpaceFile *sfile)
+void file_sfile_to_operator(bContext *C, wmOperator *op, SpaceFile *sfile)
{
char filepath[FILE_MAX];
- file_sfile_to_operator_ex(op, sfile, filepath);
+ file_sfile_to_operator_ex(C, op, sfile, filepath);
}
-void file_operator_to_sfile(SpaceFile *sfile, wmOperator *op)
+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 */
@@ -1295,10 +1299,10 @@ void file_operator_to_sfile(SpaceFile *sfile, wmOperator *op)
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 doesnt hurt to do this every time */
- BLI_path_abs(sfile->params->dir, G.main->name);
+ BLI_path_abs(sfile->params->dir, BKE_main_blendfile_path(bmain));
/* XXX, files and dirs updates missing, not really so important though */
}
@@ -1330,12 +1334,12 @@ void file_draw_check(bContext *C)
wmOperator *op = sfile->op;
if (op) { /* fail on reload */
if (op->type->check) {
- file_sfile_to_operator(op, sfile);
-
+ file_sfile_to_operator(C, op, sfile);
+
/* redraw */
if (op->type->check(C, op)) {
- file_operator_to_sfile(sfile, op);
-
+ file_operator_to_sfile(C, sfile, op);
+
/* redraw, else the changed settings wont get updated */
ED_area_tag_redraw(CTX_wm_area(C));
}
@@ -1369,6 +1373,7 @@ bool file_draw_check_exists(SpaceFile *sfile)
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);
@@ -1384,7 +1389,7 @@ int file_exec(bContext *C, wmOperator *exec_op)
BLI_parent_dir(sfile->params->dir);
}
else {
- BLI_cleanup_path(G.main->name, sfile->params->dir);
+ 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);
}
@@ -1394,13 +1399,13 @@ int file_exec(bContext *C, wmOperator *exec_op)
/* 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,
+
+ /* 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;
@@ -1410,17 +1415,17 @@ int file_exec(bContext *C, wmOperator *exec_op)
if (active == 0)
return OPERATOR_CANCELLED;
}
-
+
sfile->op = NULL;
- file_sfile_to_operator_ex(op, sfile, filepath);
+ 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(G.main->name, filepath, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL),
+ 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);
@@ -1438,10 +1443,10 @@ void FILE_OT_execute(struct wmOperatorType *ot)
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;
+ ot->poll = file_operator_poll;
/* properties */
prop = RNA_def_boolean(ot->srna, "need_active", 0, "Need Active",
@@ -1452,11 +1457,12 @@ void FILE_OT_execute(struct wmOperatorType *ot)
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(G.main->name, 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. */
@@ -1466,7 +1472,7 @@ int file_parent_exec(bContext *C, wmOperator *UNUSED(unused))
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
}
-
+
return OPERATOR_FINISHED;
}
@@ -1478,7 +1484,7 @@ void FILE_OT_parent(struct wmOperatorType *ot)
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 */
@@ -1509,7 +1515,7 @@ void FILE_OT_previous(struct wmOperatorType *ot)
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 */
@@ -1540,7 +1546,7 @@ void FILE_OT_next(struct wmOperatorType *ot)
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 */
@@ -1581,7 +1587,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
/* 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);
/* check if we are editing a name */
@@ -1621,9 +1627,9 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
if (sfile->scroll_offset <= offset) sfile->scroll_offset -= sfile->layout->columns;
}
}
-
+
numfiles_layout = ED_fileselect_layout_numfiles(sfile->layout, ar);
-
+
/* check if we have reached our final scroll position */
if ( (sfile->scroll_offset >= offset) && (sfile->scroll_offset < offset + numfiles_layout) ) {
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer);
@@ -1631,10 +1637,10 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
return OPERATOR_FINISHED;
}
- /* temporarily set context to the main window region,
+ /* 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) {
@@ -1643,7 +1649,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
else {
WM_operator_name_call(C, "VIEW2D_OT_scroll_up", 0, NULL);
}
-
+
}
else {
if (sfile->layout->flag & FILE_LAYOUT_HOR) {
@@ -1653,27 +1659,27 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
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";
-
+
/* api callbacks */
ot->invoke = file_smoothscroll_invoke;
-
+
ot->poll = ED_operator_file_active;
}
@@ -1694,7 +1700,7 @@ static int filepath_drop_exec(bContext *C, wmOperator *op)
file_sfile_filepath_set(sfile, filepath);
if (sfile->op) {
- file_sfile_to_operator(sfile->op, sfile);
+ file_sfile_to_operator(C, sfile->op, sfile);
file_draw_check(C);
}
@@ -1749,12 +1755,12 @@ int file_directory_new_exec(bContext *C, wmOperator *op)
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
ScrArea *sa = CTX_wm_area(C);
-
+
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"))) {
@@ -1824,7 +1830,7 @@ void FILE_OT_directory_new(struct wmOperatorType *ot)
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;
@@ -1840,12 +1846,13 @@ void FILE_OT_directory_new(struct wmOperatorType *ot)
/* 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) {
- /* TODO, what about // when relbase isn't valid? */
- if (G.relbase_valid && BLI_path_is_rel(sfile->params->dir)) {
- BLI_path_abs(sfile->params->dir, G.main->name);
+ 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];
@@ -1898,8 +1905,9 @@ static bool can_create_dir(const char *dir)
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);
@@ -1928,7 +1936,7 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN
}
}
- BLI_cleanup_dir(G.main->name, sfile->params->dir);
+ 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 */
@@ -1975,6 +1983,7 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN
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];
@@ -1995,7 +2004,7 @@ void file_filename_enter_handle(bContext *C, void *UNUSED(arg_unused), void *arg
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);
}
@@ -2004,7 +2013,7 @@ void file_filename_enter_handle(bContext *C, void *UNUSED(arg_unused), void *arg
/* if directory, open it and empty filename field */
if (filelist_is_dir(sfile->files, filepath)) {
- BLI_cleanup_dir(G.main->name, 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);
@@ -2024,7 +2033,7 @@ void FILE_OT_refresh(struct wmOperatorType *ot)
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 */
@@ -2035,13 +2044,13 @@ static int file_hidedot_exec(bContext *C, wmOperator *UNUSED(unused))
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
ScrArea *sa = CTX_wm_area(C);
-
+
if (sfile->params) {
sfile->params->flag ^= FILE_HIDE_DOT;
ED_fileselect_clear(wm, sa, sfile);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
-
+
return OPERATOR_FINISHED;
}
@@ -2052,7 +2061,7 @@ void FILE_OT_hidedot(struct wmOperatorType *ot)
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 */
@@ -2067,11 +2076,11 @@ ARegion *file_tools_region(ScrArea *sa)
/* add subdiv level; after header */
ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
-
+
/* 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;
@@ -2089,7 +2098,7 @@ static int file_bookmark_toggle_exec(bContext *C, wmOperator *UNUSED(unused))
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = file_tools_region(sa);
-
+
if (ar)
ED_region_toggle_hidden(C, ar);
@@ -2102,7 +2111,7 @@ void FILE_OT_bookmark_toggle(struct wmOperatorType *ot)
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 */
@@ -2144,7 +2153,7 @@ static int file_filenum_exec(bContext *C, wmOperator *op)
{
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);
@@ -2152,7 +2161,7 @@ static int file_filenum_exec(bContext *C, wmOperator *op)
file_draw_check(C);
// WM_event_add_notifier(C, NC_WINDOW, NULL);
}
-
+
return OPERATOR_FINISHED;
}
@@ -2163,7 +2172,7 @@ void FILE_OT_filenum(struct wmOperatorType *ot)
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 */
@@ -2176,7 +2185,7 @@ 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);
@@ -2188,7 +2197,7 @@ static int file_rename_exec(bContext *C, wmOperator *UNUSED(op))
}
ED_area_tag_redraw(sa);
}
-
+
return OPERATOR_FINISHED;
}
@@ -2232,10 +2241,10 @@ void FILE_OT_rename(struct wmOperatorType *ot)
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;
+ ot->poll = file_rename_poll;
}
@@ -2262,13 +2271,14 @@ static int file_delete_poll(bContext *C)
}
else
poll = 0;
-
+
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);
@@ -2281,7 +2291,7 @@ int file_delete_exec(bContext *C, wmOperator *op)
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(G.main->name, str, sfile->params->dir, file->relpath);
+ 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))
{
@@ -2289,7 +2299,7 @@ int file_delete_exec(bContext *C, wmOperator *op)
}
}
}
-
+
if (report_error) {
BKE_reportf(op->reports, RPT_ERROR,
"Could not delete file: %s",
@@ -2298,7 +2308,7 @@ int file_delete_exec(bContext *C, wmOperator *op)
ED_fileselect_clear(wm, sa, sfile);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -2309,7 +2319,7 @@ void FILE_OT_delete(struct wmOperatorType *ot)
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;
@@ -2321,6 +2331,6 @@ void ED_operatormacros_file(void)
{
// wmOperatorType *ot;
// wmOperatorTypeMacro *otmacro;
-
+
/* future macros */
}
diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c
index 363e9666399..11b891d1c1e 100644
--- a/source/blender/editors/space_file/file_panels.c
+++ b/source/blender/editors/space_file/file_panels.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation, Andrea Weikert
*
* ***** END GPL LICENSE BLOCK *****
@@ -107,4 +107,3 @@ void file_panels_register(ARegionType *art)
pt->draw = file_panel_operator;
BLI_addtail(&art->paneltypes, pt);
}
-
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index d670af59bc9..09e2660a762 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -43,7 +43,7 @@
#else
# include <io.h>
# include <direct.h>
-#endif
+#endif
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
@@ -188,13 +188,13 @@ void folderlist_free(ListBase *folderlist)
ListBase *folderlist_duplicate(ListBase *folderlist)
{
-
+
if (folderlist) {
ListBase *folderlistn = MEM_callocN(sizeof(*folderlistn), __func__);
FolderList *folder;
-
+
BLI_duplicatelist(folderlistn, folderlist);
-
+
for (folder = folderlistn->first; folder; folder = folder->next) {
folder->foldername = MEM_dupallocN(folder->foldername);
}
@@ -267,10 +267,11 @@ typedef struct FileListEntryPreview {
ImBuf *img;
} FileListEntryPreview;
+
typedef struct FileListFilter {
unsigned int filter;
unsigned int filter_id;
- char filter_glob[256];
+ char filter_glob[FILE_MAXFILE];
char filter_search[66]; /* + 2 for heading/trailing implicit '*' wildcards. */
short flags;
} FileListFilter;
@@ -404,7 +405,7 @@ static int compare_direntry_generic(const FileListInternEntry *entry1, const Fil
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;
}
@@ -436,7 +437,7 @@ static int compare_date(void *UNUSED(user_data), const void *a1, const void *a2)
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;
@@ -459,7 +460,7 @@ static int compare_size(void *UNUSED(user_data), const void *a1, const void *a2)
if ((ret = compare_direntry_generic(entry1, entry2))) {
return ret;
}
-
+
size1 = entry1->st.st_size;
size2 = entry2->st.st_size;
if (size1 < size2) return 1;
@@ -1347,7 +1348,7 @@ void filelist_free(struct FileList *filelist)
printf("Attempting to delete empty filelist.\n");
return;
}
-
+
filelist_clear_ex(filelist, false, false); /* No need to clear cache & selection_state, we free them anyway. */
filelist_cache_free(&filelist->filelist_cache);
@@ -1419,7 +1420,7 @@ void filelist_setdir(struct FileList *filelist, char *r_dir)
{
BLI_assert(strlen(r_dir) < FILE_MAX_LIBEXTRA);
- BLI_cleanup_dir(G.main->name, r_dir);
+ 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);
@@ -1555,7 +1556,7 @@ FileDirEntry *filelist_file(struct FileList *filelist, int index)
int filelist_file_findpath(struct FileList *filelist, const char *filename)
{
int fidx = -1;
-
+
if (filelist->filelist.nbr_entries_filtered < 0) {
return fidx;
}
@@ -1950,17 +1951,17 @@ static bool file_is_blend_backup(const char *str)
}
else {
const char *loc;
-
+
if (a > b + 1)
b++;
-
+
/* allow .blend1 .blend2 .blend32 */
loc = BLI_strcasestr(str + a - b, ".blend");
-
+
if (loc)
retval = 1;
}
-
+
return (retval);
}
@@ -1973,31 +1974,31 @@ int ED_path_extension_type(const char *path)
else if (file_is_blend_backup(path)) {
return FILE_TYPE_BLENDER_BACKUP;
}
- else if (BLI_testextensie(path, ".app")) {
+ else if (BLI_path_extension_check(path, ".app")) {
return FILE_TYPE_APPLICATIONBUNDLE;
}
- else if (BLI_testextensie(path, ".py")) {
+ else if (BLI_path_extension_check(path, ".py")) {
return FILE_TYPE_PYSCRIPT;
}
- else if (BLI_testextensie_n(path, ".txt", ".glsl", ".osl", ".data", ".pov", ".ini", ".mcr", ".inc", NULL)) {
+ else if (BLI_path_extension_check_n(path, ".txt", ".glsl", ".osl", ".data", ".pov", ".ini", ".mcr", ".inc", NULL)) {
return FILE_TYPE_TEXT;
}
- else if (BLI_testextensie_n(path, ".ttf", ".ttc", ".pfb", ".otf", ".otc", NULL)) {
+ else if (BLI_path_extension_check_n(path, ".ttf", ".ttc", ".pfb", ".otf", ".otc", NULL)) {
return FILE_TYPE_FTFONT;
}
- else if (BLI_testextensie(path, ".btx")) {
+ else if (BLI_path_extension_check(path, ".btx")) {
return FILE_TYPE_BTX;
}
- else if (BLI_testextensie(path, ".dae")) {
+ else if (BLI_path_extension_check(path, ".dae")) {
return FILE_TYPE_COLLADA;
}
- else if (BLI_testextensie(path, ".abc")) {
+ else if (BLI_path_extension_check(path, ".abc")) {
return FILE_TYPE_ALEMBIC;
}
- else if (BLI_testextensie_array(path, imb_ext_image)) {
+ else if (BLI_path_extension_check_array(path, imb_ext_image)) {
return FILE_TYPE_IMAGE;
}
- else if (BLI_testextensie(path, ".ogg")) {
+ else if (BLI_path_extension_check(path, ".ogg")) {
if (IMB_isanim(path)) {
return FILE_TYPE_MOVIE;
}
@@ -2005,10 +2006,10 @@ int ED_path_extension_type(const char *path)
return FILE_TYPE_SOUND;
}
}
- else if (BLI_testextensie_array(path, imb_ext_movie)) {
+ else if (BLI_path_extension_check_array(path, imb_ext_movie)) {
return FILE_TYPE_MOVIE;
}
- else if (BLI_testextensie_array(path, imb_ext_audio)) {
+ else if (BLI_path_extension_check_array(path, imb_ext_audio)) {
return FILE_TYPE_SOUND;
}
return 0;
@@ -2024,7 +2025,7 @@ static int file_extension_type(const char *dir, const char *relpath)
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;
@@ -2233,7 +2234,7 @@ static int filelist_readjob_list_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_testextensie_glob(entry->relpath, filter_glob)) {
+ if (filter_glob[0] && BLI_path_extension_check_glob(entry->relpath, filter_glob)) {
entry->typeflag |= FILE_TYPE_OPERATOR;
}
}
@@ -2313,13 +2314,13 @@ static int filelist_readjob_list_lib(const char *root, ListBase *entries, const
#if 0
/* Kept for reference here, in case we want to add back that feature later. We do not need it currently. */
/* Code ***NOT*** updated for job stuff! */
-static void filelist_readjob_main_rec(struct FileList *filelist)
+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);
@@ -2375,7 +2376,7 @@ static void filelist_readjob_main_rec(struct FileList *filelist)
/* make files */
idcode = groupname_to_code(filelist->filelist.root);
- lb = which_libbase(G.main, idcode);
+ lb = which_libbase(bmain, idcode);
if (lb == NULL) return;
filelist->filelist.nbr_entries = 0;
@@ -2394,7 +2395,7 @@ static void filelist_readjob_main_rec(struct FileList *filelist)
}
files = filelist->filelist.entries;
-
+
if (!(filelist->filter_data.flags & FLF_HIDE_PARENT)) {
files->entry->relpath = BLI_strdup(FILENAME_PARENT);
files->typeflag |= FILE_TYPE_DIR;
@@ -2464,7 +2465,7 @@ static void filelist_readjob_do(
BLI_Stack *todo_dirs;
TodoDir *td_dir;
char dir[FILE_MAX_LIBEXTRA];
- char filter_glob[64]; /* TODO should be define! */
+ 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;
@@ -2700,13 +2701,14 @@ static void filelist_readjob_free(void *flrjv)
void filelist_readjob_start(FileList *filelist, const bContext *C)
{
+ 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, G.main->name, sizeof(flrj->main_name));
+ 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;
diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h
index 4e9c1e0dd1d..76845c44226 100644
--- a/source/blender/editors/space_file/filelist.h
+++ b/source/blender/editors/space_file/filelist.h
@@ -127,4 +127,3 @@ bool filelist_cache_previews_running(struct FileList *filelist);
#endif
#endif
-
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index 3dfeb5eb5b3..cb014f30d95 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -96,11 +96,13 @@ 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(G.main->name, sfile->params->dir, sfile->params->file, sizeof(sfile->params->dir), sizeof(sfile->params->file));
+ 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;
@@ -149,8 +151,8 @@ short ED_fileselect_set_params(SpaceFile *sfile)
}
if (params->dir[0]) {
- BLI_cleanup_dir(G.main->name, params->dir);
- BLI_path_abs(params->dir, G.main->name);
+ 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) {
@@ -194,6 +196,10 @@ short ED_fileselect_set_params(SpaceFile *sfile)
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);
}
@@ -224,7 +230,7 @@ short ED_fileselect_set_params(SpaceFile *sfile)
else {
params->flag &= ~FILE_HIDE_DOT;
}
-
+
if (params->type == FILE_LOADLIB) {
params->flag |= RNA_boolean_get(op->ptr, "link") ? FILE_LINK : 0;
@@ -283,8 +289,8 @@ short ED_fileselect_set_params(SpaceFile *sfile)
sfile->folders_prev = folderlist_new();
if (!sfile->params->dir[0]) {
- if (G.main->name[0]) {
- BLI_split_dir_part(G.main->name, sfile->params->dir, sizeof(sfile->params->dir));
+ 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();
@@ -366,12 +372,12 @@ FileSelection ED_fileselect_layout_offset_rect(FileLayout *layout, const rcti *r
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) )
{
@@ -380,12 +386,12 @@ FileSelection ED_fileselect_layout_offset_rect(FileLayout *layout, const rcti *r
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)
+ if (layout->flag & FILE_LAYOUT_HOR)
sel.first = layout->rows * colmin + rowmin;
else
sel.first = colmin + layout->columns * rowmin;
@@ -394,7 +400,7 @@ FileSelection ED_fileselect_layout_offset_rect(FileLayout *layout, const rcti *r
sel.last = -1;
}
else {
- if (layout->flag & FILE_LAYOUT_HOR)
+ if (layout->flag & FILE_LAYOUT_HOR)
sel.last = layout->rows * colmax + rowmax;
else
sel.last = colmax + layout->columns * rowmax;
@@ -410,14 +416,14 @@ int ED_fileselect_layout_offset(FileLayout *layout, int x, int y)
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);
-
+
if (offsetx > layout->columns - 1) return -1;
if (offsety > layout->rows - 1) return -1;
-
- if (layout->flag & FILE_LAYOUT_HOR)
+
+ if (layout->flag & FILE_LAYOUT_HOR)
active_file = layout->rows * offsetx + offsety;
else
active_file = offsetx + layout->columns * offsety;
@@ -611,12 +617,12 @@ void ED_file_change_dir(bContext *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
+ /* 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++) {
@@ -645,7 +651,7 @@ int autocomplete_directory(struct bContext *C, char *str, void *UNUSED(arg_v))
DIR *dir;
struct dirent *de;
-
+
BLI_split_dir_part(str, dirname, sizeof(dirname));
dir = opendir(dirname);
@@ -660,7 +666,7 @@ int autocomplete_directory(struct bContext *C, char *str, void *UNUSED(arg_v))
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) {
@@ -726,7 +732,7 @@ void ED_fileselect_exit(wmWindowManager *wm, ScrArea *sa, SpaceFile *sfile)
folderlist_free(sfile->folders_prev);
folderlist_free(sfile->folders_next);
-
+
if (sfile->files) {
ED_fileselect_clear(wm, sa, sfile);
filelist_free(sfile->files);
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
index ee0ec3fda39..5ecb95bf61b 100644
--- a/source/blender/editors/space_file/fsmenu.c
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -42,8 +42,6 @@
#include "BKE_appdir.h"
-#include "DNA_space_types.h"
-
#include "ED_fileselect.h"
#ifdef WIN32
@@ -352,7 +350,7 @@ void fsmenu_remove_entry(struct FSMenu *fsmenu, FSMenuCategory category, int idx
idx--;
if (fsm_iter) {
- /* you should only be able to remove entries that were
+ /* 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) {
@@ -512,18 +510,18 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
/* 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 */
@@ -531,29 +529,29 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
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,
+ 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;
@@ -565,11 +563,11 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
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);
}
diff --git a/source/blender/editors/space_file/fsmenu.h b/source/blender/editors/space_file/fsmenu.h
index 81014874fb5..bb201a7a80c 100644
--- a/source/blender/editors/space_file/fsmenu.h
+++ b/source/blender/editors/space_file/fsmenu.h
@@ -23,7 +23,7 @@
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
- *
+ *
*/
/** \file blender/editors/space_file/fsmenu.h
@@ -60,7 +60,7 @@ void fsmenu_remove_entry(struct FSMenu *fsmenu, enum FSMenuCategory category,
/** saves the 'bookmarks' to the specified file */
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);
@@ -80,4 +80,3 @@ void fsmenu_refresh_bookmarks_status(struct FSMenu *fsmenu);
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 40707d5add7..858bbb06688 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -65,6 +65,7 @@
#include "file_intern.h" // own include
#include "fsmenu.h"
#include "filelist.h"
+#include "GPU_framebuffer.h"
/* ******************** default callbacks for file space ***************** */
@@ -115,9 +116,9 @@ static SpaceLink *file_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scen
/* not spacelink itself */
static void file_free(SpaceLink *sl)
-{
+{
SpaceFile *sfile = (SpaceFile *) sl;
-
+
BLI_assert(sfile->previews_timer == NULL);
if (sfile->files) {
@@ -185,7 +186,7 @@ static SpaceLink *file_duplicate(SpaceLink *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 */
@@ -203,7 +204,7 @@ static SpaceLink *file_duplicate(SpaceLink *sl)
if (sfileo->folders_next)
sfilen->folders_next = folderlist_duplicate(sfileo->folders_next);
-
+
if (sfileo->layout) {
sfilen->layout = MEM_dupallocN(sfileo->layout);
}
@@ -326,9 +327,9 @@ static void file_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Sce
static void file_main_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
-
+
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
-
+
/* own keymaps */
keymap = WM_keymap_find(wm->defaultconf, "File Browser", SPACE_FILE, 0);
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
@@ -408,11 +409,11 @@ static void file_main_region_draw(const bContext *C, ARegion *ar)
/* clear and setup matrix */
UI_GetThemeColor3fv(TH_BACK, col);
- glClearColor(col[0], col[1], col[2], 0.0);
- glClear(GL_COLOR_BUFFER_BIT);
-
+ 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;
@@ -422,7 +423,7 @@ static void file_main_region_draw(const bContext *C, ARegion *ar)
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 doesnt scroll vertically */
if (v2d->cur.ymax < 0) {
@@ -438,18 +439,18 @@ static void file_main_region_draw(const bContext *C, ARegion *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, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
UI_view2d_scrollers_draw(C, v2d, scrollers);
@@ -505,7 +506,9 @@ static void file_keymap(struct wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", HKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "space_data.params.show_hidden");
WM_keymap_add_item(keymap, "FILE_OT_directory_new", IKEY, KM_PRESS, 0, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "FILE_OT_delete", XKEY, KM_PRESS, 0, 0);
+#endif
WM_keymap_add_item(keymap, "FILE_OT_delete", DELKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "FILE_OT_smoothscroll", TIMER1, KM_ANY, KM_ANY, 0);
@@ -603,8 +606,8 @@ static void file_keymap(struct wmKeyConfig *keyconf)
RNA_int_set(kmi->ptr, "increment", -10);
kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADMINUS, KM_PRESS, KM_CTRL, 0);
RNA_int_set(kmi->ptr, "increment", -100);
-
-
+
+
/* keys for button region (top) */
keymap = WM_keymap_find(keyconf, "File Browser Buttons", SPACE_FILE, 0);
kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADPLUSKEY, KM_PRESS, 0, 0);
@@ -636,7 +639,7 @@ static void file_tools_region_init(wmWindowManager *wm, ARegion *ar)
static void file_tools_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
static void file_tools_region_listener(
@@ -655,9 +658,9 @@ static void file_tools_region_listener(
static void file_header_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
-
+
ED_region_header_init(ar);
-
+
keymap = WM_keymap_find(wm->defaultconf, "File Browser", SPACE_FILE, 0);
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
@@ -687,8 +690,8 @@ static void file_ui_region_draw(const bContext *C, ARegion *ar)
float col[3];
/* clear */
UI_GetThemeColor3fv(TH_BACK, col);
- glClearColor(col[0], col[1], col[2], 0.0);
- glClear(GL_COLOR_BUFFER_BIT);
+ 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);
@@ -748,10 +751,10 @@ 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;
@@ -772,7 +775,7 @@ void ED_spacetype_file(void)
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;
@@ -782,7 +785,7 @@ void ED_spacetype_file(void)
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;
@@ -843,7 +846,7 @@ void ED_file_exit(void)
void ED_file_read_bookmarks(void)
{
const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL);
-
+
fsmenu_free();
fsmenu_read_system(ED_fsmenu_get(), true);
@@ -854,4 +857,3 @@ void ED_file_read_bookmarks(void)
fsmenu_read_bookmarks(ED_fsmenu_get(), name);
}
}
-
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index c79652795ac..2a0d5baa5c3 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation, Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
@@ -81,25 +81,25 @@ static int graph_panel_context(const bContext *C, bAnimListElem **ale, FCurve **
{
bAnimContext ac;
bAnimListElem *elem = NULL;
-
- /* for now, only draw if we could init the anim-context info (necessary for all animation-related tools)
+
+ /* 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)
+ 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)
+ if (elem == NULL)
return 0;
-
+
if (fcu)
*fcu = (FCurve *)elem->data;
if (ale)
*ale = elem;
else
MEM_freeN(elem);
-
+
return 1;
}
@@ -118,7 +118,7 @@ static void graph_panel_view(const bContext *C, Panel *pa)
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);
@@ -126,7 +126,7 @@ static void graph_panel_view(const bContext *C, Panel *pa)
/* 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");
@@ -139,7 +139,7 @@ static void graph_panel_view(const bContext *C, Panel *pa)
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);
@@ -154,20 +154,15 @@ static void graph_panel_properties(const bContext *C, Panel *pa)
PointerRNA fcu_ptr;
uiLayout *layout = pa->layout;
uiLayout *col, *row, *sub;
- // uiBlock *block; // UNUSED
char name[256];
int icon = 0;
if (!graph_panel_context(C, &ale, &fcu))
return;
-
- // UNUSED
- // block = uiLayoutGetBlock(layout);
- // UI_block_func_handle_set(block, do_graph_region_buttons, NULL);
-
+
/* 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) {
@@ -177,7 +172,7 @@ static void graph_panel_properties(const bContext *C, Panel *pa)
else {
/* NLA Control Curve, etc. */
const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
-
+
/* get name */
if (acf && acf->name) {
acf->name(ale, name);
@@ -186,26 +181,26 @@ static void graph_panel_properties(const bContext *C, Panel *pa)
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);
@@ -225,31 +220,31 @@ static short get_active_fcurve_keyframe_edit(FCurve *fcu, BezTriple **bezt, BezT
{
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
+
+ /* 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
+ /* 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;
}
@@ -258,7 +253,7 @@ static short get_active_fcurve_keyframe_edit(FCurve *fcu, BezTriple **bezt, BezT
static void graphedit_activekey_update_cb(bContext *UNUSED(C), void *fcu_ptr, void *UNUSED(bezt_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);
@@ -268,8 +263,8 @@ static void graphedit_activekey_update_cb(bContext *UNUSED(C), void *fcu_ptr, vo
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
+
+ /* 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)) {
@@ -280,7 +275,7 @@ static void graphedit_activekey_handles_cb(bContext *C, void *fcu_ptr, void *bez
else {
BKE_nurb_bezt_handle_test(bezt, true);
}
-
+
/* now call standard updates */
graphedit_activekey_update_cb(C, fcu_ptr, bezt_ptr);
}
@@ -310,20 +305,20 @@ static void graphedit_activekey_left_handle_coord_cb(bContext *C, void *fcu_ptr,
static void graphedit_activekey_right_handle_coord_cb(bContext *C, void *fcu_ptr, void *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;
-
- /* temporarily make it so that only the right handle is selected, so that updates go correctly
+
+ /* 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);
-
+
/* restore selection state so that no-one notices this hack */
bezt->f1 = f1;
bezt->f3 = f3;
@@ -334,34 +329,34 @@ 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) {
@@ -372,7 +367,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *pa)
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);
@@ -391,8 +386,8 @@ static void graph_panel_key_properties(const bContext *C, Panel *pa)
default:
break;
}
-
- /* numerical coordinate editing
+
+ /* 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
*/
@@ -400,50 +395,50 @@ static void graph_panel_key_properties(const bContext *C, Panel *pa)
/* 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");
@@ -464,7 +459,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *pa)
else
uiItemL(layout, IFACE_("No active keyframe on F-Curve"), ICON_NONE);
}
-
+
MEM_freeN(ale);
}
@@ -472,46 +467,39 @@ static void graph_panel_key_properties(const bContext *C, Panel *pa)
#define B_IPO_DEPCHANGE 10
-static void do_graph_region_driver_buttons(bContext *C, void *UNUSED(arg), int event)
+static void do_graph_region_driver_buttons(bContext *C, void *fcu_v, int event)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
-
+
switch (event) {
case B_IPO_DEPCHANGE:
{
+ /* 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;
+ }
+
/* rebuild depsgraph for the new deps */
DEG_relations_tag_update(bmain);
break;
}
}
-
+
/* default for now */
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); // XXX could use better notifier
}
-/* callback to remove the active driver */
-static void driver_remove_cb(bContext *C, void *ale_v, void *UNUSED(arg))
-{
- bAnimListElem *ale = (bAnimListElem *)ale_v;
- ID *id = ale->id;
- FCurve *fcu = ale->data;
- ReportList *reports = CTX_wm_reports(C);
-
- /* try to get F-Curve that driver lives on, and ID block which has this AnimData */
- if (ELEM(NULL, id, fcu))
- return;
-
- /* call API method to remove this driver */
- ANIM_remove_driver(reports, id, fcu->rna_path, fcu->array_index, 0);
- ED_undo_push(C, "Remove Driver");
-}
-
/* 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;
-
+
/* add a new variable */
driver_add_new_variable(driver);
ED_undo_push(C, "Add Driver Variable");
@@ -522,7 +510,7 @@ static void driver_delete_var_cb(bContext *C, void *driver_v, void *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");
@@ -533,9 +521,9 @@ static void driver_dvar_invalid_name_query_cb(bContext *C, void *dvar_v, void *U
{
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);
}
@@ -543,7 +531,7 @@ static void driver_dvar_invalid_name_query_cb(bContext *C, void *dvar_v, void *U
uiItemL(layout, "It cannot start with a number", ICON_ERROR);
}
if (dvar->flag & DVAR_FLAG_INVALID_START_CHAR) {
- uiItemL(layout,
+ uiItemL(layout,
"It cannot start with a special character,"
" including '$', '@', '!', '~', '+', '-', '_', '.', or ' '",
ICON_NONE);
@@ -560,7 +548,7 @@ static void driver_dvar_invalid_name_query_cb(bContext *C, void *dvar_v, void *U
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);
}
@@ -569,7 +557,7 @@ static void driver_update_flags_cb(bContext *UNUSED(C), void *fcu_v, void *UNUSE
{
FCurve *fcu = (FCurve *)fcu_v;
ChannelDriver *driver = fcu->driver;
-
+
/* clear invalid flags */
fcu->flag &= ~FCURVE_DISABLED;
driver->flag &= ~DRIVER_FLAG_INVALID;
@@ -592,22 +580,22 @@ static void graph_panel_driverVar__singleProp(uiLayout *layout, ID *id, DriverVa
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);
-
+ 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));
@@ -664,23 +652,23 @@ static void graph_panel_driverVar__locDiff(uiLayout *layout, ID *id, DriverVar *
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);
+ 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", IFACE_("Bone"), ICON_BONE_DATA);
}
-
+
uiLayoutSetRedAlert(col, false); /* we can clear it again now - it's only needed when creating the ID/Bone fields */
uiItemR(col, &dtar_ptr, "transform_space", 0, NULL, ICON_NONE);
@@ -688,14 +676,14 @@ static void graph_panel_driverVar__locDiff(uiLayout *layout, ID *id, DriverVar *
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", IFACE_("Bone"), ICON_BONE_DATA);
}
-
+
uiLayoutSetRedAlert(col, false); /* we can clear it again now - it's only needed when creating the ID/Bone fields */
uiItemR(col, &dtar2_ptr, "transform_space", 0, NULL, ICON_NONE);
}
@@ -707,92 +695,123 @@ static void graph_panel_driverVar__transChan(uiLayout *layout, ID *id, DriverVar
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);
-
+ 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);
}
-/* driver settings for active F-Curve (only for 'Drivers' mode) */
-static void graph_panel_drivers(const bContext *C, Panel *pa)
+/* ----------------------------------------------------------------- */
+
+
+/* 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)
{
- bAnimListElem *ale;
- FCurve *fcu;
- ChannelDriver *driver;
+ PointerRNA fcu_ptr;
+ uiLayout *row;
+ char name[256];
+ int icon = 0;
+
+ /* 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);
+
+ /* 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 F-Curve/driver target */
+ uiItemL(row, "", VICO_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)
+{
+ ChannelDriver *driver = fcu->driver;
DriverVar *dvar;
-
+
PointerRNA driver_ptr;
- uiLayout *col;
+ uiLayout *col, *row;
uiBlock *block;
uiBut *but;
-
- /* Get settings from context */
- if (!graph_panel_context(C, &ale, &fcu))
- return;
- driver = fcu->driver;
-
+
/* set event handler for panel */
- block = uiLayoutGetBlock(pa->layout); // xxx?
+ block = uiLayoutGetBlock(layout);
UI_block_func_handle_set(block, do_graph_region_driver_buttons, NULL);
-
- /* general actions - management */
- col = uiLayoutColumn(pa->layout, false);
- block = uiLayoutGetBlock(col);
- 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"));
- UI_but_func_set(but, driver_update_flags_cb, fcu, NULL);
- but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ZOOMOUT, IFACE_("Remove Driver"),
- 0, 0, 10 * UI_UNIT_X, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0, 0,
- TIP_("Remove this driver"));
- UI_but_funcN_set(but, driver_remove_cb, MEM_dupallocN(ale), NULL);
-
/* driver-level settings - type, expressions, and errors */
- RNA_pointer_create(ale->id, &RNA_Driver, driver, &driver_ptr);
-
- col = uiLayoutColumn(pa->layout, true);
+ 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 */
- uiItemR(col, &driver_ptr, "expression", 0, IFACE_("Expr"), ICON_NONE);
-
+ /* 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 ((G.f & G_SCRIPT_AUTOEXEC) == 0) {
- uiItemL(col, IFACE_("ERROR: Python auto-execution disabled"), ICON_CANCEL);
+ /* TODO: Add button to enable? */
+ uiItemL(col, IFACE_("WARNING: Python expressions limited for security"), ICON_ERROR);
}
else if (driver->flag & DRIVER_FLAG_INVALID) {
uiItemL(col, IFACE_("ERROR: Invalid Python expression"), ICON_CANCEL);
}
-
+
/* 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);
}
@@ -803,9 +822,12 @@ static void graph_panel_drivers(const bContext *C, Panel *pa)
}
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
@@ -814,128 +836,122 @@ static void graph_panel_drivers(const bContext *C, Panel *pa)
*/
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);
}
}
}
-
- col = uiLayoutColumn(pa->layout, true);
- if (driver->type == DRIVER_TYPE_PYTHON) {
- uiItemR(col, &driver_ptr, "use_self", 0, NULL, ICON_NONE);
- }
+ uiItemS(layout);
- /* debug setting */
- uiItemR(col, &driver_ptr, "show_debug_info", 0, NULL, ICON_NONE);
-
- /* value of driver */
- if (driver->flag & DRIVER_FLAG_SHOWDEBUG) {
- uiLayout *row = uiLayoutRow(col, true);
- char valBuf[32];
-
- uiItemL(row, IFACE_("Driver Value:"), ICON_NONE);
-
- BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", driver->curval);
- uiItemL(row, valBuf, ICON_NONE);
- }
-
/* add/copy/paste driver variables */
- {
- uiLayout *row;
-
+ 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_ZOOMIN, 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(pa->layout, false);
+ row = uiLayoutRow(layout, false);
block = uiLayoutGetBlock(row);
- but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ZOOMIN, IFACE_("Add 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 and that drivers will update correctly"));
+ but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ZOOMIN, 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, eusuring 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, *row;
+ uiLayout *box;
uiLayout *subrow, *sub;
-
+
/* sub-layout column for this variable's settings */
- col = uiLayoutColumn(pa->layout, true);
-
+ col = uiLayoutColumn(layout, true);
+
/* 1) header panel */
box = uiLayoutBox(col);
- RNA_pointer_create(ale->id, &RNA_DriverVariable, dvar, &dvar_ptr);
-
+ 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 */
sub = uiLayoutRow(subrow, true); /* HACK: special group just for the enum, otherwise we */
uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT); /* we get ugly layout with text included too... */
-
+
uiItemR(sub, &dvar_ptr, "type", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
-
+
/* 1.1.2) variable name */
sub = uiLayoutRow(subrow, true); /* HACK: special group to counteract the effects of the previous */
uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_EXPAND); /* enum, which now pushes everything too far right */
-
+
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, ale->id, dvar);
+ graph_panel_driverVar__singleProp(box, id, dvar);
break;
case DVAR_TYPE_ROT_DIFF: /* rotational difference */
- graph_panel_driverVar__rotDiff(box, ale->id, dvar);
+ graph_panel_driverVar__rotDiff(box, id, dvar);
break;
case DVAR_TYPE_LOC_DIFF: /* location difference */
- graph_panel_driverVar__locDiff(box, ale->id, dvar);
+ graph_panel_driverVar__locDiff(box, id, dvar);
break;
case DVAR_TYPE_TRANSFORM_CHAN: /* transform channel */
- graph_panel_driverVar__transChan(box, ale->id, dvar);
+ graph_panel_driverVar__transChan(box, id, dvar);
break;
}
-
+
/* 3) value of variable */
- if (driver->flag & DRIVER_FLAG_SHOWDEBUG) {
+ {
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 &&
@@ -946,15 +962,113 @@ static void graph_panel_drivers(const bContext *C, Panel *pa)
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;
+
+ if (!graph_panel_context(C, &ale, &fcu))
+ return;
+
+ graph_draw_driven_property_panel(pa->layout, ale->id, fcu);
+
+ MEM_freeN(ale);
+}
+
+/* driver settings for active F-Curve (only for 'Drivers' mode in Graph Editor, i.e. the full "Drivers Editor") */
+static void graph_panel_drivers(const bContext *C, Panel *pa)
+{
+ bAnimListElem *ale;
+ FCurve *fcu;
+
+ /* Get settings from context */
+ if (!graph_panel_context(C, &ale, &fcu))
+ return;
+
+ graph_draw_driver_settings_panel(pa->layout, ale->id, fcu, false);
+
/* cleanup */
MEM_freeN(ale);
}
+/* ----------------------------------------------------------------- */
+
+/* poll to make this not show up in the graph editor, as this is only to be used as a popup elsewhere */
+static int graph_panel_drivers_popover_poll(const bContext *C, PanelType *UNUSED(pt))
+{
+ 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");
+}
+
/* ******************* F-Modifiers ******************************** */
/* All the drawing code is in editors/animation/fmodifier_ui.c */
@@ -969,7 +1083,7 @@ static void do_graph_region_modifier_buttons(bContext *C, void *UNUSED(arg), int
}
}
-static void graph_panel_modifiers(const bContext *C, Panel *pa)
+static void graph_panel_modifiers(const bContext *C, Panel *pa)
{
bAnimListElem *ale;
FCurve *fcu;
@@ -977,37 +1091,37 @@ static void graph_panel_modifiers(const bContext *C, Panel *pa)
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...
+
+ /* 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->id, &fcu->modifiers, fcm);
}
-
+
MEM_freeN(ale);
}
@@ -1025,7 +1139,7 @@ void graph_buttons_register(ARegionType *art)
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"));
@@ -1035,16 +1149,33 @@ void graph_buttons_register(ARegionType *art)
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_("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);
+
pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel modifiers");
strcpy(pt->idname, "GRAPH_PT_modifiers");
strcpy(pt->label, N_("Modifiers"));
@@ -1053,7 +1184,7 @@ void graph_buttons_register(ARegionType *art)
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"));
@@ -1067,7 +1198,7 @@ static int graph_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = graph_has_buttons_region(sa);
-
+
if (ar)
ED_region_toggle_hidden(C, ar);
@@ -1076,10 +1207,10 @@ static int graph_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
void GRAPH_OT_properties(wmOperatorType *ot)
{
- ot->name = "Properties";
+ 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;
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index 26a3f110d36..87fe4a62343 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -51,6 +51,7 @@
#include "GPU_draw.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "ED_anim_api.h"
@@ -63,7 +64,7 @@
/* *************************** */
/* Utility Drawing Defines */
-/* determine the alpha value that should be used when
+/* determine the alpha value that should be used when
* drawing components for some F-Curve (fcu)
* - selected F-Curves should be more visible than partially visible ones
*/
@@ -87,12 +88,12 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d)
const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
immUniform1i("num_colors", 0); /* Simple dashes. */
@@ -114,7 +115,7 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d)
if (env->totvert > 0) {
/* set size of vertices (non-adjustable for now) */
- glPointSize(2.0f);
+ GPU_point_size(2.0f);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -175,14 +176,14 @@ static void draw_fcurve_selected_keyframe_vertices(FCurve *fcu, View2D *v2d, boo
BezTriple *bezt = fcu->bezt;
for (int i = 0; i < fcu->totvert; i++, bezt++) {
- /* as an optimization step, only draw those in view
+ /* 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]);
@@ -273,7 +274,7 @@ static void draw_fcurve_vertices(ARegion *ar, FCurve *fcu, bool do_handles, bool
{
View2D *v2d = &ar->v2d;
- /* only draw points if curve is visible
+ /* 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)
@@ -281,7 +282,7 @@ static void draw_fcurve_vertices(ARegion *ar, FCurve *fcu, bool do_handles, bool
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- glEnable(GL_BLEND);
+ 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) */
@@ -293,7 +294,7 @@ static void draw_fcurve_vertices(ARegion *ar, FCurve *fcu, bool do_handles, bool
draw_fcurve_keyframe_vertices(fcu, v2d, !(fcu->flag & FCURVE_PROTECTED), pos);
GPU_disable_program_point_size();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
/* Handles ---------------- */
@@ -330,7 +331,7 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu)
immBeginAtMost(GWN_PRIM_LINES, 4 * 2 * fcu->totvert);
- /* slightly hacky, but we want to draw unselected points before selected ones
+ /* 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++) {
@@ -340,18 +341,18 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu)
unsigned char col[4];
for (b = 0; b < fcu->totvert; b++, prevbezt = bezt, bezt++) {
- /* if only selected keyframes can get their handles shown,
+ /* 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);
@@ -361,7 +362,7 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu)
immAttrib4ubv(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);
@@ -385,7 +386,7 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu)
immAttrib4ubv(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))
@@ -408,8 +409,8 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu)
/* Samples ---------------- */
-/* helper func - draw sample-range marker for an F-Curve as a cross
- * NOTE: the caller MUST HAVE GL_LINE_SMOOTH & GL_BLEND ENABLED, otherwise, the controls don't
+/* helper func - draw sample-range marker for an F-Curve as a cross
+ * 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)
@@ -437,20 +438,20 @@ static void draw_fcurve_samples(SpaceIpo *sipo, ARegion *ar, FCurve *fcu)
{
FPoint *first, *last;
float hsize, xscale, yscale;
-
+
/* get view settings */
hsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
UI_view2d_scale_get(&ar->v2d, &xscale, &yscale);
-
+
/* 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) glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
+ if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) GPU_line_smooth(true);
+ GPU_blend(true);
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -462,8 +463,8 @@ static void draw_fcurve_samples(SpaceIpo *sipo, ARegion *ar, FCurve *fcu)
immUnbindProgram();
- glDisable(GL_BLEND);
- if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glDisable(GL_LINE_SMOOTH);
+ GPU_blend(false);
+ if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) GPU_line_smooth(false);
}
}
@@ -491,10 +492,10 @@ static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d
/* disable any drivers temporarily */
driver = fcu->driver;
fcu->driver = NULL;
-
+
/* compute unit correction factor */
unitFac = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, 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,
@@ -510,10 +511,10 @@ static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d
/* 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)!
@@ -529,15 +530,15 @@ static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d
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
+
+
+ /* 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
*/
@@ -584,11 +585,11 @@ static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, Vie
gpuTranslate2f(0.0f, offset);
immBegin(GWN_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 */
@@ -600,26 +601,26 @@ static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, Vie
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 */
@@ -632,29 +633,29 @@ static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, Vie
if (fac) fac = 1.0f / fac;
v[1] = prevfpt->vec[1] - fac * (prevfpt->vec[1] - fpt->vec[1]);
}
-
+
immVertex2fv(shdr_pos, v);
}
-
+
immEnd();
gpuPopMatrix();
}
-/* helper func - check if the F-Curve only contains easily drawable segments
- * (i.e. no easing equation interpolations)
+/* helper func - check if the F-Curve only contains easily drawable segments
+ * (i.e. no easing equation interpolations)
*/
static bool fcurve_can_use_simple_bezt_drawing(FCurve *fcu)
{
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;
}
}
-
+
return true;
}
@@ -670,7 +671,7 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
int resol;
float unit_scale, offset;
short mapping_flag = ANIM_get_normalization_flags(ac);
-
+
/* apply unit mapping */
gpuPushMatrix();
unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
@@ -681,12 +682,12 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
* bezier interpolation, and are drawn at full res.
* This is tricky to optimize, but maybe can be improved at some point... */
immBeginAtMost(GWN_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 */
@@ -704,17 +705,17 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
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--) {
@@ -723,7 +724,7 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
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);
@@ -735,10 +736,10 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
immVertex2fv(pos, v1);
}
else if (prevbezt->ipo == BEZT_IPO_BEZ) {
- /* Bezier-Interpolation: draw curve as series of segments between keyframes
+ /* 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) {
@@ -747,7 +748,7 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
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];
@@ -758,32 +759,32 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
/* 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];
@@ -791,11 +792,11 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
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 */
@@ -814,10 +815,10 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
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();
gpuPopMatrix();
@@ -825,10 +826,10 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
/* Debugging -------------------------------- */
-/* Draw indicators which show the value calculated from the driver,
+/* Draw indicators which show the value calculated from the driver,
* and how this is mapped to the value that comes out of it. This
* is handy for helping users better understand how to interpret
- * the graphs, and also facilitates debugging.
+ * the graphs, and also facilitates debugging.
*/
static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
{
@@ -837,7 +838,7 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
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;
@@ -846,25 +847,25 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
immUniform1i("num_colors", 0); /* Simple dashes. */
/* No curve to modify/visualize the result?
- * => We still want to show the 1-1 default...
+ * => 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);
-
+
immUniform1f("dash_width", 40.0f);
immUniform1f("dash_factor", 0.5f);
- glLineWidth(2.0f);
-
- /* draw 1-1 line, stretching just past the screen limits
+ 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(GWN_PRIM_LINES, 2);
@@ -877,17 +878,17 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
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;
-
+
/* 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);
@@ -916,7 +917,7 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
immVertex2fv(shdr_pos, co);
immEnd();
-
+
immUnbindProgram();
/* GWN_PRIM_POINTS do not survive dashed line geometry shader... */
@@ -925,16 +926,16 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
/* x marks the spot .................................................... */
/* -> outer frame */
immUniformColor3f(0.9f, 0.9f, 0.9f);
- glPointSize(7.0);
-
+ GPU_point_size(7.0);
+
immBegin(GWN_PRIM_POINTS, 1);
immVertex2f(shdr_pos, x, y);
immEnd();
-
+
/* inner frame */
immUniformColor3f(0.9f, 0.0f, 0.0f);
- glPointSize(3.0);
-
+ GPU_point_size(3.0);
+
immBegin(GWN_PRIM_POINTS, 1);
immVertex2f(shdr_pos, x, y);
immEnd();
@@ -946,28 +947,28 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
/* Public Curve-Drawing API ---------------- */
-/* Draw the 'ghost' F-Curves (i.e. snapshots of the curve)
+/* Draw the 'ghost' F-Curves (i.e. snapshots of the curve)
* NOTE: unit mapping has already been applied to the values, so do not try and apply again
*/
void graph_draw_ghost_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar)
{
FCurve *fcu;
-
+
/* draw with thick dotted lines */
- glLineWidth(3.0f);
-
+ GPU_line_width(3.0f);
+
/* anti-aliased lines for less jagged appearance */
if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
- glEnable(GL_LINE_SMOOTH);
+ GPU_line_smooth(true);
}
- glEnable(GL_BLEND);
+ GPU_blend(true);
const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
immUniform1i("num_colors", 0); /* Simple dashes. */
@@ -976,12 +977,12 @@ void graph_draw_ghost_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar)
/* the ghost curves are simply sampled F-Curves stored in sipo->ghostCurves */
for (fcu = sipo->ghostCurves.first; fcu; fcu = fcu->next) {
- /* set whatever color the curve has set
+ /* 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);
}
@@ -989,9 +990,9 @@ void graph_draw_ghost_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar)
immUnbindProgram();
if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
- glDisable(GL_LINE_SMOOTH);
+ GPU_line_smooth(false);
}
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
/* This is called twice from space_graph.c -> graph_main_region_draw()
@@ -1002,21 +1003,21 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
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
+ * 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);
@@ -1028,7 +1029,7 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
* - 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)))
@@ -1036,24 +1037,24 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
/* 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) {
- glLineWidth(2.5);
+ GPU_line_width(2.5);
}
else {
- glLineWidth(1.0);
+ GPU_line_width(1.0);
}
-
+
/* anti-aliased lines for less jagged appearance */
if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
- glEnable(GL_LINE_SMOOTH);
+ GPU_line_smooth(true);
}
- glEnable(GL_BLEND);
+ GPU_blend(true);
const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
immUniform1i("num_colors", 0); /* Simple dashes. */
@@ -1081,8 +1082,8 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
/* 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 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);
}
@@ -1104,12 +1105,12 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
immUnbindProgram();
if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
- glDisable(GL_LINE_SMOOTH);
+ GPU_line_smooth(false);
}
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
-
- /* 2) draw handles and vertices as appropriate based on active
+
+ /* 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)) {
@@ -1127,46 +1128,46 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
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 */
gpuPushMatrix();
gpuScale2f(1.0f, unit_scale);
gpuTranslate2f(0.0f, offset);
-
+
/* set this once and for all - all handles and handle-verts should use the same thickness */
- glLineWidth(1.0);
-
+ 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 */
- glEnable(GL_BLEND);
+ GPU_blend(true);
draw_fcurve_handles(sipo, fcu);
- glDisable(GL_BLEND);
+ 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);
}
-
+
gpuPopMatrix();
}
}
-
+
/* 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);
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
}
-
+
/* free list of curves */
ANIM_animdata_freelist(&anim_data);
}
@@ -1175,40 +1176,40 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
/* Channel List */
/* left hand part */
-void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
+void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *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
+ * - 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) )
@@ -1216,7 +1217,7 @@ void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
/* 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++;
@@ -1225,17 +1226,17 @@ void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
{ /* 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 */
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
-
+ 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) )
@@ -1243,18 +1244,18 @@ void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
/* draw all channels using standard channel-drawing API */
ANIM_channel_draw_widgets(C, ac, ale, block, yminc, ymaxc, channel_index);
}
-
+
/* adjust y-position for next one */
y -= ACHANNEL_STEP(ac);
channel_index++;
}
-
+
UI_block_end(C, block);
UI_block_draw(C, block);
-
- glDisable(GL_BLEND);
+
+ 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 29e3f99e1d4..26a6e93ba57 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -54,10 +54,11 @@
#include "BLT_translation.h"
+#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
+#include "BKE_main.h"
#include "BKE_nla.h"
-#include "BKE_context.h"
#include "BKE_report.h"
#include "DEG_depsgraph_build.h"
@@ -83,36 +84,36 @@
/* 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,
+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);
@@ -122,24 +123,24 @@ void get_graph_keyframe_extents(bAnimContext *ac, float *xmin, float *xmax, floa
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)) {
@@ -157,7 +158,7 @@ void get_graph_keyframe_extents(bAnimContext *ac, float *xmin, float *xmax, floa
if (ymin) *ymin = -5;
if (ymax) *ymax = 5;
}
-
+
/* free memory */
ANIM_animdata_freelist(&anim_data);
}
@@ -171,7 +172,7 @@ void get_graph_keyframe_extents(bAnimContext *ac, float *xmin, float *xmax, floa
if (xmin) *xmin = -5;
if (xmax) *xmax = 100;
}
-
+
if (ymin) *ymin = -5;
if (ymax) *ymax = 5;
}
@@ -184,7 +185,7 @@ static int graphkeys_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;
@@ -192,31 +193,31 @@ static int graphkeys_previewrange_exec(bContext *C, wmOperator *UNUSED(op))
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 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 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";
-
+
/* 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;
}
@@ -228,11 +229,11 @@ static int graphkeys_viewall(bContext *C, const bool do_sel_only, const bool inc
{
bAnimContext ac;
rctf cur_new;
-
+
/* 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,
@@ -240,9 +241,9 @@ static int graphkeys_viewall(bContext *C, const bool do_sel_only, const bool inc
do_sel_only, include_handles);
BLI_rctf_scale(&cur_new, 1.1f);
-
+
UI_view2d_smooth_view(C, ac.ar, &cur_new, smooth_viewtx);
-
+
return OPERATOR_FINISHED;
}
@@ -252,16 +253,16 @@ 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);
-
+
/* 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);
-
+
/* only selected */
return graphkeys_viewall(C, true, include_handles, smooth_viewtx);
}
@@ -274,16 +275,16 @@ void GRAPH_OT_view_all(wmOperatorType *ot)
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;
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;
-
+
/* props */
- ot->prop = RNA_def_boolean(ot->srna, "include_handles", true, "Include Handles",
+ ot->prop = RNA_def_boolean(ot->srna, "include_handles", true, "Include Handles",
"Include handles of keyframes when calculating extents");
}
@@ -300,9 +301,9 @@ void GRAPH_OT_view_selected(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* props */
- ot->prop = RNA_def_boolean(ot->srna, "include_handles", true, "Include Handles",
+ ot->prop = RNA_def_boolean(ot->srna, "include_handles", true, "Include Handles",
"Include handles of keyframes when calculating extents");
}
@@ -321,11 +322,11 @@ void GRAPH_OT_view_frame(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -337,25 +338,25 @@ 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)
-{
+{
SpaceIpo *sipo = (SpaceIpo *)ac->sl;
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
-
+
/* free existing ghost curves */
free_fcurves(&sipo->ghostCurves);
-
+
/* 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;
@@ -366,41 +367,41 @@ static void create_ghost_curves(bAnimContext *ac, int start, int end)
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
+
+ /* 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
+
+ /* 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->ghostCurves, gcu);
-
+
/* restore driver */
fcu->driver = driver;
}
-
+
/* admin and redraws */
ANIM_animdata_freelist(&anim_data);
}
@@ -412,39 +413,39 @@ static int graphkeys_create_ghostcurves_exec(bContext *C, wmOperator *UNUSED(op)
bAnimContext ac;
View2D *v2d;
int start, end;
-
+
/* 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;
-
+
/* 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));
-
+
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";
-
+
/* api callbacks */
ot->exec = graphkeys_create_ghostcurves_exec;
ot->poll = graphop_visible_keyframes_poll;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
// todo: add props for start/end frames
}
@@ -455,36 +456,36 @@ static int graphkeys_clear_ghostcurves_exec(bContext *C, wmOperator *UNUSED(op))
{
bAnimContext ac;
SpaceIpo *sipo;
-
+
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
sipo = (SpaceIpo *)ac.sl;
-
+
/* if no ghost curves, don't do anything */
if (BLI_listbase_is_empty(&sipo->ghostCurves))
return OPERATOR_CANCELLED;
-
+
/* free ghost curves */
free_fcurves(&sipo->ghostCurves);
-
+
/* update this editor only */
ED_area_tag_redraw(CTX_wm_area(C));
-
+
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";
-
+
/* api callbacks */
ot->exec = graphkeys_clear_ghostcurves_exec;
ot->poll = ED_operator_graphedit_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -517,26 +518,27 @@ static const EnumPropertyItem prop_graphkeys_insertkey_types[] = {
};
/* this function is responsible for snapping keyframes to frame-times */
-static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode)
+static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
size_t num_items;
-
+
ReportList *reports = ac->reports;
SpaceIpo *sipo = (SpaceIpo *)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)
@@ -545,26 +547,26 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode)
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;
@@ -572,16 +574,16 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode)
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;
}
}
@@ -590,15 +592,15 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode)
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
FCurve *fcu = (FCurve *)ale->key_data;
float cfra;
-
+
/* 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);
- else
+ else
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,
@@ -608,17 +610,18 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode)
* up adding the keyframes on a new F-Curve in the action data instead.
*/
if (ale->id && !ale->owner && !fcu->driver) {
- insert_keyframe(reports, ale->id, NULL, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, ts->keyframe_type, flag);
+ 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, flag);
}
else {
const float curval = evaluate_fcurve(fcu, cfra);
insert_vert_fcurve(fcu, cfra, curval, ts->keyframe_type, 0);
}
-
+
ale->update |= ANIM_UPDATE_DEFAULT;
}
}
-
+
ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
@@ -629,20 +632,20 @@ static int graphkeys_insertkey_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
eGraphKeys_InsertKey_Types mode;
-
+
/* 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");
-
+
/* 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);
-
+
return OPERATOR_FINISHED;
}
@@ -652,15 +655,15 @@ void GRAPH_OT_keyframe_insert(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* id-props */
ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_insertkey_types, 0, "Type", "");
}
@@ -674,11 +677,11 @@ static int graphkeys_click_insert_exec(bContext *C, wmOperator *op)
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)) {
@@ -686,17 +689,17 @@ static int graphkeys_click_insert_exec(bContext *C, wmOperator *op)
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)
@@ -704,28 +707,28 @@ static int graphkeys_click_insert_exec(bContext *C, wmOperator *op)
*/
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 {
@@ -737,13 +740,13 @@ static int graphkeys_click_insert_exec(bContext *C, wmOperator *op)
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;
}
@@ -755,23 +758,23 @@ static int graphkeys_click_insert_invoke(bContext *C, wmOperator *op, const wmEv
View2D *v2d;
int mval[2];
float x, y;
-
+
/* 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;
-
+
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);
-
+
RNA_float_set(op->ptr, "frame", x);
RNA_float_set(op->ptr, "value", y);
-
+
/* run exec now */
return graphkeys_click_insert_exec(C, op);
}
@@ -782,19 +785,19 @@ void GRAPH_OT_click_insert(wmOperatorType *ot)
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");
}
@@ -802,20 +805,20 @@ void GRAPH_OT_click_insert(wmOperatorType *ot)
/* NOTE: the backend code for this is shared with the dopesheet editor */
static short copy_graph_keys(bAnimContext *ac)
-{
+{
ListBase anim_data = {NULL, NULL};
int filter, ok = 0;
-
+
/* 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);
-
+
/* copy keyframes */
ok = copy_animedit_keys(ac, &anim_data);
-
+
/* clean up */
ANIM_animdata_freelist(&anim_data);
@@ -824,21 +827,21 @@ static short copy_graph_keys(bAnimContext *ac)
static short paste_graph_keys(bAnimContext *ac,
const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode, bool flip)
-{
+{
ListBase anim_data = {NULL, NULL};
int filter, ok = 0;
-
- /* filter data
- * - First time we try to filter more strictly, allowing only selected channels
+
+ /* 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);
-
+
/* paste keyframes */
ok = paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode, flip);
@@ -853,32 +856,32 @@ static short paste_graph_keys(bAnimContext *ac,
static int graphkeys_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 (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;
}
-
+
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";
-
+
/* api callbacks */
ot->exec = graphkeys_copy_exec;
ot->poll = graphop_editable_keyframes_poll;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -892,11 +895,11 @@ static int graphkeys_paste_exec(bContext *C, wmOperator *op)
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;
@@ -904,30 +907,30 @@ static int graphkeys_paste_exec(bContext *C, wmOperator *op)
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);
-
+
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");
@@ -942,11 +945,11 @@ static void duplicate_graph_keys(bAnimContext *ac)
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);
-
+
/* loop through filtered data and delete selected keys */
for (ale = anim_data.first; ale; ale = ale->next) {
duplicate_fcurve_keys((FCurve *)ale->key_data);
@@ -963,17 +966,17 @@ static void duplicate_graph_keys(bAnimContext *ac)
static int graphkeys_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
{
bAnimContext ac;
-
+
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
+
/* duplicate keyframes */
duplicate_graph_keys(&ac);
-
+
/* set notifier that keyframes have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -983,14 +986,14 @@ void GRAPH_OT_duplicate(wmOperatorType *ot)
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;
-
+
/* 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", "");
}
@@ -1003,17 +1006,17 @@ static bool delete_graph_keys(bAnimContext *ac)
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);
-
+
/* 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);
@@ -1021,7 +1024,7 @@ static bool delete_graph_keys(bAnimContext *ac)
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) &&
@@ -1043,33 +1046,33 @@ static bool delete_graph_keys(bAnimContext *ac)
static int graphkeys_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
bAnimContext ac;
-
+
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
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);
-
+
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";
-
+
/* 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;
}
@@ -1077,15 +1080,15 @@ void GRAPH_OT_delete(wmOperatorType *ot)
/* ******************** Clean Keyframes Operator ************************* */
static void clean_graph_keys(bAnimContext *ac, float thresh, bool clean_chan)
-{
+{
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);
-
+
/* loop through filtered data and clean curves */
for (ale = anim_data.first; ale; ale = ale->next) {
clean_fcurve(ac, ale, thresh, clean_chan);
@@ -1104,38 +1107,38 @@ static int graphkeys_clean_exec(bContext *C, wmOperator *op)
bAnimContext ac;
float thresh;
bool clean_chan;
-
+
/* 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);
-
+
/* set notifier that keyframes have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
-
+
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";
-
+
/* api callbacks */
- //ot->invoke = // XXX we need that number popup for this!
+ //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;
-
+
/* 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", "");
@@ -1146,26 +1149,26 @@ 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;
-
+
/* 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;
-
+
/* 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);
-
+
/* restore driver */
fcu->driver = driver;
@@ -1183,42 +1186,42 @@ static int graphkeys_bake_exec(bContext *C, wmOperator *UNUSED(op))
bAnimContext ac;
Scene *scene = NULL;
int start, end;
-
+
/* 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
+ // TODO: add properties for this
scene = ac.scene;
start = PSFRA;
end = PEFRA;
-
+
/* 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);
-
+
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";
-
+
/* api callbacks */
ot->invoke = WM_operator_confirm; // FIXME...
ot->exec = graphkeys_bake_exec;
- ot->poll = graphop_selected_fcurve_poll;
-
+ ot->poll = graphop_selected_fcurve_poll;
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
// todo: add props for start/end frames
}
@@ -1311,7 +1314,7 @@ static int graphkeys_sound_bake_exec(bContext *C, wmOperator *op)
/* 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);
@@ -1402,15 +1405,15 @@ 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;
-
+
/* 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);
@@ -1427,31 +1430,31 @@ static void sample_graph_keys(bAnimContext *ac)
static int graphkeys_sample_exec(bContext *C, wmOperator *UNUSED(op))
{
bAnimContext ac;
-
+
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
+
/* sample keyframes */
sample_graph_keys(&ac);
-
+
/* set notifier that keyframes have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
-
+
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";
-
+
/* api callbacks */
ot->exec = graphkeys_sample_exec;
ot->poll = graphop_editable_keyframes_poll;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1470,27 +1473,27 @@ void GRAPH_OT_sample(wmOperatorType *ot)
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}
};
/* this function is responsible for setting extrapolation mode for keyframes */
-static void setexpo_graph_keys(bAnimContext *ac, short mode)
+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;
@@ -1498,7 +1501,7 @@ static void setexpo_graph_keys(bAnimContext *ac, short mode)
ale->update |= ANIM_UPDATE_HANDLES;
}
else {
- /* shortcuts for managing Cycles F-Modifiers to make it easier to toggle cyclic animation
+ /* 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) {
@@ -1511,10 +1514,10 @@ static void setexpo_graph_keys(bAnimContext *ac, short mode)
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);
}
@@ -1534,38 +1537,38 @@ static int graphkeys_expo_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
short mode;
-
+
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
+
/* get handle setting mode */
mode = RNA_enum_get(op->ptr, "type");
-
+
/* set handle type */
setexpo_graph_keys(&ac, mode);
-
+
/* set notifier that keyframe properties have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
-
+
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";
-
+
/* 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;
-
+
/* id-props */
ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_expo_types, 0, "Type", "");
}
@@ -1573,17 +1576,17 @@ void GRAPH_OT_extrapolation_type(wmOperatorType *ot)
/* ******************** Set Interpolation-Type Operator *********************** */
/* this function is responsible for setting interpolation mode for keyframes */
-static void setipo_graph_keys(bAnimContext *ac, short mode)
+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);
-
+
/* 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...
*/
@@ -1603,38 +1606,38 @@ static int graphkeys_ipo_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
short mode;
-
+
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
+
/* get handle setting mode */
mode = RNA_enum_get(op->ptr, "type");
-
+
/* set handle type */
setipo_graph_keys(&ac, mode);
-
+
/* set notifier that keyframe properties have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
-
+
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";
-
+
/* 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;
-
+
/* id-props */
ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_beztriple_interpolation_mode_items, 0, "Type", "");
}
@@ -1647,11 +1650,11 @@ static void seteasing_graph_keys(bAnimContext *ac, short mode)
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);
-
+
/* loop through setting BezTriple easing
* Note: we do not supply KeyframeEditData to the looper yet. Currently that's not necessary here...
*/
@@ -1669,20 +1672,20 @@ static int graphkeys_easing_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
short mode;
-
+
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
+
/* get handle setting mode */
mode = RNA_enum_get(op->ptr, "type");
-
+
/* set handle type */
seteasing_graph_keys(&ac, mode);
-
+
/* set notifier that keyframe properties have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -1692,15 +1695,15 @@ void GRAPH_OT_easing_type(wmOperatorType *ot)
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;
-
+
/* 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", "");
}
@@ -1708,25 +1711,25 @@ void GRAPH_OT_easing_type(wmOperatorType *ot)
/* ******************** Set Handle-Type Operator *********************** */
/* this function is responsible for setting handle-type of selected keyframes */
-static void sethandles_graph_keys(bAnimContext *ac, short mode)
+static void sethandles_graph_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_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* loop through setting flags for handles
+
+ /* 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 */
@@ -1745,38 +1748,38 @@ static int graphkeys_handletype_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
short mode;
-
+
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
+
/* get handle setting mode */
mode = RNA_enum_get(op->ptr, "type");
-
+
/* set handle type */
sethandles_graph_keys(&ac, mode);
-
+
/* set notifier that keyframe properties have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
-
+
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";
-
+
/* 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;
-
+
/* id-props */
ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_keyframe_handle_type_items, 0, "Type", "");
}
@@ -1794,43 +1797,43 @@ void GRAPH_OT_handle_type(wmOperatorType *ot)
/* set of three euler-rotation F-Curves */
typedef struct tEulerFilter {
struct tEulerFilter *next, *prev;
-
+
ID *id; /* ID-block which owns the channels */
FCurve *(fcurves[3]); /* 3 Pointers to F-Curves */
const char *rna_path; /* Pointer to one of the RNA Path's used by one of the F-Curves */
} 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
+
+ /* check if this is an appropriate F-Curve
* - only rotation curves
* - for pchan curves, make sure we're only using the euler curves
*/
@@ -1842,9 +1845,9 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op)
(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
+ * 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))) {
@@ -1856,7 +1859,7 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op)
euf = MEM_callocN(sizeof(tEulerFilter), "tEulerFilter");
BLI_addtail(&eulers, euf);
groups++;
-
+
euf->id = ale->id;
euf->rna_path = fcu->rna_path; /* this should be safe, since we're only using it for a short time */
euf->fcurves[fcu->array_index] = fcu;
@@ -1870,13 +1873,13 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op)
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
+
+ /* 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])) {
@@ -1887,7 +1890,7 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op)
(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;
@@ -1899,21 +1902,21 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op)
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;
@@ -1924,13 +1927,13 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op)
}
}
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,
+ 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;
@@ -1942,15 +1945,15 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op)
"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 */
@@ -1959,11 +1962,11 @@ void GRAPH_OT_euler_filter(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1987,18 +1990,18 @@ static int graphkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op))
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);
@@ -2009,9 +2012,9 @@ static int graphkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op))
memset(&current_ked, 0, sizeof(current_ked));
if (adt) {
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
+ 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);
+ 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);
@@ -2021,14 +2024,14 @@ static int graphkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op))
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) {
SpaceIpo *sipo = (SpaceIpo *)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) */
@@ -2042,10 +2045,10 @@ static int graphkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op))
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;
}
@@ -2055,11 +2058,11 @@ void GRAPH_OT_frame_jump(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -2084,23 +2087,23 @@ static const EnumPropertyItem prop_graphkeys_snap_types[] = {
};
/* this function is responsible for snapping keyframes to frame-times */
-static void snap_graph_keys(bAnimContext *ac, short mode)
+static void snap_graph_keys(bAnimContext *ac, short mode)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
-
+
SpaceIpo *sipo = (SpaceIpo *)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));
+ memset(&ked, 0, sizeof(KeyframeEditData));
ked.scene = ac->scene;
if (mode == GRAPHKEYS_SNAP_NEAREST_MARKER) {
ked.list.first = (ac->markers) ? ac->markers->first : NULL;
@@ -2118,32 +2121,32 @@ static void snap_graph_keys(bAnimContext *ac, short mode)
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_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
+ else
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve);
-
+
ale->update |= ANIM_UPDATE_DEFAULT;
}
@@ -2157,38 +2160,38 @@ static int graphkeys_snap_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
short mode;
-
+
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
+
/* get snapping mode */
mode = RNA_enum_get(op->ptr, "type");
-
+
/* 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);
-
+
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";
-
+
/* 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;
-
+
/* id-props */
ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_snap_types, 0, "Type", "");
}
@@ -2211,28 +2214,28 @@ static const EnumPropertyItem prop_graphkeys_mirror_types[] = {
};
/* this function is responsible for mirroring keyframes */
-static void mirror_graph_keys(bAnimContext *ac, short mode)
+static void mirror_graph_keys(bAnimContext *ac, short mode)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
-
+
SpaceIpo *sipo = (SpaceIpo *)ac->sl;
KeyframeEditData ked;
KeyframeEditFunc edit_cb;
float cursor_value = 0.0f;
/* init custom data for looping over keyframes */
- memset(&ked, 0, sizeof(KeyframeEditData));
+ 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;
@@ -2251,36 +2254,36 @@ static void mirror_graph_keys(bAnimContext *ac, short mode)
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_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
+ else
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve);
-
+
ale->update |= ANIM_UPDATE_DEFAULT;
}
@@ -2294,38 +2297,38 @@ static int graphkeys_mirror_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
short mode;
-
+
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
+
/* get mirroring mode */
mode = RNA_enum_get(op->ptr, "type");
-
+
/* 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);
-
+
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";
-
+
/* 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;
-
+
/* id-props */
ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_mirror_types, 0, "Type", "");
}
@@ -2338,15 +2341,15 @@ static int graphkeys_smooth_exec(bContext *C, wmOperator *UNUSED(op))
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
-
+
/* 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);
-
+
/* smooth keyframes */
for (ale = anim_data.first; ale; ale = ale->next) {
/* For now, we can only smooth by flattening handles AND smoothing curve values.
@@ -2360,24 +2363,24 @@ static int graphkeys_smooth_exec(bContext *C, wmOperator *UNUSED(op))
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);
-
+
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";
-
+
/* api callbacks */
ot->exec = graphkeys_smooth_exec;
ot->poll = graphop_editable_keyframes_poll;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -2392,29 +2395,29 @@ static const EnumPropertyItem *graph_fmodifier_itemf(bContext *C, PointerRNA *UN
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;
-
+
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;
}
@@ -2425,14 +2428,14 @@ static int graph_fmodifier_add_exec(bContext *C, wmOperator *op)
bAnimListElem *ale;
int filter;
short type;
-
+
/* 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");
-
+
/* filter data */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
if (RNA_boolean_get(op->ptr, "only_active"))
@@ -2440,12 +2443,12 @@ static int graph_fmodifier_add_exec(bContext *C, wmOperator *op)
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 of specified type to active F-Curve, and make it the active one */
fcm = add_fmodifier(&fcu->modifiers, type, fcu);
if (fcm) {
@@ -2455,41 +2458,41 @@ static int graph_fmodifier_add_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "Modifier could not be added (see console for details)");
break;
}
-
+
ale->update |= ANIM_UPDATE_DEPS;
}
-
+
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);
-
+
return OPERATOR_FINISHED;
}
-
+
void GRAPH_OT_fmodifier_add(wmOperatorType *ot)
{
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";
-
+
/* api callbacks */
ot->invoke = WM_menu_invoke;
ot->exec = graph_fmodifier_add_exec;
- ot->poll = graphop_selected_fcurve_poll;
-
+ ot->poll = graphop_selected_fcurve_poll;
+
/* 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;
-
+
RNA_def_boolean(ot->srna, "only_active", 1, "Only Active", "Only add F-Modifier to active F-Curve");
}
@@ -2500,28 +2503,28 @@ static int graph_fmodifier_copy_exec(bContext *C, wmOperator *op)
bAnimContext ac;
bAnimListElem *ale;
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 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;
-
+
/* 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);
}
-
+
/* successful or not? */
if (ok == 0) {
BKE_report(op->reports, RPT_ERROR, "No F-Modifiers available to be copied");
@@ -2530,21 +2533,21 @@ static int graph_fmodifier_copy_exec(bContext *C, wmOperator *op)
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";
-
+
/* api callbacks */
ot->exec = graph_fmodifier_copy_exec;
- ot->poll = graphop_active_fcurve_poll;
-
+ ot->poll = graphop_active_fcurve_poll;
+
/* 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");
}
@@ -2554,18 +2557,18 @@ void GRAPH_OT_fmodifier_copy(wmOperatorType *ot)
static int graph_fmodifier_paste_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
-
+
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
-
+
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;
-
+
/* filter data */
if (RNA_boolean_get(op->ptr, "only_active")) {
/* This should be the default (for buttons) - Just paste to the active FCurve */
@@ -2575,32 +2578,32 @@ static int graph_fmodifier_paste_exec(bContext *C, wmOperator *op)
/* 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);
-
+
/* 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);
-
+
if (tot) {
ale->update |= ANIM_UPDATE_DEPS;
ok = true;
}
}
-
+
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);
-
+
return OPERATOR_FINISHED;
}
else {
@@ -2608,24 +2611,24 @@ static int graph_fmodifier_paste_exec(bContext *C, wmOperator *op)
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";
-
+
/* api callbacks */
ot->exec = graph_fmodifier_paste_exec;
ot->poll = graphop_active_fcurve_poll;
-
+
/* 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",
+ RNA_def_boolean(ot->srna, "replace", false, "Replace Existing",
"Replace existing F-Modifiers, instead of just appending to the end of the existing list");
}
@@ -2639,45 +2642,45 @@ static int graph_driver_vars_copy_exec(bContext *C, wmOperator *op)
bAnimContext ac;
bAnimListElem *ale;
bool ok = false;
-
+
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
+
/* clear buffer first */
ANIM_driver_vars_copybuf_free();
-
+
/* 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;
-
+
ok = ANIM_driver_vars_copy(op->reports, fcu);
-
+
/* free temp data now */
MEM_freeN(ale);
}
-
+
/* 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";
-
+
/* api callbacks */
ot->exec = graph_driver_vars_copy_exec;
- ot->poll = graphop_active_fcurve_poll;
-
+ ot->poll = graphop_active_fcurve_poll;
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -2687,62 +2690,62 @@ void GRAPH_OT_driver_variables_copy(wmOperatorType *ot)
static int graph_driver_vars_paste_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
-
+
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
-
+
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;
-
+
/* 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);
}
-
+
/* 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));
-
+
/* 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;
}
}
-
+
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";
-
+
/* api callbacks */
ot->exec = graph_driver_vars_paste_exec;
ot->poll = graphop_active_fcurve_poll;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
- RNA_def_boolean(ot->srna, "replace", false, "Replace Existing",
+ RNA_def_boolean(ot->srna, "replace", false, "Replace Existing",
"Replace existing driver variables, instead of just appending to the end of the existing list");
}
diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h
index 6c375b23352..da352d4ea06 100644
--- a/source/blender/editors/space_graph/graph_intern.h
+++ b/source/blender/editors/space_graph/graph_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -87,7 +87,7 @@ enum eGraphKeys_ColumnSelect_Mode {
/* ***************************************** */
/* graph_edit.c */
-void get_graph_keyframe_extents(struct bAnimContext *ac, float *xmin, float *xmax, float *ymin, float *ymax,
+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);
@@ -119,7 +119,7 @@ void GRAPH_OT_frame_jump(struct wmOperatorType *ot);
void GRAPH_OT_snap(struct wmOperatorType *ot);
void GRAPH_OT_mirror(struct wmOperatorType *ot);
-/* defines for snap keyframes
+/* defines for snap keyframes
* NOTE: keep in sync with eEditKeyframes_Snap (in ED_keyframes_edit.h)
*/
enum eGraphKeys_Snap_Mode {
@@ -131,7 +131,7 @@ enum eGraphKeys_Snap_Mode {
GRAPHKEYS_SNAP_VALUE,
};
-/* defines for mirror keyframes
+/* defines for mirror keyframes
* NOTE: keep in sync with eEditKeyframes_Mirror (in ED_keyframes_edit.h)
*/
enum eGraphKeys_Mirror_Mode {
diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c
index 57d8f45905d..50e09b60b70 100644
--- a/source/blender/editors/space_graph/graph_ops.c
+++ b/source/blender/editors/space_graph/graph_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -83,19 +83,19 @@ static void graphview_cursor_apply(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
SpaceIpo *sipo = CTX_wm_space_graph(C);
float frame = RNA_float_get(op->ptr, "frame"); /* this isn't technically "frame", but it'll do... */
-
+
/* 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
+ /* 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,
@@ -107,14 +107,14 @@ static void graphview_cursor_apply(bContext *C, wmOperator *op)
/* 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);
}
@@ -135,14 +135,14 @@ static void graphview_cursor_setprops(bContext *C, wmOperator *op, const wmEvent
{
ARegion *ar = CTX_wm_region(C);
float viewx, viewy;
-
+
/* 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);
-
+
/* 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);
@@ -153,18 +153,18 @@ static void graphview_cursor_setprops(bContext *C, wmOperator *op, const wmEvent
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;
@@ -175,32 +175,32 @@ static int graphview_cursor_modal(bContext *C, wmOperator *op, const wmEvent *ev
{
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 LEFTMOUSE:
case RIGHTMOUSE:
case MIDDLEMOUSE:
- /* we check for either mouse-button to end, as checking for ACTIONMOUSE (which is used to init
+ /* we check for either mouse-button to end, as checking for ACTIONMOUSE (which is used to init
* the modal op) doesn't work for some reason
*/
if (event->val == KM_RELEASE) {
if (screen)
screen->scrubbing = false;
-
+
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
return OPERATOR_FINISHED;
}
@@ -216,13 +216,13 @@ static void GRAPH_OT_cursor_set(wmOperatorType *ot)
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;
@@ -241,39 +241,39 @@ static int graphview_curves_hide_exec(bContext *C, wmOperator *op)
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
+
+ /* 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)
+ * - 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);
}
@@ -281,7 +281,7 @@ static int graphview_curves_hide_exec(bContext *C, wmOperator *op)
/* cleanup */
ANIM_animdata_freelist(&anim_data);
BLI_freelistN(&all_data);
-
+
/* unhide selected */
if (unselected) {
/* turn off requirement for visible */
@@ -295,21 +295,21 @@ static int graphview_curves_hide_exec(bContext *C, wmOperator *op)
/* 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);
+ 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;
}
@@ -319,14 +319,14 @@ static void GRAPH_OT_hide(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* props */
RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected curves");
}
@@ -341,50 +341,50 @@ static int graphview_curves_reveal_exec(bContext *C, wmOperator *op)
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
+
+ /* 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;
}
@@ -394,11 +394,11 @@ static void GRAPH_OT_reveal(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -411,19 +411,19 @@ 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);
@@ -436,7 +436,7 @@ void graphedit_operatortypes(void)
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);
@@ -453,18 +453,18 @@ void graphedit_operatortypes(void)
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);
@@ -475,7 +475,7 @@ 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);
@@ -491,7 +491,7 @@ void ED_operatormacros_graph(void)
static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
{
wmKeyMapItem *kmi;
-
+
/* view */
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", HKEY, KM_PRESS, KM_CTRL, 0);
RNA_string_set(kmi->ptr, "data_path", "space_data.show_handles");
@@ -500,8 +500,8 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
* This keymap is supposed to override ANIM_OT_change_frame, which does the same except it doesn't do y-values
*/
WM_keymap_add_item(keymap, "GRAPH_OT_cursor_set", ACTIONMOUSE, KM_PRESS, 0, 0);
-
-
+
+
/* graph_select.c - selection tools */
/* click-select: keyframe (replace) */
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, 0, 0);
@@ -533,7 +533,7 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
RNA_boolean_set(kmi->ptr, "extend", true);
RNA_boolean_set(kmi->ptr, "curves", true);
RNA_boolean_set(kmi->ptr, "column", false);
-
+
/* click-select left/right */
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_leftright", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "extend", false);
@@ -541,20 +541,20 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_leftright", SELECTMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "extend", true);
RNA_enum_set(kmi->ptr, "mode", GRAPHKEYS_LRSEL_TEST);
-
+
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_leftright", LEFTBRACKETKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "extend", false);
RNA_enum_set(kmi->ptr, "mode", GRAPHKEYS_LRSEL_LEFT);
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_leftright", RIGHTBRACKETKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "extend", false);
RNA_enum_set(kmi->ptr, "mode", GRAPHKEYS_LRSEL_RIGHT);
-
+
/* deselect all */
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "invert", false);
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "invert", true);
-
+
/* borderselect */
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_border", BKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "axis_range", false);
@@ -562,68 +562,72 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_border", BKEY, KM_PRESS, KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "axis_range", true);
RNA_boolean_set(kmi->ptr, "include_handles", false);
-
+
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_border", BKEY, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "axis_range", false);
RNA_boolean_set(kmi->ptr, "include_handles", true);
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_border", BKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "axis_range", true);
RNA_boolean_set(kmi->ptr, "include_handles", true);
-
+
/* region select */
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "deselect", false);
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "deselect", true);
-
+
WM_keymap_add_item(keymap, "GRAPH_OT_select_circle", CKEY, KM_PRESS, 0, 0);
-
+
/* column select */
RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, 0, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_KEYS);
RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_CFRA);
RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN);
RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, KM_ALT, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN);
-
+
/* select more/less */
WM_keymap_add_item(keymap, "GRAPH_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "GRAPH_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
-
+
/* select linked */
WM_keymap_add_item(keymap, "GRAPH_OT_select_linked", LKEY, KM_PRESS, 0, 0);
-
-
+
+
/* graph_edit.c */
/* jump to selected keyframes */
WM_keymap_add_item(keymap, "GRAPH_OT_frame_jump", GKEY, KM_PRESS, KM_CTRL, 0);
-
+
/* menu + single-step transform */
WM_keymap_add_item(keymap, "GRAPH_OT_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "GRAPH_OT_mirror", MKEY, KM_PRESS, KM_SHIFT, 0);
-
+
WM_keymap_add_item(keymap, "GRAPH_OT_handle_type", VKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "GRAPH_OT_interpolation_type", TKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "GRAPH_OT_easing_type", EKEY, KM_PRESS, KM_CTRL, 0);
-
+
/* destructive */
WM_keymap_add_item(keymap, "GRAPH_OT_smooth", OKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "GRAPH_OT_sample", OKEY, KM_PRESS, KM_SHIFT, 0);
-
+
WM_keymap_add_item(keymap, "GRAPH_OT_bake", CKEY, KM_PRESS, KM_ALT, 0);
-
+
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_menu(keymap, "GRAPH_MT_delete", XKEY, KM_PRESS, 0, 0);
+#endif
WM_keymap_add_menu(keymap, "GRAPH_MT_delete", DELKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_menu(keymap, "GRAPH_MT_specials", WKEY, KM_PRESS, 0, 0);
+
WM_keymap_add_item(keymap, "GRAPH_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
-
+
/* insertkey */
WM_keymap_add_item(keymap, "GRAPH_OT_keyframe_insert", IKEY, KM_PRESS, 0, 0);
-
+
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_click_insert", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "extend", false);
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_click_insert", ACTIONMOUSE, KM_CLICK, KM_CTRL | KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "extend", true);
-
+
/* copy/paste */
WM_keymap_add_item(keymap, "GRAPH_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "GRAPH_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0);
@@ -648,16 +652,16 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
/* F-Modifiers */
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_fmodifier_add", MKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "only_active", false);
-
+
/* animation module */
/* channels list
* NOTE: these operators were originally for the channels list, but are added here too for convenience...
*/
WM_keymap_add_item(keymap, "ANIM_OT_channels_editable_toggle", TABKEY, KM_PRESS, 0, 0);
-
+
/* transform system */
transform_keymap_for_space(keyconf, keymap, SPACE_IPO);
-
+
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", OKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_proportional_fcurve");
@@ -665,15 +669,15 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
RNA_string_set(kmi->ptr, "value", "BOUNDING_BOX_CENTER");
-
+
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
RNA_string_set(kmi->ptr, "value", "CURSOR");
-
+
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM_PRESS, KM_CTRL, 0);
RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
RNA_string_set(kmi->ptr, "value", "INDIVIDUAL_ORIGINS");
-
+
/* special markers hotkeys for anim editors: see note in definition of this function */
ED_marker_keymap_animedit_conflictfree(keymap);
}
@@ -684,35 +688,34 @@ void graphedit_keymap(wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
wmKeyMapItem *kmi;
-
+
/* keymap for all regions */
keymap = WM_keymap_find(keyconf, "Graph Editor Generic", SPACE_IPO, 0);
WM_keymap_add_item(keymap, "GRAPH_OT_properties", NKEY, KM_PRESS, 0, 0);
-
+
/* extrapolation works on channels, not keys */
WM_keymap_add_item(keymap, "GRAPH_OT_extrapolation_type", EKEY, KM_PRESS, KM_SHIFT, 0);
-
+
/* find (i.e. a shortcut for setting the name filter) */
WM_keymap_add_item(keymap, "ANIM_OT_channels_find", FKEY, KM_PRESS, KM_CTRL, 0);
-
+
/* hide/reveal selected curves */
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_hide", HKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "unselected", false);
-
+
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "unselected", true);
-
+
WM_keymap_add_item(keymap, "GRAPH_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0);
-
-
+
+
/* channels */
- /* Channels are not directly handled by the Graph Editor module, but are inherited from the Animation module.
+ /* 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 */
keymap = WM_keymap_find(keyconf, "Graph Editor", SPACE_IPO, 0);
graphedit_keymap_keyframes(keyconf, keymap);
}
-
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index 0b7ce7d7310..9a6b733a5ff 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -77,7 +77,7 @@
* - This is called by the deselect all operator, as well as other ones!
*
* - test: check if select or deselect all
- * - sel: how to select keyframes
+ * - sel: how to select keyframes
* 0 = deselect
* 1 = select
* 2 = invert
@@ -88,20 +88,20 @@ void deselect_graph_keys(bAnimContext *ac, bool test, short sel, bool do_channel
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
-
+
SpaceIpo *sipo = (SpaceIpo *)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) {
@@ -111,17 +111,17 @@ void deselect_graph_keys(bAnimContext *ac, bool test, short sel, bool do_channel
}
}
}
-
+
/* 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 */
@@ -129,17 +129,17 @@ void deselect_graph_keys(bAnimContext *ac, bool test, short sel, bool do_channel
/* 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)
+ 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);
}
@@ -150,56 +150,56 @@ 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
+
+ /* 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 */
if (RNA_boolean_get(op->ptr, "invert"))
deselect_graph_keys(&ac, 0, SELECT_INVERT, true);
else
deselect_graph_keys(&ac, 1, SELECT_ADD, true);
-
+
/* 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...
+
+ /* 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_toggle(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Select All";
ot->idname = "GRAPH_OT_select_all_toggle";
ot->description = "Toggle selection of all keyframes";
-
+
/* api callbacks */
ot->exec = graphkeys_deselectall_exec;
ot->poll = graphop_visible_keyframes_poll;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* props */
ot->prop = RNA_def_boolean(ot->srna, "invert", 0, "Invert", "");
}
@@ -226,24 +226,24 @@ static void borderselect_graphkeys(
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter, mapping_flag;
-
+
SpaceIpo *sipo = (SpaceIpo *)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) {
@@ -259,7 +259,7 @@ static void borderselect_graphkeys(
else {
ked.data = &scaled_rectf;
}
-
+
/* treat handles separately? */
if (incl_handles) {
ked.iterflags |= KEYFRAME_ITER_INCL_HANDLES;
@@ -267,29 +267,29 @@ static void borderselect_graphkeys(
}
else
mapping_flag = ANIM_UNITCONV_ONLYKEYS;
-
+
mapping_flag |= ANIM_get_normalization_flags(ac);
-
+
/* loop over data, doing border 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
+
+ /* 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) {
@@ -300,12 +300,12 @@ static void borderselect_graphkeys(
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 */
@@ -313,12 +313,12 @@ static void borderselect_graphkeys(
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);
}
@@ -334,7 +334,7 @@ static int graphkeys_borderselect_exec(bContext *C, wmOperator *op)
bool incl_handles;
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;
@@ -344,7 +344,7 @@ static int graphkeys_borderselect_exec(bContext *C, wmOperator *op)
if (!extend)
deselect_graph_keys(&ac, 1, SELECT_SUBTRACT, true);
- /* get select mode
+ /* get select mode
* - 'include_handles' from the operator specifies whether to include handles in the selection
*/
if (select) {
@@ -353,15 +353,15 @@ static int graphkeys_borderselect_exec(bContext *C, wmOperator *op)
else {
selectmode = SELECT_SUBTRACT;
}
-
+
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 borderselect 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
+ /* 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...
@@ -371,19 +371,19 @@ static int graphkeys_borderselect_exec(bContext *C, wmOperator *op)
else
mode = BEZT_OK_VALUERANGE;
}
- else
+ else
mode = BEZT_OK_REGION;
BLI_rctf_rcti_copy(&rect_fl, &rect);
/* apply borderselect action */
borderselect_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_border(wmOperatorType *ot)
{
@@ -391,21 +391,21 @@ void GRAPH_OT_select_border(wmOperatorType *ot)
ot->name = "Border Select";
ot->idname = "GRAPH_OT_select_border";
ot->description = "Select all keyframes within the specified region";
-
+
/* api callbacks */
ot->invoke = WM_gesture_border_invoke;
ot->exec = graphkeys_borderselect_exec;
ot->modal = WM_gesture_border_modal;
ot->cancel = WM_gesture_border_cancel;
-
+
ot->poll = graphop_visible_keyframes_poll;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* rna */
WM_operator_properties_gesture_border_select(ot);
-
+
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");
}
@@ -416,34 +416,34 @@ void GRAPH_OT_select_border(wmOperatorType *ot)
static int graphkeys_lassoselect_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
-
+
KeyframeEdit_LassoData data_lasso = {0};
rcti rect;
rctf rect_fl;
-
+
short selectmode;
bool incl_handles;
bool extend;
-
+
/* 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;
-
+
/* clear all selection if not extending selection */
extend = RNA_boolean_get(op->ptr, "extend");
if (!extend)
deselect_graph_keys(&ac, 1, SELECT_SUBTRACT, true);
-
+
if (!RNA_boolean_get(op->ptr, "deselect"))
selectmode = SELECT_ADD;
else
selectmode = SELECT_SUBTRACT;
-
+
{
SpaceIpo *sipo = (SpaceIpo *)ac.sl;
if (selectmode == SELECT_ADD) {
@@ -454,19 +454,19 @@ static int graphkeys_lassoselect_exec(bContext *C, wmOperator *op)
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);
-
+
/* apply borderselect action */
borderselect_graphkeys(&ac, &rect_fl, BEZT_OK_REGION_LASSO, selectmode, incl_handles, &data_lasso);
-
+
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);
-
+
return OPERATOR_FINISHED;
}
@@ -476,17 +476,17 @@ void GRAPH_OT_select_lasso(wmOperatorType *ot)
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_select(ot);
}
@@ -499,10 +499,10 @@ static int graph_circle_select_exec(bContext *C, wmOperator *op)
const bool select = !RNA_boolean_get(op->ptr, "deselect");
const short selectmode = select ? SELECT_ADD : SELECT_SUBTRACT;
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");
@@ -510,17 +510,17 @@ static int graph_circle_select_exec(bContext *C, wmOperator *op)
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
+
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;
-
+
{
SpaceIpo *sipo = (SpaceIpo *)ac.sl;
if (selectmode == SELECT_ADD) {
@@ -531,13 +531,13 @@ static int graph_circle_select_exec(bContext *C, wmOperator *op)
incl_handles = (sipo->flag & SIPO_NOHANDLES) == 0;
}
}
-
+
/* apply borderselect action */
borderselect_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;
}
@@ -546,13 +546,13 @@ 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;
@@ -577,7 +577,7 @@ static const EnumPropertyItem prop_column_select_types[] = {
{0, NULL, 0, NULL, NULL}
};
-/* ------------------- */
+/* ------------------- */
/* Selects all visible keyframes between the specified markers */
/* TODO, this is almost an _exact_ duplicate of a function of the same name in action_select.c
@@ -587,27 +587,27 @@ 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);
@@ -621,7 +621,7 @@ static void markers_selectkeys_between(bAnimContext *ac)
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
}
}
-
+
/* Cleanup */
ANIM_animdata_freelist(&anim_data);
}
@@ -633,56 +633,56 @@ 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
*/
@@ -694,7 +694,7 @@ static void columnselect_graph_keys(bAnimContext *ac, short mode)
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
}
}
-
+
/* free elements */
BLI_freelistN(&ked.list);
ANIM_animdata_freelist(&anim_data);
@@ -706,39 +706,39 @@ static int graphkeys_columnselect_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
short mode;
-
+
/* 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");
-
+
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);
-
+
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)";
-
+
/* api callbacks */
ot->exec = graphkeys_columnselect_exec;
ot->poll = graphop_visible_keyframes_poll;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* props */
ot->prop = RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", "");
}
@@ -748,38 +748,38 @@ void GRAPH_OT_select_column(wmOperatorType *ot)
static int graphkeys_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
{
bAnimContext ac;
-
+
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);
-
+
/* 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);
-
+
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);
}
}
-
+
/* 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);
-
+
return OPERATOR_FINISHED;
}
@@ -789,11 +789,11 @@ void GRAPH_OT_select_linked(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -806,38 +806,38 @@ static void select_moreless_graph_keys(bAnimContext *ac, short mode)
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));
-
+ 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);
-
+
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;
-
+
/* 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);
-
+
/* free the selmap used here */
MEM_freeN(ked.data);
ked.data = NULL;
}
-
+
/* Cleanup */
ANIM_animdata_freelist(&anim_data);
}
@@ -847,17 +847,17 @@ static void select_moreless_graph_keys(bAnimContext *ac, short mode)
static int graphkeys_select_more_exec(bContext *C, wmOperator *UNUSED(op))
{
bAnimContext ac;
-
+
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
+
/* 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);
-
+
return OPERATOR_FINISHED;
}
@@ -867,11 +867,11 @@ void GRAPH_OT_select_more(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -881,17 +881,17 @@ void GRAPH_OT_select_more(wmOperatorType *ot)
static int graphkeys_select_less_exec(bContext *C, wmOperator *UNUSED(op))
{
bAnimContext ac;
-
+
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
+
/* 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);
-
+
return OPERATOR_FINISHED;
}
@@ -901,11 +901,11 @@ void GRAPH_OT_select_less(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -928,25 +928,25 @@ static void graphkeys_select_leftright(bAnimContext *ac, short leftright, short
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);
@@ -955,15 +955,15 @@ static void graphkeys_select_leftright(bAnimContext *ac, short leftright, short
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);
@@ -984,28 +984,28 @@ static int graphkeys_select_leftright_exec(bContext *C, wmOperator *op)
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;
-
+
/* 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;
-
+
/* 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);
-
+
return OPERATOR_FINISHED;
}
@@ -1013,11 +1013,11 @@ static int graphkeys_select_leftright_invoke(bContext *C, wmOperator *op, const
{
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;
@@ -1032,7 +1032,7 @@ static int graphkeys_select_leftright_invoke(bContext *C, wmOperator *op, const
else
RNA_enum_set(op->ptr, "mode", GRAPHKEYS_LRSEL_RIGHT);
}
-
+
/* perform selection */
return graphkeys_select_leftright_exec(C, op);
}
@@ -1040,24 +1040,24 @@ static int graphkeys_select_leftright_invoke(bContext *C, wmOperator *op, const
void GRAPH_OT_select_leftright(wmOperatorType *ot)
{
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";
-
+
/* 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;
-
+
/* 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);
}
@@ -1068,25 +1068,25 @@ void GRAPH_OT_select_leftright(wmOperatorType *ot)
* - 2) all keyframes on the same side of current frame indicator as mouse - ALT modifier
* - 3) column select all keyframes in frame under mouse - CTRL modifier
*
- * In addition to these basic options, the SHIFT modifier can be used to toggle the
+ * In addition to these basic options, the SHIFT modifier can be used to toggle the
* selection mode between replacing the selection (without) and inverting the selection (with).
*/
/* temp info for caching handle vertices close */
typedef struct tNearestVertInfo {
struct tNearestVertInfo *next, *prev;
-
+
FCurve *fcu; /* F-Curve that keyframe comes from */
-
+
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 */
-
+
eAnim_ChannelType ctype; /* type of animation channel this FCurve comes from */
-
+
float frame; /* frame that point was on when it matched (global time) */
} tNearestVertInfo;
@@ -1095,7 +1095,7 @@ typedef enum eGraphVertIndex {
NEAREST_HANDLE_LEFT = -1,
NEAREST_HANDLE_KEY,
NEAREST_HANDLE_RIGHT
-} eGraphVertIndex;
+} 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?
@@ -1121,9 +1121,9 @@ static void nearest_fcurve_vert_store(
/* 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,
+
+ /* 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
*/
@@ -1135,7 +1135,7 @@ static void nearest_fcurve_vert_store(
{
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... */
@@ -1145,19 +1145,19 @@ static void nearest_fcurve_vert_store(
/* 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);
@@ -1174,12 +1174,12 @@ static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], L
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
-
+
SpaceIpo *sipo = (SpaceIpo *)ac->sl;
View2D *v2d = &ac->ar->v2d;
short mapping_flag = 0;
-
- /* get curves to search through
+
+ /* 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...
*/
@@ -1188,32 +1188,32 @@ static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], L
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);
@@ -1223,14 +1223,14 @@ static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], L
}
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);
}
@@ -1240,22 +1240,22 @@ 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
+ /* 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);
@@ -1267,29 +1267,29 @@ static tNearestVertInfo *get_best_nearest_fcurve_vert(ListBase *matches)
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)
- * NOTE: the match info found must still be freed
+/* Find the nearest vertices (either a handle or the keyframe) that are nearest to the mouse cursor (in area coordinates)
+ * NOTE: the match info found must still be freed
*/
static tNearestVertInfo *find_nearest_fcurve_vert(bAnimContext *ac, const int mval[2])
{
ListBase matches = {NULL, NULL};
tNearestVertInfo *nvi;
-
+
/* 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);
-
+
BLI_freelistN(&matches);
-
+
/* return the best vert found */
return nvi;
}
@@ -1302,30 +1302,30 @@ static void mouse_graph_keys(bAnimContext *ac, const int mval[2], short select_m
SpaceIpo *sipo = (SpaceIpo *)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
+
+ /* 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)) {
@@ -1343,7 +1343,7 @@ static void mouse_graph_keys(bAnimContext *ac, const int mval[2], short select_m
BEZT_SEL_ALL(bezt);
}
}
-
+
/* handles - toggle selection of relevant handle */
else if (nvi->hpoint == NEAREST_HANDLE_LEFT) {
/* toggle selection */
@@ -1360,9 +1360,9 @@ static void mouse_graph_keys(bAnimContext *ac, const int mval[2], short select_m
BEZT_SEL_ALL(bezt);
}
/* otherwise, select the handle that applied */
- else if (nvi->hpoint == NEAREST_HANDLE_LEFT)
+ else if (nvi->hpoint == NEAREST_HANDLE_LEFT)
bezt->f1 |= SELECT;
- else
+ else
bezt->f3 |= SELECT;
}
}
@@ -1373,22 +1373,22 @@ static void mouse_graph_keys(bAnimContext *ac, const int mval[2], short select_m
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
+ /* 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))
@@ -1425,66 +1425,66 @@ static void graphkeys_mselect_column(bAnimContext *ac, const int mval[2], short
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);
}
-
+
/* ------------------- */
/* handle clicking */
@@ -1502,7 +1502,7 @@ static int graphkeys_clickselect_invoke(bContext *C, wmOperator *op, const wmEve
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 */
@@ -1516,41 +1516,41 @@ static int graphkeys_clickselect_invoke(bContext *C, wmOperator *op, const wmEve
/* 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 = "Mouse Select Keys";
+ 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",
+
+ 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",
+
+ 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 907f346c931..e543111e662 100644
--- a/source/blender/editors/space_graph/graph_utils.c
+++ b/source/blender/editors/space_graph/graph_utils.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation, Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
@@ -44,21 +44,66 @@
#include "BKE_context.h"
#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
/* ************************************************************** */
+/* Set Up Drivers Editor */
+
+/* Set up UI configuration for Drivers Editor */
+/* NOTE: Currently called from windowmanager (new drivers editor window) and RNA (mode switching) */
+void ED_drivers_editor_init(bContext *C, ScrArea *sa)
+{
+ SpaceIpo *sipo = (SpaceIpo *)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;
+ }
+}
+
+/* ************************************************************** */
/* Active F-Curve */
-/* Find 'active' F-Curve. It must be editable, since that's the purpose of these buttons (subject to change).
- * We return the 'wrapper' since it contains valuable context info (about hierarchy), which will need to be freed
+/* Find 'active' F-Curve. It must be editable, since that's the purpose of these buttons (subject to change).
+ * We return the 'wrapper' since it contains valuable context info (about hierarchy), which will need to be freed
* when the caller is done with it.
*
* NOTE: curve-visible flag isn't included, otherwise selecting a curve via list to edit is too cumbersome
@@ -68,20 +113,20 @@ 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);
-
+
/* 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);
-
+
return ale;
}
-
+
/* no active F-Curve */
return NULL;
}
@@ -99,30 +144,30 @@ int graphop_visible_keyframes_poll(bContext *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_IPO))
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)
+ 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
+ * - F-Curve modifiers do not interfere with the result too much
* (i.e. the modifier-control drawing check returns false)
*/
if (fcu->bezt == NULL)
@@ -132,7 +177,7 @@ int graphop_visible_keyframes_poll(bContext *C)
break;
}
}
-
+
/* cleanup and return findings */
ANIM_animdata_freelist(&anim_data);
return found;
@@ -148,27 +193,27 @@ int graphop_editable_keyframes_poll(bContext *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_IPO))
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)
+ 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
@@ -182,7 +227,7 @@ int graphop_editable_keyframes_poll(bContext *C)
break;
}
}
-
+
/* cleanup and return findings */
ANIM_animdata_freelist(&anim_data);
return found;
@@ -195,21 +240,21 @@ int graphop_active_fcurve_poll(bContext *C)
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_IPO))
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
@@ -220,10 +265,10 @@ int graphop_active_fcurve_poll(bContext *C)
FCurve *fcu = (FCurve *)ale->data;
has_fcurve = (fcu->flag & FCURVE_VISIBLE) != 0;
}
-
+
/* free temp data... */
MEM_freeN(ale);
-
+
/* return success */
return has_fcurve;
}
@@ -236,24 +281,24 @@ int graphop_selected_fcurve_poll(bContext *C)
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_IPO))
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
+
+ /* 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)
+ 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 f59d70d97c7..878c4815f73 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -54,12 +54,16 @@
#include "ED_markers.h"
#include "GPU_immediate.h"
+#include "GPU_state.h"
+#include "GPU_framebuffer.h"
#include "WM_api.h"
#include "WM_types.h"
#include "WM_message.h"
#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -71,7 +75,7 @@
ARegion *graph_has_buttons_region(ScrArea *sa)
{
ARegion *ar, *arnew;
-
+
ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
if (ar) return ar;
@@ -80,15 +84,15 @@ ARegion *graph_has_buttons_region(ScrArea *sa)
/* is error! */
if (ar == NULL) return NULL;
-
+
arnew = MEM_callocN(sizeof(ARegion), "buttons for graph");
-
+
BLI_insertlinkafter(&sa->regionbase, ar, arnew);
arnew->regiontype = RGN_TYPE_UI;
arnew->alignment = RGN_ALIGN_RIGHT;
-
+
arnew->flag = RGN_FLAG_HIDDEN;
-
+
return arnew;
}
@@ -99,98 +103,98 @@ static SpaceLink *graph_new(const ScrArea *UNUSED(sa), const Scene *scene)
{
ARegion *ar;
SpaceIpo *sipo;
-
+
/* Graph Editor - general stuff */
sipo = MEM_callocN(sizeof(SpaceIpo), "init graphedit");
sipo->spacetype = SPACE_IPO;
-
+
sipo->autosnap = SACTSNAP_FRAME;
-
+
/* 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;
-
+
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for graphedit");
-
+
BLI_addtail(&sipo->regionbase, ar);
ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = RGN_ALIGN_BOTTOM;
-
+ ar->alignment = RGN_ALIGN_TOP;
+
/* 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;
-
+
ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
-
+
/* 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;
-
+
/* main region */
ar = MEM_callocN(sizeof(ARegion), "main region for graphedit");
-
+
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.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.keeptot = 0;
-
+
return (SpaceLink *)sipo;
}
/* not spacelink itself */
static void graph_free(SpaceLink *sl)
-{
+{
SpaceIpo *si = (SpaceIpo *)sl;
-
+
if (si->ads) {
BLI_freelistN(&si->ads->chanbase);
MEM_freeN(si->ads);
}
-
+
if (si->ghostCurves.first)
free_fcurves(&si->ghostCurves);
}
/* spacetype; init callback */
-static void graph_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
+static void graph_init(struct wmWindowManager *wm, ScrArea *sa)
{
SpaceIpo *sipo = (SpaceIpo *)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 *)(G.main->scene.first); // FIXME: this is a really nasty hack here for now...
+ 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
@@ -202,11 +206,11 @@ static void graph_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
static SpaceLink *graph_duplicate(SpaceLink *sl)
{
SpaceIpo *sipon = MEM_dupallocN(sl);
-
+
/* clear or remove stuff from old */
BLI_duplicatelist(&sipon->ghostCurves, &((SpaceIpo *)sl)->ghostCurves);
sipon->ads = MEM_dupallocN(sipon->ads);
-
+
return (SpaceLink *)sipon;
}
@@ -214,9 +218,9 @@ static SpaceLink *graph_duplicate(SpaceLink *sl)
static void graph_main_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
-
+
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
-
+
/* own keymap */
keymap = WM_keymap_find(wm->defaultconf, "Graph Editor", SPACE_IPO, 0);
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
@@ -235,42 +239,42 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar)
View2DScrollers *scrollers;
float col[3];
short unitx = 0, unity = V2D_UNIT_VALUES, cfra_flag = 0;
-
+
/* clear and setup matrix */
UI_GetThemeColor3fv(TH_BACK, col);
- glClearColor(col[0], col[1], col[2], 0.0);
- glClear(GL_COLOR_BUFFER_BIT);
-
+ 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);
@@ -285,15 +289,15 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar)
/* Draw a green line to indicate the cursor value */
immUniformThemeColorShadeAlpha(TH_CFRAME, -10, -50);
- glEnable(GL_BLEND);
- glLineWidth(2.0);
+ GPU_blend(true);
+ GPU_line_width(2.0);
immBegin(GWN_PRIM_LINES, 2);
immVertex2f(pos, v2d->cur.xmin, y);
immVertex2f(pos, v2d->cur.xmax, y);
immEnd();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
/* current frame or vertical component of vertical component of the cursor */
@@ -303,15 +307,15 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar)
/* to help differentiate this from the current frame, draw slightly darker like the horizontal one */
immUniformThemeColorShadeAlpha(TH_CFRAME, -40, -50);
- glEnable(GL_BLEND);
- glLineWidth(2.0);
+ GPU_blend(true);
+ GPU_line_width(2.0);
immBegin(GWN_PRIM_LINES, 2);
immVertex2f(pos, x, v2d->cur.ymin);
immVertex2f(pos, x, v2d->cur.ymax);
immEnd();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
immUnbindProgram();
@@ -322,28 +326,28 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar)
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);
ED_markers_draw(C, DRAW_MARKERS_MARGIN);
-
+
/* 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, 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);
@@ -354,15 +358,15 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar)
static void graph_channel_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
-
+
/* make sure we keep the hide flags */
ar->v2d.scroll |= V2D_SCROLL_RIGHT;
ar->v2d.scroll &= ~(V2D_SCROLL_LEFT | V2D_SCROLL_TOP | V2D_SCROLL_BOTTOM); /* prevent any noise of past */
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);
-
+
/* own keymap */
keymap = WM_keymap_find(wm->defaultconf, "Animation Channels", 0, 0);
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
@@ -376,22 +380,22 @@ static void graph_channel_region_draw(const bContext *C, ARegion *ar)
View2D *v2d = &ar->v2d;
View2DScrollers *scrollers;
float col[3];
-
+
/* clear and setup matrix */
UI_GetThemeColor3fv(TH_BACK, col);
- glClearColor(col[0], col[1], col[2], 0.0);
- glClear(GL_COLOR_BUFFER_BIT);
-
+ 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, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
UI_view2d_scrollers_draw(C, v2d, scrollers);
@@ -413,7 +417,7 @@ static void graph_header_region_draw(const bContext *C, ARegion *ar)
static void graph_buttons_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
-
+
ED_region_panels_init(wm, ar);
keymap = WM_keymap_find(wm->defaultconf, "Graph Editor Generic", SPACE_IPO, 0);
@@ -422,7 +426,7 @@ static void graph_buttons_region_init(wmWindowManager *wm, ARegion *ar)
static void graph_buttons_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
static void graph_region_listener(
@@ -483,7 +487,7 @@ static void graph_region_listener(
if (wmn->data == ND_KEYS)
ED_region_tag_redraw(ar);
break;
-
+
}
}
@@ -525,6 +529,42 @@ static void graph_region_message_subscribe(
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 */
@@ -532,7 +572,7 @@ static void graph_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Sc
WorkSpace *UNUSED(workspace))
{
SpaceIpo *sipo = (SpaceIpo *)sa->spacedata.first;
-
+
/* context changes */
switch (wmn->category) {
case NC_ANIMATION:
@@ -549,7 +589,7 @@ static void graph_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Sc
sipo->flag |= SIPO_TEMP_NEEDCHANSYNC;
ED_area_tag_refresh(sa);
break;
-
+
default: /* just redrawing the view will do */
ED_area_tag_redraw(sa);
break;
@@ -564,7 +604,7 @@ static void graph_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Sc
break;
case ND_TRANSFORM:
break; /*do nothing*/
-
+
default: /* just redrawing the view will do */
ED_area_tag_redraw(sa);
break;
@@ -587,7 +627,7 @@ static void graph_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Sc
ED_area_tag_refresh(sa);
}
break;
-
+
// XXX: restore the case below if not enough updates occur...
//default:
// if (wmn->data == ND_KEYS)
@@ -599,29 +639,29 @@ static void graph_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Sc
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_IPO, 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:
@@ -633,11 +673,11 @@ static void graph_refresh_fcurve_colors(const bContext *C)
}
case FCURVE_COLOR_AUTO_RGB:
{
- /* F-Curve's array index is automatically mapped to RGB values. This works best of 3-value vectors.
+ /* 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);
@@ -659,7 +699,7 @@ static void graph_refresh_fcurve_colors(const bContext *C)
{
/* 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);
@@ -670,29 +710,29 @@ static void graph_refresh_fcurve_colors(const bContext *C)
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;
@@ -711,7 +751,7 @@ static void graph_refresh_fcurve_colors(const bContext *C)
}
}
}
-
+
/* free temp list */
ANIM_animdata_freelist(&anim_data);
}
@@ -719,24 +759,24 @@ static void graph_refresh_fcurve_colors(const bContext *C)
static void graph_refresh(const bContext *C, ScrArea *sa)
{
SpaceIpo *sipo = (SpaceIpo *)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
+
+ /* 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->flag & SIPO_TEMP_NEEDCHANSYNC) {
@@ -744,7 +784,7 @@ static void graph_refresh(const bContext *C, ScrArea *sa)
sipo->flag &= ~SIPO_TEMP_NEEDCHANSYNC;
ED_area_tag_redraw(sa);
}
-
+
/* init/adjust F-Curve colors */
graph_refresh_fcurve_colors(C);
}
@@ -752,10 +792,10 @@ static void graph_refresh(const bContext *C, ScrArea *sa)
static void graph_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
{
SpaceIpo *sgraph = (SpaceIpo *)slink;
-
+
if (sgraph->ads) {
if ((ID *)sgraph->ads->filter_grp == old_id) {
- sgraph->ads->filter_grp = (Group *)new_id;
+ sgraph->ads->filter_grp = (Collection *)new_id;
}
if ((ID *)sgraph->ads->source == old_id) {
sgraph->ads->source = new_id;
@@ -763,15 +803,33 @@ static void graph_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID
}
}
+static int graph_space_subtype_get(ScrArea *sa)
+{
+ SpaceIpo *sgraph = sa->spacedata.first;
+ return sgraph->mode;
+}
+
+static void graph_space_subtype_set(ScrArea *sa, int value)
+{
+ SpaceIpo *sgraph = sa->spacedata.first;
+ sgraph->mode = value;
+}
+
+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);
+}
+
/* 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_IPO;
strncpy(st->name, "Graph", BKE_ST_MAXNAME);
-
+
st->new = graph_new;
st->free = graph_free;
st->init = graph_init;
@@ -781,6 +839,9 @@ void ED_spacetype_ipo(void)
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");
@@ -792,7 +853,7 @@ void ED_spacetype_ipo(void)
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;
@@ -801,20 +862,21 @@ void ED_spacetype_ipo(void)
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;
art->prefsizex = 200 + V2D_SCROLL_WIDTH; /* 200 is the 'standard', but due to scrollers, we want a bit more to fit the lock icons in */
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;
@@ -823,11 +885,10 @@ void ED_spacetype_ipo(void)
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/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index c105f40f1d6..0cd61f3e330 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -134,7 +134,7 @@ static void image_info(Scene *scene, ImageUser *iuser, Image *ima, ImBuf *ibuf,
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))
@@ -147,7 +147,7 @@ struct ImageUser *ntree_get_active_iuser(bNodeTree *ntree)
/* ************ panel stuff ************* */
#if 0
-/* 0: disable preview
+/* 0: disable preview
* otherwise refresh preview
*
* XXX if you put this back, also check XXX in image_main_region_draw() */
@@ -155,7 +155,7 @@ struct ImageUser *ntree_get_active_iuser(bNodeTree *ntree)
void image_preview_event(int event)
{
int exec = 0;
-
+
if (event == 0) {
G.scene->r.scemode &= ~R_COMP_CROP;
exec = 1;
@@ -168,27 +168,27 @@ void image_preview_event(int event)
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 */
-
+
ntreeCompositTagGenerators(G.scene->nodetree);
G.is_break = false;
G.scene->nodetree->timecursor = set_timecursor;
G.scene->nodetree->test_break = BKE_blender_test_break;
-
+
BIF_store_spare();
-
+
ntreeCompositExecTree(scene->nodetree, &scene->r, 1, &scene->view_settings, &scene->display_settings); /* 1 is do_previews */
-
+
G.scene->nodetree->timecursor = NULL;
G.scene->nodetree->test_break = NULL;
-
+
scrarea_do_windraw(curarea);
waitcursor(0);
-
+
WM_event_add_notifier(C, NC_IMAGE, ima_v);
}
}
@@ -203,20 +203,20 @@ static void preview_cb(ScrArea *sa, struct uiBlock *block)
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 */
@@ -224,13 +224,13 @@ static void preview_cb(ScrArea *sa, struct uiBlock *block)
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);
@@ -254,7 +254,7 @@ static bool is_preview_allowed(ScrArea *cur)
/* check image type */
if (sima->image == NULL || sima->image->type != IMA_TYPE_COMPOSITE)
return 0;
-
+
return 1;
}
@@ -264,23 +264,23 @@ static void image_panel_preview(ScrArea *sa, short cntrl) // IMAGE_HANDLER_PRE
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;
}
-
+
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;
-
+
UI_but_func_drawextra_set(block, preview_cb);
-
+
}
#endif
@@ -291,23 +291,24 @@ static void ui_imageuser_slot_menu(bContext *UNUSED(C), uiLayout *layout, void *
{
uiBlock *block = uiLayoutGetBlock(layout);
Image *image = image_p;
- int slot;
+ 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 = IMA_MAX_RENDER_SLOT;
- while (slot--) {
+ slot_id = BLI_listbase_count(&image->renderslots) - 1;
+ for (RenderSlot *slot = image->renderslots.last; slot; slot = slot->prev) {
char str[64];
- if (image->render_slots[slot].name[0] != '\0') {
- BLI_strncpy(str, image->render_slots[slot].name, sizeof(str));
+ if (slot->name[0] != '\0') {
+ BLI_strncpy(str, slot->name, sizeof(str));
}
else {
- BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), slot + 1);
+ 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, 0.0, 0, -1, "");
+ UI_UNIT_X * 5, UI_UNIT_X, &image->render_slot, (float) slot_id, 0.0, 0, -1, "");
+ slot_id--;
}
}
@@ -660,7 +661,7 @@ static void image_multiview_cb(bContext *C, void *rnd_pt, void *UNUSED(arg_v))
}
#if 0
-static void image_freecache_cb(bContext *C, void *ima_v, void *unused)
+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);
@@ -708,8 +709,9 @@ static void uiblock_layer_pass_buttons(
/* menu buts */
if (render_slot) {
char str[64];
- if (image->render_slots[*render_slot].name[0] != '\0') {
- BLI_strncpy(str, image->render_slots[*render_slot].name, sizeof(str));
+ 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);
@@ -898,7 +900,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
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:");
@@ -929,7 +931,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
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);
@@ -1043,7 +1045,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
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);
@@ -1077,7 +1079,7 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_man
col = uiLayoutColumn(layout, false);
split = uiLayoutSplit(col, 0.5f, false);
-
+
uiItemR(split, imfptr, "file_format", 0, "", ICON_NONE);
sub = uiLayoutRow(split, false);
uiItemR(sub, imfptr, "color_mode", UI_ITEM_R_EXPAND, IFACE_("Color"), ICON_NONE);
@@ -1109,7 +1111,7 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_man
if (ELEM(imf->imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) {
uiItemR(col, imfptr, "exr_codec", 0, NULL, ICON_NONE);
}
-
+
row = uiLayoutRow(col, false);
if (BKE_imtype_supports_zbuf(imf->imtype)) {
uiItemR(row, imfptr, "use_zbuffer", 0, NULL, ICON_NONE);
@@ -1126,7 +1128,7 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_man
row = uiLayoutRow(col, false);
uiItemR(row, imfptr, "use_jpeg2k_cinema_preset", 0, NULL, ICON_NONE);
uiItemR(row, imfptr, "use_jpeg2k_cinema_48", 0, NULL, ICON_NONE);
-
+
uiItemR(col, imfptr, "use_jpeg2k_ycc", 0, NULL, ICON_NONE);
}
@@ -1297,14 +1299,14 @@ void uiTemplateImageInfo(uiLayout *layout, bContext *C, Image *ima, ImageUser *i
void image_buttons_register(ARegionType *UNUSED(art))
{
-
+
}
static int image_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = image_has_buttons_region(sa);
-
+
if (ar)
ED_region_toggle_hidden(C, ar);
@@ -1313,13 +1315,13 @@ static int image_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
void IMAGE_OT_properties(wmOperatorType *ot)
{
- ot->name = "Properties";
+ 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;
-
+
/* flags */
ot->flag = 0;
}
@@ -1328,23 +1330,22 @@ static int image_scopes_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = image_has_tools_region(sa);
-
+
if (ar)
ED_region_toggle_hidden(C, ar);
-
+
return OPERATOR_FINISHED;
}
void IMAGE_OT_toolshelf(wmOperatorType *ot)
{
- ot->name = "Tool Shelf";
+ 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;
-
+
/* 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 fc4d8c39e26..11e06c168b4 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -65,6 +65,7 @@
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "BLF_api.h"
@@ -130,7 +131,7 @@ static void draw_render_info(const bContext *C,
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColor(TH_FACE_SELECT);
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
rcti *tile = tiles;
for (int i = 0; i < total_tiles; i++, tile++) {
@@ -170,8 +171,8 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
float hue = 0, sat = 0, val = 0, lum = 0, u = 0, v = 0;
float col[4], finalcol[4];
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -182,7 +183,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
immUnbindProgram();
- glDisable(GL_BLEND);
+ GPU_blend(false);
BLF_size(blf_mono_font, 11 * U.pixelsize, U.dpi);
@@ -231,7 +232,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
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)
BLI_snprintf(str, sizeof(str), " G:%-.5f", fp[1]);
@@ -242,7 +243,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
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)
BLI_snprintf(str, sizeof(str), " B:%-.5f", fp[2]);
@@ -253,7 +254,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
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)
@@ -287,7 +288,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
dx += BLF_width(blf_mono_font, str, sizeof(str));
}
}
-
+
/* color rectangle */
if (channels == 1) {
if (fp) {
@@ -323,7 +324,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
copy_v4_v4(finalcol, col);
}
- glDisable(GL_BLEND);
+ GPU_blend(false);
dx += 0.25f * UI_UNIT_X;
BLI_rcti_init(&color_rect, dx, dx + (1.5f * UI_UNIT_X), 0.15f * UI_UNIT_Y, 0.85f * UI_UNIT_Y);
@@ -354,10 +355,10 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
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);
- glEnable(GL_BLEND);
+ 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);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
else {
immUniformColor3fv(finalcol);
@@ -384,7 +385,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
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);
}
-
+
BLI_snprintf(str, sizeof(str), "V:%-.4f", val);
BLF_position(blf_mono_font, dx, dy, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
@@ -503,8 +504,8 @@ static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar,
if (sima->flag & SI_USE_ALPHA) {
imm_draw_box_checker_2d(x, y, x + ibuf->x * zoomx, y + ibuf->y * zoomy);
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
}
/* If RGBA display with color management */
@@ -544,7 +545,7 @@ static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar,
}
if (sima->flag & SI_USE_ALPHA)
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
}
@@ -561,7 +562,7 @@ void draw_image_grease_pencil(bContext *C, bool onlyv2d)
else {
/* assume that UI_view2d_restore(C) has been called... */
//SpaceImage *sima = (SpaceImage *)CTX_wm_space_data(C);
-
+
/* draw grease-pencil ('screen' strokes) */
ED_gpencil_draw_view2d(C, 0);
}
@@ -578,7 +579,7 @@ void draw_image_sample_line(SpaceImage *sima)
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
immUniform1i("num_colors", 2); /* Advanced dashes. */
@@ -618,13 +619,13 @@ static void draw_image_paint_helpers(const bContext *C, ARegion *ar, Scene *scen
return;
}
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
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);
- glDisable(GL_BLEND);
+ GPU_blend(false);
BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
IMB_display_buffer_release(cache_handle);
@@ -647,10 +648,10 @@ void draw_image_main(const bContext *C, ARegion *ar)
/* 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);
@@ -758,8 +759,8 @@ void draw_image_cache(const bContext *C, ARegion *ar)
mask = ED_space_image_get_mask(sima);
}
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
/* Draw cache background. */
ED_region_cache_draw_background(ar);
@@ -773,7 +774,7 @@ void draw_image_cache(const bContext *C, ARegion *ar)
ED_region_cache_draw_cached_segments(ar, num_segments, points, sfra + sima->iuser.offset, efra + sima->iuser.offset);
}
- glDisable(GL_BLEND);
+ GPU_blend(false);
/* Draw current frame. */
x = (cfra - sfra) / (efra - sfra + 1) * ar->winx;
diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c
index c598e486a7e..8bbca25538a 100644
--- a/source/blender/editors/space_image/image_edit.c
+++ b/source/blender/editors/space_image/image_edit.c
@@ -34,6 +34,7 @@
#include "DNA_scene_types.h"
#include "BLI_rect.h"
+#include "BLI_listbase.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
@@ -41,6 +42,7 @@
#include "BKE_image.h"
#include "BKE_editmesh.h"
#include "BKE_library.h"
+#include "BKE_main.h"
#include "IMB_imbuf_types.h"
@@ -63,7 +65,7 @@ Image *ED_space_image(SpaceImage *sima)
}
/* called to assign images to UV faces */
-void ED_space_image_set(SpaceImage *sima, Scene *UNUSED(scene), Object *obedit, Image *ima)
+void ED_space_image_set(Main *bmain, SpaceImage *sima, Scene *UNUSED(scene), Object *obedit, 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 */
@@ -76,7 +78,7 @@ void ED_space_image_set(SpaceImage *sima, Scene *UNUSED(scene), Object *obedit,
}
if (sima->image)
- BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE);
+ BKE_image_signal(bmain, sima->image, &sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE);
id_us_ensure_real((ID *)sima->image);
@@ -301,17 +303,19 @@ bool ED_image_slot_cycle(struct Image *image, int direction)
BLI_assert(ELEM(direction, -1, 1));
- for (i = 1; i < IMA_MAX_RENDER_SLOT; i++) {
- slot = (cur + ((direction == -1) ? -i : i)) % IMA_MAX_RENDER_SLOT;
- if (slot < 0) slot += IMA_MAX_RENDER_SLOT;
+ 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;
- if (image->renders[slot] || slot == image->last_render_slot) {
+ 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 == IMA_MAX_RENDER_SLOT) {
+ if (i == num_slots) {
image->render_slot = ((cur == 1) ? 0 : 1);
}
@@ -322,7 +326,7 @@ void ED_space_image_scopes_update(const struct bContext *C, struct SpaceImage *s
{
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;
@@ -338,7 +342,7 @@ void ED_space_image_scopes_update(const struct bContext *C, struct SpaceImage *s
return;
}
}
-
+
scopes_update(&sima->scopes, ibuf, use_view_settings ? &scene->view_settings : NULL, &scene->display_settings);
}
@@ -420,4 +424,3 @@ int ED_space_image_maskedit_mask_poll(bContext *C)
return false;
}
-
diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h
index 47d6257366c..3725f1d5195 100644
--- a/source/blender/editors/space_image/image_intern.h
+++ b/source/blender/editors/space_image/image_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -83,6 +83,9 @@ void IMAGE_OT_unpack(struct wmOperatorType *ot);
void IMAGE_OT_invert(struct wmOperatorType *ot);
void IMAGE_OT_cycle_render_slot(struct wmOperatorType *ot);
+void IMAGE_OT_clear_render_slot(struct wmOperatorType *ot);
+void IMAGE_OT_add_render_slot(struct wmOperatorType *ot);
+void IMAGE_OT_remove_render_slot(struct wmOperatorType *ot);
void IMAGE_OT_sample(struct wmOperatorType *ot);
void IMAGE_OT_sample_line(struct wmOperatorType *ot);
@@ -101,4 +104,3 @@ void IMAGE_OT_properties(struct wmOperatorType *ot);
void IMAGE_OT_toolshelf(struct wmOperatorType *ot);
#endif /* __IMAGE_INTERN_H__ */
-
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index a2afb5cb5c5..40311594512 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -57,7 +57,6 @@
#include "BKE_colortools.h"
#include "BKE_context.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_icons.h"
#include "BKE_image.h"
#include "BKE_global.h"
@@ -227,7 +226,7 @@ static int space_image_file_exists_poll(bContext *C)
ibuf = ED_space_image_acquire_buffer(sima, &lock);
if (ibuf) {
BLI_strncpy(name, ibuf->name, FILE_MAX);
- BLI_path_abs(name, bmain->name);
+ 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");
@@ -366,7 +365,7 @@ static int image_view_pan_exec(bContext *C, wmOperator *op)
image_preview_event(2);
}
#endif
-
+
return OPERATOR_FINISHED;
}
@@ -375,7 +374,7 @@ static int image_view_pan_invoke(bContext *C, wmOperator *op, const wmEvent *eve
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);
@@ -423,10 +422,10 @@ static void image_view_pan_cancel(bContext *C, wmOperator *op)
void IMAGE_OT_view_pan(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "View Pan";
+ 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;
@@ -436,7 +435,7 @@ void IMAGE_OT_view_pan(wmOperatorType *ot)
/* 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);
@@ -521,7 +520,7 @@ static int image_view_zoom_exec(bContext *C, wmOperator *op)
image_preview_event(2);
}
#endif
-
+
return OPERATOR_FINISHED;
}
@@ -549,7 +548,7 @@ static int image_view_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
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 {
@@ -639,10 +638,10 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot)
PropertyRNA *prop;
/* identifiers */
- ot->name = "View Zoom";
+ 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;
@@ -652,7 +651,7 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot)
/* 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);
@@ -701,7 +700,7 @@ void IMAGE_OT_view_ndof(wmOperatorType *ot)
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;
@@ -734,7 +733,7 @@ static int image_view_all_exec(bContext *C, wmOperator *op)
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;
@@ -762,7 +761,7 @@ static int image_view_all_exec(bContext *C, wmOperator *op)
sima->xof = sima->yof = 0.0f;
ED_region_tag_redraw(ar);
-
+
return OPERATOR_FINISHED;
}
@@ -774,7 +773,7 @@ void IMAGE_OT_view_all(wmOperatorType *ot)
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;
@@ -830,7 +829,7 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
sima_zoom_set_from_bounds(sima, ar, &bounds);
ED_region_tag_redraw(ar);
-
+
return OPERATOR_FINISHED;
}
@@ -845,7 +844,7 @@ void IMAGE_OT_view_selected(wmOperatorType *ot)
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;
@@ -858,13 +857,13 @@ 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];
-
+
RNA_float_get_array(op->ptr, "location", location);
sima_zoom_set_factor(sima, ar, powf(2.0f, 1.0f / 3.0f), location);
ED_region_tag_redraw(ar);
-
+
return OPERATOR_FINISHED;
}
@@ -887,7 +886,7 @@ void IMAGE_OT_view_zoom_in(wmOperatorType *ot)
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;
@@ -907,13 +906,13 @@ 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];
-
+
RNA_float_get_array(op->ptr, "location", location);
sima_zoom_set_factor(sima, ar, powf(0.5f, 1.0f / 3.0f), location);
-
+
ED_region_tag_redraw(ar);
-
+
return OPERATOR_FINISHED;
}
@@ -936,7 +935,7 @@ void IMAGE_OT_view_zoom_out(wmOperatorType *ot)
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;
@@ -959,7 +958,7 @@ static int image_view_zoom_ratio_exec(bContext *C, wmOperator *op)
ARegion *ar = CTX_wm_region(C);
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;
@@ -974,7 +973,7 @@ static int image_view_zoom_ratio_exec(bContext *C, wmOperator *op)
#endif
ED_region_tag_redraw(ar);
-
+
return OPERATOR_FINISHED;
}
@@ -984,7 +983,7 @@ void IMAGE_OT_view_zoom_ratio(wmOperatorType *ot)
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;
@@ -1057,7 +1056,7 @@ void IMAGE_OT_view_zoom_border(wmOperatorType *ot)
static void image_filesel(bContext *C, wmOperator *op, const char *path)
{
RNA_string_set(op->ptr, "filepath", path);
- WM_event_add_fileselect(C, op);
+ WM_event_add_fileselect(C, op);
}
/******************** open image operator ********************/
@@ -1179,14 +1178,14 @@ static int image_sequence_get_len(ListBase *frames, int *ofs)
}
static Image *image_open_single(
- wmOperator *op, const char *filepath, const char *relbase,
+ 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(filepath, &exists);
+ ima = BKE_image_load_exists_ex(bmain, filepath, &exists);
if (!ima) {
if (op->customdata) MEM_freeN(op->customdata);
@@ -1263,11 +1262,11 @@ static int image_open_exec(bContext *C, wmOperator *op)
BLI_strncpy(filepath_range, frame_range->filepath, sizeof(filepath_range));
if (was_relative) {
- BLI_path_rel(filepath_range, bmain->name);
+ BLI_path_rel(filepath_range, BKE_main_blendfile_path(bmain));
}
Image *ima_range = image_open_single(
- op, filepath_range, bmain->name,
+ bmain, op, filepath_range, BKE_main_blendfile_path(bmain),
is_relative_path, use_multiview, frame_range_seq_len);
/* take the first image */
@@ -1282,7 +1281,7 @@ static int image_open_exec(bContext *C, wmOperator *op)
else {
/* for drag & drop etc. */
ima = image_open_single(
- op, filepath, bmain->name,
+ bmain, op, filepath, BKE_main_blendfile_path(bmain),
is_relative_path, use_multiview, 1);
}
@@ -1308,7 +1307,7 @@ static int image_open_exec(bContext *C, wmOperator *op)
}
else if (sa && sa->spacetype == SPACE_IMAGE) {
SpaceImage *sima = sa->spacedata.first;
- ED_space_image_set(sima, scene, obedit, ima);
+ ED_space_image_set(bmain, sima, scene, obedit, ima);
iuser = &sima->iuser;
}
else {
@@ -1348,10 +1347,10 @@ static int image_open_exec(bContext *C, wmOperator *op)
/* XXX unpackImage frees image buffers */
ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
-
- BKE_image_signal(ima, iuser, IMA_SIGNAL_RELOAD);
+
+ 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;
@@ -1399,7 +1398,7 @@ static int image_open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
if (RNA_struct_property_is_set(op->ptr, "filepath"))
return image_open_exec(C, op);
-
+
image_open_init(C, op);
/* show multiview save options only if scene has multiviews */
@@ -1448,7 +1447,7 @@ void IMAGE_OT_open(wmOperatorType *ot)
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;
@@ -1487,7 +1486,7 @@ static int image_match_len_exec(bContext *C, wmOperator *UNUSED(op))
ima = sima->image;
iuser = &sima->iuser;
}
-
+
}
if (!ima || !iuser || !BKE_image_has_anim(ima))
@@ -1509,7 +1508,7 @@ void IMAGE_OT_match_movie_length(wmOperatorType *ot)
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;
@@ -1521,12 +1520,13 @@ void IMAGE_OT_match_movie_length(wmOperatorType *ot)
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];
if (!sima->image)
return OPERATOR_CANCELLED;
-
+
RNA_string_get(op->ptr, "filepath", str);
/* we cant do much if the str is longer then FILE_MAX :/ */
@@ -1534,19 +1534,19 @@ static int image_replace_exec(bContext *C, wmOperator *op)
if (sima->image->source == IMA_SRC_GENERATED) {
sima->image->source = IMA_SRC_FILE;
- BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_SRC_CHANGE);
+ BKE_image_signal(bmain, sima->image, &sima->iuser, IMA_SIGNAL_SRC_CHANGE);
}
-
- if (BLI_testextensie_array(str, imb_ext_movie))
+
+ 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));
-
+
BKE_icon_changed(BKE_icon_id_ensure(&sima->image->id));
- BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_RELOAD);
+ 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;
@@ -1576,7 +1576,7 @@ void IMAGE_OT_replace(wmOperatorType *ot)
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;
@@ -1627,7 +1627,7 @@ static char imtype_best_depth(ImBuf *ibuf, const char imtype)
}
}
-static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima, Scene *scene,
+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;
@@ -1692,12 +1692,12 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima,
}
else {
BLI_strncpy(simopts->filepath, "//untitled", sizeof(simopts->filepath));
- BLI_path_abs(simopts->filepath, G.main->name);
+ 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 : G.main->name);
+ BLI_path_abs(simopts->filepath, is_prev_save ? G.ima : BKE_main_blendfile_path(bmain));
}
}
@@ -1711,7 +1711,7 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima,
return (ibuf != NULL);
}
-static void save_image_options_from_op(SaveImageOptions *simopts, wmOperator *op)
+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);
@@ -1721,7 +1721,7 @@ static void save_image_options_from_op(SaveImageOptions *simopts, wmOperator *op
if (RNA_struct_property_is_set(op->ptr, "filepath")) {
RNA_string_get(op->ptr, "filepath", simopts->filepath);
- BLI_path_abs(simopts->filepath, G.main->name);
+ BLI_path_abs(simopts->filepath, BKE_main_blendfile_path(bmain));
}
}
@@ -1737,7 +1737,7 @@ static void save_image_options_to_op(SaveImageOptions *simopts, wmOperator *op)
}
static void save_image_post(
- wmOperator *op, ImBuf *ibuf, Image *ima, int ok, int save_copy,
+ 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) {
@@ -1783,7 +1783,7 @@ static void save_image_post(
if (!BKE_color_managed_colorspace_settings_equals(&old_colorspace_settings,
&ima->colorspace_settings))
{
- BKE_image_signal(ima, NULL, IMA_SIGNAL_COLORMANAGE);
+ BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_COLORMANAGE);
}
}
}
@@ -1814,6 +1814,7 @@ static void save_imbuf_post(ImBuf *ibuf, ImBuf *colormanaged_ibuf)
*/
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);
@@ -1891,7 +1892,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
if (imf->views_format == R_IMF_VIEWS_MULTIVIEW && is_exr_rr) {
/* save render result */
ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, NULL, sima->iuser.layer);
- save_image_post(op, ibuf, ima, ok, true, relbase, relative, do_newpath, simopts->filepath);
+ 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 */
@@ -1904,7 +1905,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
ok = BKE_imbuf_write_as(colormanaged_ibuf, simopts->filepath, imf, save_copy);
save_imbuf_post(ibuf, colormanaged_ibuf);
}
- save_image_post(op, ibuf, ima, ok, (is_exr_rr ? true : save_copy), relbase, relative, do_newpath, simopts->filepath);
+ 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 */
@@ -1926,7 +1927,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
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, -1);
- save_image_post(op, ibuf, ima, ok_view, true, relbase, relative, do_newpath, filepath);
+ 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 */
@@ -1947,7 +1948,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
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(op, ibuf, ima, ok_view, true, relbase, relative, do_newpath, filepath);
+ 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;
@@ -1961,7 +1962,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
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, -1);
- save_image_post(op, ibuf, ima, ok, true, relbase, relative, do_newpath, simopts->filepath);
+ save_image_post(bmain, op, ibuf, ima, ok, true, relbase, relative, do_newpath, simopts->filepath);
ED_space_image_release_buffer(sima, ibuf, lock);
}
else {
@@ -2054,6 +2055,7 @@ static void image_save_as_free(wmOperator *op)
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;
@@ -2061,9 +2063,9 @@ static int image_save_as_exec(bContext *C, wmOperator *op)
/* just in case to initialize values,
* these should be set on invoke or by the caller. */
- save_image_options_init(&simopts, sima, CTX_data_scene(C), false, false);
+ save_image_options_init(bmain, &simopts, sima, CTX_data_scene(C), false, false);
- save_image_options_from_op(&simopts, op);
+ save_image_options_from_op(bmain, &simopts, op);
save_image_doit(C, sima, op, &simopts, true);
@@ -2080,6 +2082,7 @@ static bool image_save_as_check(bContext *UNUSED(C), wmOperator *op)
static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
+ Main *bmain = CTX_data_main(C);
SpaceImage *sima = CTX_wm_space_image(C);
Image *ima = ED_space_image(sima);
Scene *scene = CTX_data_scene(C);
@@ -2092,7 +2095,7 @@ static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS
save_image_options_defaults(&simopts);
- if (save_image_options_init(&simopts, sima, scene, true, save_as_render) == 0)
+ if (save_image_options_init(bmain, &simopts, sima, scene, true, save_as_render) == 0)
return OPERATOR_CANCELLED;
save_image_options_to_op(&simopts, op);
@@ -2178,7 +2181,7 @@ void IMAGE_OT_save_as(wmOperatorType *ot)
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;
@@ -2203,14 +2206,15 @@ void IMAGE_OT_save_as(wmOperatorType *ot)
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;
save_image_options_defaults(&simopts);
- if (save_image_options_init(&simopts, sima, scene, false, false) == 0)
+ if (save_image_options_init(bmain, &simopts, sima, scene, false, false) == 0)
return OPERATOR_CANCELLED;
- save_image_options_from_op(&simopts, op);
+ 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)) {
@@ -2232,7 +2236,7 @@ void IMAGE_OT_save(wmOperatorType *ot)
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;
@@ -2251,7 +2255,7 @@ static int image_save_sequence_exec(bContext *C, wmOperator *op)
int tot = 0;
char di[FILE_MAX];
struct MovieCacheIter *iter;
-
+
if (sima->image == NULL)
return OPERATOR_CANCELLED;
@@ -2264,7 +2268,7 @@ static int image_save_sequence_exec(bContext *C, wmOperator *op)
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) {
@@ -2281,7 +2285,7 @@ static int image_save_sequence_exec(bContext *C, wmOperator *op)
}
IMB_moviecacheIter_free(iter);
}
-
+
if (tot == 0) {
BKE_report(op->reports, RPT_WARNING, "No images have been changed");
return OPERATOR_CANCELLED;
@@ -2299,7 +2303,7 @@ static int image_save_sequence_exec(bContext *C, wmOperator *op)
char name[FILE_MAX];
BLI_strncpy(name, ibuf->name, sizeof(name));
- BLI_path_abs(name, bmain->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));
@@ -2323,7 +2327,7 @@ void IMAGE_OT_save_sequence(wmOperatorType *ot)
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;
@@ -2336,6 +2340,7 @@ void IMAGE_OT_save_sequence(wmOperatorType *ot)
static int image_reload_exec(bContext *C, wmOperator *UNUSED(op))
{
+ Main *bmain = CTX_data_main(C);
Image *ima = CTX_data_edit_image(C);
SpaceImage *sima = CTX_wm_space_image(C);
@@ -2344,13 +2349,13 @@ static int image_reload_exec(bContext *C, wmOperator *UNUSED(op))
/* XXX unpackImage frees image buffers */
ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
-
+
// XXX other users?
- BKE_image_signal(ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_RELOAD);
+ 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);
-
+
return OPERATOR_FINISHED;
}
@@ -2360,7 +2365,7 @@ void IMAGE_OT_reload(wmOperatorType *ot)
ot->name = "Reload Image";
ot->idname = "IMAGE_OT_reload";
ot->description = "Reload current image from disk";
-
+
/* api callbacks */
ot->exec = image_reload_exec;
@@ -2438,16 +2443,16 @@ static int image_new_exec(bContext *C, wmOperator *op)
RNA_property_update(C, &ptr, prop);
}
else if (sima) {
- ED_space_image_set(sima, scene, obedit, ima);
+ ED_space_image_set(bmain, sima, scene, obedit, ima);
}
else if (gen_context == GEN_CONTEXT_PAINT_CANVAS) {
bScreen *sc;
Object *ob = CTX_data_active_object(C);
-
+
if (scene->toolsettings->imapaint.canvas)
id_us_min(&scene->toolsettings->imapaint.canvas->id);
scene->toolsettings->imapaint.canvas = ima;
-
+
for (sc = bmain->screen.first; sc; sc = sc->id.next) {
ScrArea *sa;
for (sa = sc->areabase.first; sa; sa = sa->next) {
@@ -2455,9 +2460,9 @@ static int image_new_exec(bContext *C, wmOperator *op)
for (sl = sa->spacedata.first; sl; sl = sl->next) {
if (sl->spacetype == SPACE_IMAGE) {
SpaceImage *sima_other = (SpaceImage *)sl;
-
+
if (!sima_other->pin) {
- ED_space_image_set(sima_other, scene, obedit, ima);
+ ED_space_image_set(bmain, sima_other, scene, obedit, ima);
}
}
}
@@ -2471,8 +2476,8 @@ static int image_new_exec(bContext *C, wmOperator *op)
if (scene->toolsettings->imapaint.stencil)
id_us_min(&scene->toolsettings->imapaint.stencil->id);
scene->toolsettings->imapaint.stencil = ima;
- BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
- WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
}
else {
Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
@@ -2484,10 +2489,10 @@ static int image_new_exec(bContext *C, wmOperator *op)
}
}
- BKE_image_signal(ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_USER_NEW_IMAGE);
-
+ BKE_image_signal(bmain, ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_USER_NEW_IMAGE);
+
WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima);
-
+
return OPERATOR_FINISHED;
}
@@ -2558,17 +2563,17 @@ void IMAGE_OT_new(wmOperatorType *ot)
{GEN_CONTEXT_PAINT_STENCIL, "PAINT_STENCIL", 0, "Paint Stencil", ""},
{0, NULL, 0, NULL, NULL}
};
-
+
/* 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;
-
+
/* flags */
ot->flag = OPTYPE_UNDO;
@@ -2630,7 +2635,7 @@ static int image_invert_exec(bContext *C, wmOperator *op)
}
/* 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];
@@ -2644,7 +2649,7 @@ static int image_invert_exec(bContext *C, wmOperator *op)
}
}
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];
@@ -2685,11 +2690,11 @@ void IMAGE_OT_invert(wmOperatorType *ot)
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;
-
+
/* properties */
prop = RNA_def_boolean(ot->srna, "invert_r", 0, "Red", "Invert Red Channel");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
@@ -2699,7 +2704,7 @@ void IMAGE_OT_invert(wmOperatorType *ot)
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;
}
@@ -2733,7 +2738,7 @@ static int image_pack_exec(bContext *C, wmOperator *op)
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;
@@ -2785,9 +2790,9 @@ void IMAGE_OT_pack(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Pack Image";
- ot->description = "Pack an image as embedded data into the .blend file";
+ 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;
@@ -2813,7 +2818,7 @@ static int image_unpack_exec(bContext *C, wmOperator *op)
ima = BLI_findstring(&CTX_data_main(C)->image, imaname, offsetof(ID, name) + 2);
if (!ima) ima = CTX_data_edit_image(C);
}
-
+
if (!ima || !BKE_image_has_packedfile(ima))
return OPERATOR_CANCELLED;
@@ -2824,12 +2829,12 @@ static int image_unpack_exec(bContext *C, wmOperator *op)
if (G.fileflags & G_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));
-
- unpackImage(op->reports, ima, method);
-
+
+ unpackImage(CTX_data_main(C), op->reports, ima, method);
+
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
return OPERATOR_FINISHED;
@@ -2841,7 +2846,7 @@ static int image_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
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;
@@ -2862,16 +2867,16 @@ void IMAGE_OT_unpack(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Unpack Image";
- ot->description = "Save an image packed in the .blend file to disk";
+ 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;
/* 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");
RNA_def_string(ot->srna, "id", NULL, MAX_ID_NAME - 2, "Image Name", "Image data-block name to unpack"); /* XXX, weark!, will fail with library, name collisions */
@@ -3074,7 +3079,7 @@ static void image_sample_apply(bContext *C, wmOperator *op, const wmEvent *event
#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) {
@@ -3118,7 +3123,7 @@ static int image_sample_invoke(bContext *C, wmOperator *op, const wmEvent *event
if (!ED_space_image_has_buffer(sima))
return OPERATOR_CANCELLED;
-
+
info = MEM_callocN(sizeof(ImageSampleInfo), "ImageSampleInfo");
info->art = ar->type;
info->draw_handle = ED_region_draw_cb_activate(ar->type, image_sample_draw, info, REGION_DRAW_POST_PIXEL);
@@ -3160,7 +3165,7 @@ void IMAGE_OT_sample(wmOperatorType *ot)
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;
@@ -3182,13 +3187,13 @@ static int image_sample_line_exec(bContext *C, wmOperator *op)
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;
-
+
float x1f, y1f, x2f, y2f;
-
+
if (ibuf == NULL) {
ED_space_image_release_buffer(sima, ibuf, lock);
return OPERATOR_CANCELLED;
@@ -3198,7 +3203,7 @@ static int image_sample_line_exec(bContext *C, wmOperator *op)
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);
@@ -3211,14 +3216,14 @@ static int image_sample_line_exec(bContext *C, wmOperator *op)
hist->flag |= HISTO_FLAG_SAMPLELINE;
BKE_histogram_update_sample_line(hist, ibuf, &scene->view_settings, &scene->display_settings);
-
+
/* reset y zoom */
hist->ymax = 1.0f;
ED_space_image_release_buffer(sima, ibuf, lock);
-
+
ED_area_tag_redraw(CTX_wm_area(C));
-
+
return OPERATOR_FINISHED;
}
@@ -3231,7 +3236,7 @@ static int image_sample_line_invoke(bContext *C, wmOperator *op, const wmEvent *
if (!ED_space_image_has_buffer(sima))
return OPERATOR_CANCELLED;
-
+
return WM_gesture_straightline_invoke(C, op, event);
}
@@ -3241,17 +3246,17 @@ void IMAGE_OT_sample_line(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = 0; /* no undo/register since this operates on the space */
-
+
WM_operator_properties_gesture_straightline(ot, CURSOR_EDIT);
}
@@ -3272,7 +3277,7 @@ void IMAGE_OT_curves_point_set(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* api callbacks */
ot->invoke = image_sample_invoke;
ot->modal = image_sample_modal;
@@ -3298,19 +3303,19 @@ static int image_record_composite_apply(bContext *C, wmOperator *op)
RecordCompositeData *rcd = op->customdata;
Scene *scene = CTX_data_scene(C);
ImBuf *ibuf;
-
+
WM_cursor_time(CTX_wm_window(C), scene->r.cfra);
// XXX scene->nodetree->test_break = BKE_blender_test_break;
// XXX scene->nodetree->test_break = NULL;
-
+
BKE_image_all_free_anim_ibufs(scene->r.cfra);
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));
-
+
ibuf = BKE_image_acquire_ibuf(sima->image, &sima->iuser, NULL);
/* save memory in flipbooks */
if (ibuf)
@@ -3333,7 +3338,7 @@ static int image_record_composite_init(bContext *C, wmOperator *op)
return 0;
if (scene->nodetree == NULL)
return 0;
-
+
op->customdata = rcd = MEM_callocN(sizeof(RecordCompositeData), "ImageRecordCompositeData");
rcd->old_cfra = scene->r.cfra;
@@ -3369,18 +3374,18 @@ static int image_record_composite_exec(bContext *C, wmOperator *op)
{
if (!image_record_composite_init(C, op))
return OPERATOR_CANCELLED;
-
+
while (image_record_composite_apply(C, op)) {}
-
+
image_record_composite_exit(C, op);
-
+
return OPERATOR_FINISHED;
}
static int image_record_composite_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
RecordCompositeData *rcd;
-
+
if (!image_record_composite_init(C, op))
return OPERATOR_CANCELLED;
@@ -3426,7 +3431,7 @@ void IMAGE_OT_record_composite(wmOperatorType *ot)
/* identifiers */
ot->name = "Record Composite";
ot->idname = "IMAGE_OT_record_composite";
-
+
/* api callbacks */
ot->exec = image_record_composite_exec;
ot->invoke = image_record_composite_invoke;
@@ -3458,9 +3463,10 @@ static int image_cycle_render_slot_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
/* no undo push for browsing existing */
- if (ima->renders[ima->render_slot] || ima->render_slot == ima->last_render_slot)
+ 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;
}
@@ -3470,7 +3476,7 @@ void IMAGE_OT_cycle_render_slot(wmOperatorType *ot)
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;
@@ -3481,6 +3487,97 @@ void IMAGE_OT_cycle_render_slot(wmOperatorType *ot)
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);
+
+ if (!BKE_image_clear_renderslot(ima, &sima->iuser, ima->render_slot)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
+
+ 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";
+
+ /* api callbacks */
+ ot->exec = image_clear_render_slot_exec;
+ ot->poll = image_cycle_render_slot_poll;
+
+ /* 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);
+
+ 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);
+
+ 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";
+
+ /* api callbacks */
+ ot->exec = image_add_render_slot_exec;
+ ot->poll = image_cycle_render_slot_poll;
+
+ /* 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);
+
+ if (!BKE_image_remove_renderslot(ima, &sima->iuser, ima->render_slot)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
+
+ 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";
+
+ /* api callbacks */
+ ot->exec = image_remove_render_slot_exec;
+ ot->poll = image_cycle_render_slot_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
+}
+
/********************** change frame operator *********************/
static int change_frame_poll(bContext *C)
@@ -3601,13 +3698,14 @@ void IMAGE_OT_change_frame(wmOperatorType *ot)
/* 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;
- ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
+ ima = BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result");
if (sima->image == NULL) {
- ED_space_image_set(sima, scene, NULL, ima);
+ ED_space_image_set(bmain, sima, scene, NULL, ima);
}
RE_ReadRenderResult(scene, scene);
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index bfbf51487ad..792dc25981e 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -72,12 +72,14 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_message.h"
#include "UI_resources.h"
#include "UI_interface.h"
#include "UI_view2d.h"
#include "image_intern.h"
+#include "GPU_framebuffer.h"
/**************************** common state *****************************/
@@ -116,21 +118,21 @@ ARegion *image_has_buttons_region(ScrArea *sa)
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);
/* is error! */
if (ar == NULL) return NULL;
-
+
arnew = MEM_callocN(sizeof(ARegion), "buttons for image");
-
+
BLI_insertlinkafter(&sa->regionbase, ar, arnew);
arnew->regiontype = RGN_TYPE_UI;
arnew->alignment = RGN_ALIGN_RIGHT;
-
+
arnew->flag = RGN_FLAG_HIDDEN;
-
+
return arnew;
}
@@ -146,17 +148,17 @@ ARegion *image_has_tools_region(ScrArea *sa)
/* is error! */
if (ar == NULL) return NULL;
-
+
arnew = MEM_callocN(sizeof(ARegion), "scopes for image");
-
+
BLI_insertlinkafter(&sa->regionbase, ar, arnew);
arnew->regiontype = RGN_TYPE_TOOLS;
arnew->alignment = RGN_ALIGN_LEFT;
-
+
arnew->flag = RGN_FLAG_HIDDEN;
image_scopes_tag_refresh(sa);
-
+
return arnew;
}
@@ -166,39 +168,39 @@ static SpaceLink *image_new(const ScrArea *UNUSED(area), const Scene *UNUSED(sce
{
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;
+ simage->flag = SI_SHOW_GPENCIL | SI_USE_ALPHA | SI_COORDFLOATS;
simage->iuser.ok = true;
simage->iuser.fie_ima = 2;
simage->iuser.frames = 100;
- simage->iuser.flag = IMA_SHOW_STEREO;
+ simage->iuser.flag = IMA_SHOW_STEREO | IMA_ANIM_ALWAYS;
scopes_new(&simage->scopes);
simage->sample_line_hist.height = 100;
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for image");
-
+
BLI_addtail(&simage->regionbase, ar);
ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = RGN_ALIGN_BOTTOM;
-
+ ar->alignment = RGN_ALIGN_TOP;
+
/* 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;
-
+
/* 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;
@@ -206,16 +208,16 @@ static SpaceLink *image_new(const ScrArea *UNUSED(area), const Scene *UNUSED(sce
/* main area */
ar = MEM_callocN(sizeof(ARegion), "main area for image");
-
+
BLI_addtail(&simage->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
-
+
return (SpaceLink *)simage;
}
/* not spacelink itself */
static void image_free(SpaceLink *sl)
-{
+{
SpaceImage *simage = (SpaceImage *) sl;
scopes_free(&simage->scopes);
@@ -229,13 +231,13 @@ static void image_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
/* add drop boxes */
WM_event_add_dropbox_handler(&sa->handlers, lb);
-
+
}
static SpaceLink *image_duplicate(SpaceLink *sl)
{
SpaceImage *simagen = MEM_dupallocN(sl);
-
+
/* clear or remove stuff from old */
scopes_new(&simagen->scopes);
@@ -267,10 +269,13 @@ static void image_operatortypes(void)
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_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);
@@ -291,21 +296,23 @@ static void image_keymap(struct wmKeyConfig *keyconf)
wmKeyMap *keymap = WM_keymap_find(keyconf, "Image Generic", SPACE_IMAGE, 0);
wmKeyMapItem *kmi;
int i;
-
+
WM_keymap_add_item(keymap, "IMAGE_OT_new", NKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_open", OKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_reload", RKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_read_viewlayers", RKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_save", SKEY, KM_PRESS, KM_ALT, 0);
- WM_keymap_add_item(keymap, "IMAGE_OT_save_as", F3KEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "IMAGE_OT_save_as", SKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_properties", NKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_toolshelf", TKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_menu(keymap, "IMAGE_MT_specials", WKEY, KM_PRESS, 0, 0);
+
WM_keymap_add_item(keymap, "IMAGE_OT_cycle_render_slot", JKEY, KM_PRESS, 0, 0);
RNA_boolean_set(WM_keymap_add_item(keymap, "IMAGE_OT_cycle_render_slot", JKEY, KM_PRESS, KM_ALT, 0)->ptr, "reverse", true);
-
+
keymap = WM_keymap_find(keyconf, "Image", SPACE_IMAGE, 0);
-
+
WM_keymap_add_item(keymap, "IMAGE_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
kmi = WM_keymap_add_item(keymap, "IMAGE_OT_view_all", HOMEKEY, KM_PRESS, KM_SHIFT, 0);
@@ -355,7 +362,7 @@ static void image_keymap(struct wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "toggle", true);
/* fast switch to render slots */
- for (i = 0; i < MIN2(IMA_MAX_RENDER_SLOT, 9); i++) {
+ for (i = 0; i < 9; i++) {
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_int", ONEKEY + i, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "space_data.image.render_slots.active_index");
RNA_int_set(kmi->ptr, "value", i);
@@ -398,7 +405,7 @@ static void image_drop_copy(wmDrag *drag, wmDropBox *drop)
static void image_dropboxes(void)
{
ListBase *lb = WM_dropboxmap_find("Image", SPACE_IMAGE, 0);
-
+
WM_dropbox_add(lb, "IMAGE_OT_open", image_drop_poll, image_drop_copy);
}
@@ -415,7 +422,7 @@ static void image_refresh(const bContext *C, ScrArea *sa)
ima = ED_space_image(sima);
BKE_image_user_check_frame_calc(&sima->iuser, scene->r.cfra, 0);
-
+
/* 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) {
@@ -431,7 +438,7 @@ static void image_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Sc
WorkSpace *workspace)
{
SpaceImage *sima = (SpaceImage *)sa->spacedata.first;
-
+
/* context changes */
switch (wmn->category) {
case NC_WINDOW:
@@ -604,7 +611,7 @@ static void image_main_region_set_view2d(SpaceImage *sima, ARegion *ar)
Image *ima = ED_space_image(sima);
float x1, y1, w, h;
int width, height, winx, winy;
-
+
#if 0
if (image_preview_active(curarea, &width, &height)) {}
else
@@ -613,18 +620,18 @@ static void image_main_region_set_view2d(SpaceImage *sima, ARegion *ar)
w = width;
h = height;
-
+
if (ima)
h *= ima->aspy / ima->aspx;
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.mask.xmin = ar->v2d.mask.ymin = 0;
ar->v2d.mask.xmax = winx;
ar->v2d.mask.ymax = winy;
@@ -635,15 +642,15 @@ static void image_main_region_set_view2d(SpaceImage *sima, ARegion *ar)
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 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;
@@ -655,7 +662,7 @@ static void image_main_region_set_view2d(SpaceImage *sima, ARegion *ar)
static void image_main_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
-
+
// image space manages own v2d
// UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
@@ -685,7 +692,7 @@ static void image_main_region_init(wmWindowManager *wm, ARegion *ar)
keymap = WM_keymap_find(wm->defaultconf, "UV Editor", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
-
+
keymap = WM_keymap_find(wm->defaultconf, "UV Sculpt", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
@@ -713,11 +720,11 @@ static void image_main_region_draw(const bContext *C, ARegion *ar)
/* XXX not supported yet, disabling for now */
scene->r.scemode &= ~R_COMP_CROP;
-
+
/* clear and setup matrix */
UI_GetThemeColor3fv(TH_BACK, col);
- glClearColor(col[0], col[1], col[2], 0.0);
- glClear(GL_COLOR_BUFFER_BIT);
+ GPU_clear_color(col[0], col[1], col[2], 0.0);
+ GPU_clear(GPU_COLOR_BIT);
image_user_refresh_scene(C, sima);
@@ -859,14 +866,14 @@ static void image_buttons_region_init(wmWindowManager *wm, ARegion *ar)
ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
ED_region_panels_init(wm, ar);
-
+
keymap = WM_keymap_find(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)
{
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
static void image_buttons_region_listener(
@@ -910,10 +917,10 @@ static void image_buttons_region_listener(
static void image_tools_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
-
+
ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
ED_region_panels_init(wm, ar);
-
+
keymap = WM_keymap_find(wm->defaultconf, "Image Generic", SPACE_IMAGE, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
@@ -940,8 +947,8 @@ static void image_tools_region_draw(const bContext *C, ARegion *ar)
}
}
ED_space_image_release_buffer(sima, ibuf, lock);
-
- ED_region_panels(C, ar, NULL, -1, true);
+
+ ED_region_panels(C, ar);
}
static void image_tools_region_listener(
@@ -975,10 +982,25 @@ static void image_tools_region_listener(
case NC_NODE:
ED_region_tag_redraw(ar);
break;
-
+
}
}
+static void image_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);
+}
+
+
/************************* header region **************************/
/* add handlers, stuff you only do once or on area/region changes */
@@ -1054,10 +1076,10 @@ 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;
@@ -1078,9 +1100,8 @@ void ED_spacetype_image(void)
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 */
art = MEM_callocN(sizeof(ARegionType), "spacetype image region");
art->regionid = RGN_TYPE_UI;
@@ -1100,6 +1121,7 @@ void ED_spacetype_image(void)
art->prefsizex = 220; // XXX
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
art->listener = image_tools_region_listener;
+ art->message_subscribe = image_tools_region_message_subscribe;
art->init = image_tools_region_init;
art->draw = image_tools_region_draw;
BLI_addhead(&st->regiontypes, art);
@@ -1112,9 +1134,12 @@ void ED_spacetype_image(void)
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/info_draw.c b/source/blender/editors/space_info/info_draw.c
index cd424f45842..ecd0b082df6 100644
--- a/source/blender/editors/space_info/info_draw.c
+++ b/source/blender/editors/space_info/info_draw.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -51,6 +51,7 @@
#include "info_intern.h"
#include "textview.h"
+#include "GPU_framebuffer.h"
/* complicates things a bit, so leaving in old simple code */
#define USE_INFO_NEWLINE
@@ -130,7 +131,7 @@ static int report_textview_begin(TextViewContext *tvc)
tvc->iter = reports->list.last;
UI_ThemeClearColor(TH_BACK);
- glClear(GL_COLOR_BUFFER_BIT);
+ GPU_clear(GPU_COLOR_BIT);
#ifdef USE_INFO_NEWLINE
tvc->iter_tmp = 0;
@@ -236,7 +237,7 @@ static int info_textview_main__internal(struct SpaceInfo *sinfo, ARegion *ar, Re
int draw, int mval[2], void **mouse_pick, int *pos_pick)
{
int ret = 0;
-
+
View2D *v2d = &ar->v2d;
TextViewContext tvc = {0};
@@ -260,7 +261,7 @@ static int info_textview_main__internal(struct SpaceInfo *sinfo, ARegion *ar, Re
tvc.winx = ar->winx - V2D_SCROLL_WIDTH;
ret = textview_draw(&tvc, draw, mval, mouse_pick, pos_pick);
-
+
return ret;
}
diff --git a/source/blender/editors/space_info/info_intern.h b/source/blender/editors/space_info/info_intern.h
index 967bcec57c5..a16acd665b4 100644
--- a/source/blender/editors/space_info/info_intern.h
+++ b/source/blender/editors/space_info/info_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c
index b87a0de23b9..acd0a856f1a 100644
--- a/source/blender/editors/space_info/info_ops.c
+++ b/source/blender/editors/space_info/info_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -87,7 +87,7 @@ void FILE_OT_pack_libraries(wmOperatorType *ot)
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;
@@ -98,9 +98,9 @@ void FILE_OT_pack_libraries(wmOperatorType *ot)
static int unpack_libraries_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
-
+
unpackLibraries(bmain, op->reports);
-
+
return OPERATOR_FINISHED;
}
@@ -115,11 +115,11 @@ void FILE_OT_unpack_libraries(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -131,13 +131,13 @@ static int autopack_toggle_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
if (G.fileflags & G_AUTOPACK) {
- G.fileflags &= ~G_AUTOPACK;
+ G.fileflags &= ~G_AUTOPACK;
}
else {
packAll(bmain, op->reports, true);
G.fileflags |= G_AUTOPACK;
}
-
+
return OPERATOR_FINISHED;
}
@@ -147,10 +147,10 @@ void FILE_OT_autopack_toggle(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -160,9 +160,9 @@ void FILE_OT_autopack_toggle(wmOperatorType *ot)
static int pack_all_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
-
+
packAll(bmain, op->reports, true);
-
+
return OPERATOR_FINISHED;
}
@@ -171,25 +171,25 @@ static int pack_all_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(ev
Main *bmain = CTX_data_main(C);
Image *ima;
ImBuf *ibuf;
-
+
// first check for dirty images
for (ima = bmain->image.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);
}
@@ -199,11 +199,11 @@ void FILE_OT_pack_all(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -238,9 +238,9 @@ static int unpack_all_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
uiLayout *layout;
char title[64];
int count = 0;
-
+
count = countPackedFiles(bmain);
-
+
if (!count) {
BKE_report(op->reports, RPT_WARNING, "No packed files to unpack");
G.fileflags &= ~G_AUTOPACK;
@@ -251,7 +251,7 @@ static int unpack_all_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
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);
@@ -269,7 +269,7 @@ void FILE_OT_unpack_all(wmOperatorType *ot)
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;
@@ -301,18 +301,18 @@ static int unpack_item_exec(bContext *C, wmOperator *op)
int method = RNA_enum_get(op->ptr, "method");
RNA_string_get(op->ptr, "id_name", idname);
- id = BKE_libblock_find_name(type, 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 (method != PF_KEEP)
BKE_unpack_id(bmain, id, op->reports, method); /* XXX PF_ASK can't work here */
-
+
G.fileflags &= ~G_AUTOPACK;
-
+
return OPERATOR_FINISHED;
}
@@ -320,15 +320,15 @@ static int unpack_item_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED
{
uiPopupMenu *pup;
uiLayout *layout;
-
+
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);
-
+
UI_popup_menu_end(C, pup);
-
+
return OPERATOR_INTERFACE;
}
@@ -338,14 +338,14 @@ void FILE_OT_unpack_item(wmOperatorType *ot)
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");
@@ -364,7 +364,7 @@ static int make_paths_relative_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- BKE_bpath_relative_convert(bmain, bmain->name, 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);
@@ -378,7 +378,7 @@ void FILE_OT_make_paths_relative(wmOperatorType *ot)
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;
@@ -397,7 +397,7 @@ static int make_paths_absolute_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- BKE_bpath_absolute_convert(bmain, bmain->name, 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);
@@ -411,7 +411,7 @@ void FILE_OT_make_paths_absolute(wmOperatorType *ot)
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;
@@ -427,7 +427,7 @@ static int report_missing_files_exec(bContext *C, wmOperator *op)
/* run the missing file check */
BKE_bpath_missing_files_check(bmain, op->reports);
-
+
return OPERATOR_FINISHED;
}
@@ -437,7 +437,7 @@ void FILE_OT_report_missing_files(wmOperatorType *ot)
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;
@@ -462,7 +462,7 @@ static int find_missing_files_exec(bContext *C, wmOperator *op)
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);
+ WM_event_add_fileselect(C, op);
return OPERATOR_RUNNING_MODAL;
}
@@ -472,7 +472,7 @@ void FILE_OT_find_missing_files(wmOperatorType *ot)
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;
@@ -490,10 +490,10 @@ void FILE_OT_find_missing_files(wmOperatorType *ot)
/********************* report box operator *********************/
-/* Hard to decide whether to keep this as an operator,
- * or turn it into a hardcoded ui control feature,
+/* Hard to decide whether to keep this as an operator,
+ * or turn it into a hardcoded ui control feature,
* handling TIMER events for all regions in interface_handlers.c
- * Not sure how good that is to be accessing UI data from
+ * Not sure how good that is to be accessing UI data from
* inactive regions, so use this for now. --matt
*/
@@ -513,7 +513,7 @@ static int update_reports_display_invoke(bContext *C, wmOperator *UNUSED(op), co
float neutral_gray = 0.6;
float timeout = 0.0, color_timeout = 0.0;
int send_note = 0;
-
+
/* escape if not our timer */
if ((reports->reporttimer == NULL) ||
(reports->reporttimer != event->customdata) ||
@@ -524,17 +524,17 @@ static int update_reports_display_invoke(bContext *C, wmOperator *UNUSED(op), co
}
rti = (ReportTimerInfo *)reports->reporttimer->customdata;
-
+
timeout = (report->type & RPT_ERROR_ALL) ? ERROR_TIMEOUT : INFO_TIMEOUT;
color_timeout = (report->type & RPT_ERROR_ALL) ? ERROR_COLOR_TIMEOUT : INFO_COLOR_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);
}
@@ -558,14 +558,14 @@ static int update_reports_display_invoke(bContext *C, wmOperator *UNUSED(op), co
rti->grayscale = 0.75;
rti->widthfac = 1.0;
}
-
+
progress = (float)reports->reporttimer->duration / timeout;
color_progress = (float)reports->reporttimer->duration / color_timeout;
-
+
/* save us from too many draws */
if (color_progress <= 1.0f) {
send_note = 1;
-
+
/* fade colors out sharply according to progress through fade-out duration */
interp_v3_v3v3(rti->col, rti->col, neutral_col, color_progress);
rti->grayscale = interpf(neutral_gray, rti->grayscale, color_progress);
@@ -577,11 +577,11 @@ static int update_reports_display_invoke(bContext *C, wmOperator *UNUSED(op), co
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);
}
@@ -591,13 +591,13 @@ void INFO_OT_reports_display_update(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = 0;
-
+
/* properties */
}
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index c7d4fa1465b..3830e6d2792 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -34,9 +34,11 @@
#include "DNA_curve_types.h"
#include "DNA_group_types.h"
#include "DNA_lattice_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
#include "DNA_scene_types.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
@@ -47,7 +49,6 @@
#include "BKE_blender_version.h"
#include "BKE_curve.h"
#include "BKE_displist.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_key.h"
#include "BKE_layer.h"
#include "BKE_paint.h"
@@ -69,7 +70,7 @@ typedef struct SceneStats {
int totface, totfacesel;
int totbone, totbonesel;
int totobj, totobjsel;
- int totlamp, totlampsel;
+ int totlamp, totlampsel;
int tottri;
char infostr[MAX_INFO_LEN];
@@ -91,15 +92,15 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
switch (ob->type) {
case OB_MESH:
{
- /* we assume derivedmesh is already built, this strictly does stats now. */
- DerivedMesh *dm = ob->derivedFinal;
+ /* we assume evaluated mesh is already built, this strictly does stats now. */
+ Mesh *me_eval = ob->runtime.mesh_eval;
int totvert, totedge, totface, totloop;
- if (dm) {
- totvert = dm->getNumVerts(dm);
- totedge = dm->getNumEdges(dm);
- totface = dm->getNumPolys(dm);
- totloop = dm->getNumLoops(dm);
+ if (me_eval) {
+ totvert = me_eval->totvert;
+ totedge = me_eval->totedge;
+ totface = me_eval->totpoly;
+ totloop = me_eval->totloop;
stats->totvert += totvert * totob;
stats->totedge += totedge * totob;
@@ -153,10 +154,10 @@ static void stats_object_edit(Object *obedit, SceneStats *stats)
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;
@@ -169,15 +170,15 @@ static void stats_object_edit(Object *obedit, SceneStats *stats)
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 */
@@ -226,7 +227,7 @@ static void stats_object_edit(Object *obedit, SceneStats *stats)
/* 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++;
@@ -240,7 +241,7 @@ static void stats_object_edit(Object *obedit, SceneStats *stats)
int a;
bp = editlatt->def;
-
+
a = editlatt->pntsu * editlatt->pntsv * editlatt->pntsw;
while (a--) {
stats->totvert++;
@@ -271,36 +272,26 @@ static void stats_object_sculpt_dynamic_topology(Object *ob, SceneStats *stats)
stats->tottri = ob->sculpt->bm->totface;
}
-static void stats_dupli_object_group_count(SceneCollection *scene_collection, int *count)
+static void stats_dupli_object_group_count(Collection *collection, int *count)
{
- for (LinkData *link = scene_collection->objects.first; link; link = link->next) {
- (*count)++;
- }
+ *count += BLI_listbase_count(&collection->gobject);
- SceneCollection *scene_collection_nested;
- for (scene_collection_nested = scene_collection->scene_collections.first;
- scene_collection_nested;
- scene_collection_nested = scene_collection_nested->next)
- {
- stats_dupli_object_group_count(scene_collection_nested, count);
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ stats_dupli_object_group_count(child->collection, count);
}
}
-static void stats_dupli_object_group_doit(SceneCollection *scene_collection, SceneStats *stats, ParticleSystem *psys,
+static void stats_dupli_object_group_doit(Collection *collection, SceneStats *stats, ParticleSystem *psys,
const int totgroup, int *cur)
{
- for (LinkData *link = scene_collection->objects.first; link; link = link->next) {
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
int tot = count_particles_mod(psys, totgroup, *cur);
- stats_object(link->data, 0, tot, stats);
+ stats_object(cob->ob, 0, tot, stats);
(*cur)++;
}
- SceneCollection *scene_collection_nested;
- for (scene_collection_nested = scene_collection->scene_collections.first;
- scene_collection_nested;
- scene_collection_nested = scene_collection_nested->next)
- {
- stats_dupli_object_group_doit(scene_collection_nested, stats, psys, totgroup, cur);
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ stats_dupli_object_group_doit(child->collection, stats, psys, totgroup, cur);
}
}
@@ -323,12 +314,12 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
else if (part->draw_as == PART_DRAW_GR && part->dup_group) {
int totgroup = 0, cur = 0;
- SceneCollection *scene_collection = part->dup_group->collection;
- stats_dupli_object_group_count(scene_collection, &totgroup);
- stats_dupli_object_group_doit(scene_collection, stats, psys, totgroup, &cur);
+ Collection *collection = part->dup_group;
+ stats_dupli_object_group_count(collection, &totgroup);
+ stats_dupli_object_group_doit(collection, stats, psys, totgroup, &cur);
}
}
-
+
stats_object(ob, base->flag & BASE_SELECTED, 1, stats);
stats->totobj++;
}
@@ -353,7 +344,7 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
stats->totobj += tot;
stats_object(ob, base->flag & BASE_SELECTED, tot, stats);
}
- else if ((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) {
+ else if ((ob->transflag & OB_DUPLICOLLECTION) && ob->dup_group) {
/* Dupli Group */
int tot = count_duplilist(ob);
stats->totobj += tot;
@@ -396,7 +387,7 @@ static void stats_update(ViewLayer *view_layer)
else {
/* Objects */
for (base = view_layer->object_bases.first; base; base = base->next)
- if (base->flag & BASE_VISIBLED) {
+ if (base->flag & BASE_VISIBLE) {
stats_dupli_object(base, base->object, &stats);
}
}
@@ -419,6 +410,7 @@ static void stats_string(ViewLayer *view_layer)
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;
@@ -454,27 +446,34 @@ static void stats_string(ViewLayer *view_layer)
/* get memory statistics */
- ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, IFACE_(" | Mem:%.2fM"),
- (double)((mem_in_use - mmap_in_use) >> 10) / 1024.0);
- if (mmap_in_use)
- BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" (%.2fM)"), (double)((mmap_in_use) >> 10) / 1024.0);
+ 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);
- ofs = BLI_snprintf(gpumemstr, MAX_INFO_MEM_LEN, IFACE_(" | Free GPU Mem:%.2fM"), (double)((gpu_free_mem)) / 1024.0);
+ 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_snprintf(gpumemstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_("/%.2fM"), (double)((gpu_tot_memory)) / 1024.0);
+ 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;
- ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, "%s | ", versionstr);
+ if (ob) {
+ ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, "%s | ", ob->id.name + 2);
+ }
if (obedit) {
if (BKE_keyblock_from_object(obedit))
@@ -508,15 +507,13 @@ static void stats_string(ViewLayer *view_layer)
}
else {
ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs,
- IFACE_("Verts:%s | Faces:%s | Tris:%s | Objects:%s/%s | Lamps:%s/%s%s%s"),
+ 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, stats_fmt.totlampsel,
- stats_fmt.totlamp, memstr, gpumemstr);
+ stats_fmt.totobj, memstr, gpumemstr);
}
- if (ob)
- BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, " | %s", ob->id.name + 2);
+ ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, " | %s", versionstr);
#undef MAX_INFO_MEM_LEN
}
diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c
index 96a0a1ed3ec..c9a94878512 100644
--- a/source/blender/editors/space_info/space_info.c
+++ b/source/blender/editors/space_info/space_info.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -60,6 +60,7 @@
#include "info_intern.h" /* own include */
#include "BLO_readfile.h"
+#include "GPU_framebuffer.h"
/* ******************** default callbacks for info space ***************** */
@@ -67,7 +68,7 @@ static SpaceLink *info_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scen
{
ARegion *ar;
SpaceInfo *sinfo;
-
+
sinfo = MEM_callocN(sizeof(SpaceInfo), "initinfo");
sinfo->spacetype = SPACE_INFO;
@@ -75,17 +76,17 @@ static SpaceLink *info_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scen
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for info");
-
+
BLI_addtail(&sinfo->regionbase, ar);
ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = RGN_ALIGN_BOTTOM;
-
+ ar->alignment = RGN_ALIGN_TOP;
+
/* main region */
ar = MEM_callocN(sizeof(ARegion), "main region for info");
-
+
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 */
@@ -96,15 +97,15 @@ static SpaceLink *info_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scen
/* 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;
}
/* not spacelink itself */
static void info_free(SpaceLink *UNUSED(sl))
-{
+{
// SpaceInfo *sinfo = (SpaceInfo *) sl;
-
+
}
@@ -117,9 +118,9 @@ static void info_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
static SpaceLink *info_duplicate(SpaceLink *sl)
{
SpaceInfo *sinfon = MEM_dupallocN(sl);
-
+
/* clear or remove stuff from old */
-
+
return (SpaceLink *)sinfon;
}
@@ -132,7 +133,7 @@ static void info_main_region_init(wmWindowManager *wm, ARegion *ar)
/* 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);
/* own keymap */
@@ -157,12 +158,12 @@ static void info_main_region_draw(const bContext *C, ARegion *ar)
/* clear and setup matrix */
UI_ThemeClearColor(TH_BACK);
- glClear(GL_COLOR_BUFFER_BIT);
+ GPU_clear(GPU_COLOR_BIT);
/* quick way to avoid drawing if not bug enough */
if (ar->winy < 16)
return;
-
+
info_textview_update_rect(C, ar);
/* worlks best with no view2d matrix set */
@@ -172,7 +173,7 @@ static void info_main_region_draw(const bContext *C, ARegion *ar)
/* reset view matrix */
UI_view2d_view_restore(C);
-
+
/* scrollers */
scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_GRID_CLAMP);
UI_view2d_scrollers_draw(C, v2d, scrollers);
@@ -187,7 +188,7 @@ static void info_operatortypes(void)
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);
@@ -207,20 +208,22 @@ static void info_operatortypes(void)
static void info_keymap(struct wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_find(keyconf, "Window", 0, 0);
-
+
WM_keymap_verify_item(keymap, "INFO_OT_reports_display_update", TIMERREPORT, KM_ANY, KM_ANY, 0);
/* info space */
keymap = WM_keymap_find(keyconf, "Info", SPACE_INFO, 0);
-
-
+
+
/* report selection */
WM_keymap_add_item(keymap, "INFO_OT_select_pick", SELECTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "INFO_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "INFO_OT_select_border", BKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "INFO_OT_report_replay", RKEY, KM_PRESS, 0, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "INFO_OT_report_delete", XKEY, KM_PRESS, 0, 0);
+#endif
WM_keymap_add_item(keymap, "INFO_OT_report_delete", DELKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "INFO_OT_report_copy", CKEY, KM_PRESS, KM_CTRL, 0);
#ifdef __APPLE__
@@ -263,7 +266,7 @@ static void info_header_listener(
/* context changes */
switch (wmn->category) {
case NC_SCREEN:
- if (ELEM(wmn->data, ND_LAYER, ND_SCREENCAST, ND_ANIMPLAY)) {
+ if (ELEM(wmn->data, ND_LAYER, ND_ANIMPLAY)) {
ED_region_tag_redraw(ar);
}
break;
@@ -284,7 +287,7 @@ static void info_header_listener(
ED_region_tag_redraw(ar);
break;
}
-
+
}
static void info_header_region_message_subscribe(
@@ -337,17 +340,17 @@ void ED_spacetype_info(void)
{
SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype info");
ARegionType *art;
-
+
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;
-
+
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype info region");
art->regionid = RGN_TYPE_WINDOW;
@@ -358,20 +361,20 @@ void ED_spacetype_info(void)
art->listener = info_main_region_listener;
BLI_addhead(&st->regiontypes, art);
-
+
/* 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;
-
+
BLI_addhead(&st->regiontypes, art);
-
+
recent_files_menu_register();
BKE_spacetype_register(st);
diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c
index 3f35cadd820..a1e3842f887 100644
--- a/source/blender/editors/space_info/textview.c
+++ b/source/blender/editors/space_info/textview.c
@@ -40,6 +40,7 @@
#include "BLI_string_utf8.h"
#include "GPU_immediate.h"
+#include "GPU_state.h"
#include "BIF_gl.h"
@@ -63,7 +64,7 @@ typedef struct ConsoleDrawContext {
int ymin, ymax;
int *xy; // [2]
int *sel; // [2]
- int *pos_pick; // bottom of view == 0, top of file == combine chars, end of line is lower then start.
+ int *pos_pick; // bottom of view == 0, top of file == combine chars, end of line is lower then start.
const int *mval; // [2]
int draw;
} ConsoleDrawContext;
@@ -81,8 +82,8 @@ static void console_draw_sel(const char *str, const int sel[2], const int xy[2],
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));
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
@@ -93,7 +94,7 @@ static void console_draw_sel(const char *str, const int sel[2], const int xy[2],
immUnbindProgram();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
}
@@ -181,14 +182,14 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
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) {
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
@@ -219,7 +220,7 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
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 */
@@ -227,7 +228,7 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
}
cdc->xy[1] += cdc->lheight;
-
+
/* check if were out of view bounds */
if (cdc->xy[1] > cdc->ymax) {
MEM_freeN(offsets);
@@ -254,7 +255,7 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
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];
diff --git a/source/blender/editors/space_info/textview.h b/source/blender/editors/space_info/textview.h
index 2f9e518ed47..55f69fbf444 100644
--- a/source/blender/editors/space_info/textview.h
+++ b/source/blender/editors/space_info/textview.h
@@ -37,7 +37,7 @@ typedef struct TextViewContext {
int winx;
int ymin, ymax;
-
+
/* callbacks */
int (*begin)(struct TextViewContext *tvc);
void (*end)(struct TextViewContext *tvc);
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index 9551a1cf362..cafb40626ee 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation, Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
@@ -87,27 +87,27 @@ bool nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA *nlt_p
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)
+
+ /* 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)
+ 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
+
+ /* 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 */
@@ -122,7 +122,7 @@ bool nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA *nlt_p
NlaStrip *strip = BKE_nlastrip_find_active(nlt);
RNA_pointer_create(ale->id, &RNA_NlaStrip, strip, strip_ptr);
}
-
+
found = 1;
break;
}
@@ -149,7 +149,7 @@ bool nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA *nlt_p
/* 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;
@@ -158,13 +158,13 @@ bool nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA *nlt_p
/* 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
+
+ /* 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;
@@ -172,14 +172,14 @@ bool nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA *nlt_p
break;
}
}
-
+
if (found > 0)
break;
}
-
+
/* free temp data */
ANIM_animdata_freelist(&anim_data);
-
+
return (found != 0);
}
@@ -212,12 +212,12 @@ static int nla_strip_actclip_panel_poll(const bContext *C, PanelType *UNUSED(pt)
{
PointerRNA ptr;
NlaStrip *strip;
-
+
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);
}
@@ -226,17 +226,17 @@ static int nla_strip_eval_panel_poll(const bContext *C, PanelType *UNUSED(pt))
{
PointerRNA ptr;
NlaStrip *strip;
-
+
if (!nla_panel_context(C, NULL, NULL, &ptr))
return 0;
if (ptr.data == NULL)
return 0;
-
+
strip = ptr.data;
-
+
if (strip->type == NLASTRIP_TYPE_SOUND)
return 0;
-
+
return 1;
}
@@ -250,53 +250,53 @@ static void nla_panel_animdata(const bContext *C, Panel *pa)
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
+
+ /* 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, "", VICO_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);
-
+
/* 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);
@@ -309,14 +309,14 @@ static void nla_panel_track(const bContext *C, Panel *pa)
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;
-
+
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);
@@ -330,41 +330,41 @@ static void nla_panel_properties(const bContext *C, Panel *pa)
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 + autoblending
* - blend in/out can only be set when autoblending is off
*/
@@ -376,7 +376,7 @@ static void nla_panel_properties(const bContext *C, Panel *pa)
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")));
@@ -398,27 +398,27 @@ static void nla_panel_actclip(const bContext *C, Panel *pa)
/* 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);
@@ -438,13 +438,13 @@ static void nla_panel_evaluation(const bContext *C, Panel *pa)
/* 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);
-
+
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);
@@ -472,28 +472,28 @@ static void nla_panel_modifiers(const bContext *C, Panel *pa)
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);
}
}
@@ -565,7 +565,7 @@ static int nla_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = nla_has_buttons_region(sa);
-
+
if (ar)
ED_region_toggle_hidden(C, ar);
@@ -574,10 +574,10 @@ static int nla_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
void NLA_OT_properties(wmOperatorType *ot)
{
- ot->name = "Properties";
+ 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;
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index 1cc3d5142f5..d3725704636 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
* All rights reserved.
*
- *
+ *
* Contributor(s): Joshua Leung (major recode)
*
* ***** END GPL LICENSE BLOCK *****
@@ -80,26 +80,26 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
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) {
@@ -107,7 +107,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
{
Scene *sce = (Scene *)ale->data;
AnimData *adt = sce->adt;
-
+
/* set selection status */
if (selectmode == SELECT_INVERT) {
/* swap select */
@@ -118,7 +118,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
sce->flag |= SCE_DS_SELECTED;
if (adt) adt->flag |= ADT_UI_SELECTED;
}
-
+
notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
break;
}
@@ -128,14 +128,14 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
Base *base = (Base *)ale->data;
Object *ob = base->object;
AnimData *adt = ob->adt;
-
- if (nlaedit_is_tweakmode_on(ac) == 0 && (base->flag & BASE_SELECTABLED)) {
+
+ 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 {
@@ -146,19 +146,19 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
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);
}
@@ -195,12 +195,12 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
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;
}
@@ -209,7 +209,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
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 */
@@ -220,25 +220,25 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
}
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);
}
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);
}
@@ -253,11 +253,11 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
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);
}
@@ -266,7 +266,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
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) {
@@ -279,13 +279,13 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
/* 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;
}
/* OR rest of name... */
else {
- /* NOTE: rest of NLA-Action name doubles for operating on the AnimData block
+ /* 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
@@ -296,7 +296,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
if (nlaedit_is_tweakmode_on(ac)) {
/* exit tweakmode immediately */
nlaedit_disable_tweakmode(ac, true);
-
+
/* changes to NLA-Action occurred */
notifierFlags |= ND_NLA_ACTCHANGE;
}
@@ -311,11 +311,11 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
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);
}
}
@@ -326,10 +326,10 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
printf("Error: Invalid channel type in mouse_nla_channels()\n");
break;
}
-
+
/* free channels */
ANIM_animdata_freelist(&anim_data);
-
+
/* return the notifier-flags set */
return notifierFlags;
}
@@ -347,55 +347,55 @@ static int nlachannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmEv
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
+
+ /* 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;
-
+
/* 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;
-
+
/* 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);
@@ -411,15 +411,15 @@ static int nlachannels_pushdown_exec(bContext *C, wmOperator *op)
bAnimContext ac;
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 "
@@ -435,11 +435,11 @@ static int nlachannels_pushdown_exec(bContext *C, wmOperator *op)
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) {
@@ -452,14 +452,14 @@ static int nlachannels_pushdown_exec(bContext *C, wmOperator *op)
ANIM_animdata_freelist(&anim_data);
return OPERATOR_CANCELLED;
}
-
+
/* grab AnimData from the channel */
adt = ale->adt;
-
+
/* 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");
@@ -478,7 +478,7 @@ static int nlachannels_pushdown_exec(bContext *C, wmOperator *op)
/* 'push-down' action - only usable when not in TweakMode */
BKE_nla_action_pushdown(adt);
}
-
+
/* set notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
return OPERATOR_FINISHED;
@@ -490,14 +490,14 @@ void NLA_OT_action_pushdown(wmOperatorType *ot)
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",
@@ -512,7 +512,7 @@ static int nla_action_unlink_poll(bContext *C)
if (ED_operator_nla_active(C)) {
return nla_panel_context(C, NULL, NULL, NULL);
}
-
+
/* something failed... */
return false;
}
@@ -521,22 +521,22 @@ static int nla_action_unlink_exec(bContext *C, wmOperator *op)
{
PointerRNA adt_ptr;
AnimData *adt;
-
+
/* 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;
-
+
/* 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;
}
@@ -550,19 +550,19 @@ static int nla_action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *
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",
+ 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);
}
@@ -578,17 +578,17 @@ bool nlaedit_add_tracks_existing(bAnimContext *ac, bool above_sel)
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
*/
@@ -605,10 +605,10 @@ bool nlaedit_add_tracks_existing(bAnimContext *ac, bool above_sel)
}
}
}
-
+
/* free temp data */
ANIM_animdata_freelist(&anim_data);
-
+
return added;
}
@@ -619,18 +619,18 @@ bool nlaedit_add_tracks_empty(bAnimContext *ac)
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 */
@@ -638,10 +638,10 @@ bool nlaedit_add_tracks_empty(bAnimContext *ac)
added = true;
}
}
-
+
/* cleanup */
ANIM_animdata_freelist(&anim_data);
-
+
return added;
}
@@ -652,20 +652,20 @@ 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) {
/* set notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
-
+
/* done */
return OPERATOR_FINISHED;
}
@@ -673,7 +673,7 @@ static int nlaedit_add_tracks_exec(bContext *C, wmOperator *op)
/* 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;
}
@@ -685,14 +685,14 @@ void NLA_OT_tracks_add(wmOperatorType *ot)
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");
}
@@ -703,42 +703,42 @@ 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);
}
}
-
+
/* free temp 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;
}
@@ -749,11 +749,11 @@ void NLA_OT_tracks_delete(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -762,10 +762,10 @@ void NLA_OT_tracks_delete(wmOperatorType *ot)
/* AnimData Related Operators */
/* ******************** Include Objects Operator ***************************** */
-/* Include selected objects in NLA Editor, by giving them AnimData blocks
+/* Include selected objects in NLA Editor, by giving them AnimData blocks
* NOTE: This doesn't help for non-object AnimData, where we do not have any effective
* selection mechanism in place. Unfortunately, this means that non-object AnimData
- * once again becomes a second-class citizen here. However, at least for the most
+ * once again becomes a second-class citizen here. However, at least for the most
* common use case, we now have a nice shortcut again.
*/
@@ -773,28 +773,28 @@ 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... */
+
+ /* 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;
}
@@ -805,11 +805,11 @@ void NLA_OT_selected_objects_add(wmOperatorType *ot)
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;
-
+
/* 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 a7773aaaed5..16fb3576ae8 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
* All rights reserved.
*
- *
+ *
* Contributor(s): Joshua Leung (major recode)
*
* ***** END GPL LICENSE BLOCK *****
@@ -58,6 +58,7 @@
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_draw.h"
+#include "GPU_state.h"
#include "WM_types.h"
@@ -74,7 +75,7 @@
/* Action-Line ---------------------- */
-/* get colors for drawing Action-Line
+/* get colors for drawing Action-Line
* NOTE: color returned includes fine-tuned alpha!
*/
void nla_action_get_color(AnimData *adt, bAction *act, float color[4])
@@ -93,7 +94,7 @@ void nla_action_get_color(AnimData *adt, bAction *act, float color[4])
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;
@@ -111,8 +112,8 @@ static void nla_action_draw_keyframes(AnimData *adt, bAction *act, float y, floa
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
+ /* 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];
@@ -181,7 +182,7 @@ static void nla_actionclip_draw_markers(NlaStrip *strip, float yminc, float ymax
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
immUniform1i("num_colors", 0); /* "simple" mode */
@@ -212,8 +213,8 @@ static void nla_actionclip_draw_markers(NlaStrip *strip, float yminc, float ymax
/* Markers inside a NLA-Strip */
static void nla_strip_draw_markers(NlaStrip *strip, float yminc, float ymaxc)
{
- glLineWidth(2.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;
@@ -231,8 +232,8 @@ static void nla_strip_draw_markers(NlaStrip *strip, float yminc, float ymaxc)
}
}
}
-
- glLineWidth(1.0f);
+
+ GPU_line_width(1.0f);
}
/* Strips (Proper) ---------------------- */
@@ -303,18 +304,18 @@ static void nla_strip_get_color_inside(AnimData *adt, NlaStrip *strip, float col
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 */
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
-
+ 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(GWN_PRIM_LINE_STRIP, abs((int)(strip->end - strip->start) + 1));
@@ -343,7 +344,7 @@ static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc, uns
}
else
immVertex2f(pos, strip->start, ymaxc);
-
+
/* end of strip */
if (IS_EQF(strip->blendout, 0.0f) == 0) {
immVertex2f(pos, strip->end - strip->blendout, ymaxc);
@@ -357,8 +358,8 @@ static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc, uns
}
/* turn off AA'd lines */
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
+ GPU_line_smooth(false);
+ GPU_blend(false);
}
/* helper call to setup dashed-lines for strip outlines */
@@ -367,27 +368,27 @@ 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 = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
-
+
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
-
+
immUniform1i("num_colors", 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);
- glLineWidth(1.5f);
+ GPU_line_width(1.5f);
}
else {
/* solid line */
immUniform1f("dash_factor", 2.0f);
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
}
-
+
return shdr_pos;
}
@@ -398,26 +399,26 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
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 = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_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... */
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
+ 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
+ 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 */
@@ -429,12 +430,12 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
ATTR_FALLTHROUGH;
/* this only draws after the strip */
- case NLASTRIP_EXTEND_HOLD_FORWARD:
+ 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);
@@ -442,7 +443,7 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
break;
}
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
@@ -461,10 +462,10 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
else {
/* strip is in disabled track - make less visible */
immUniformColor3fvAlpha(color, 0.1f);
-
- glEnable(GL_BLEND);
+
+ GPU_blend(true);
immRectf(shdr_pos, strip->start, yminc, strip->end, ymaxc);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
@@ -494,7 +495,7 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
color[0] = color[1] = color[2] = 0.0f; /* FIXME: or 1.0f ?? */
}
- /* draw outline
+ /* draw outline
* - dashed-line shader is loaded after this block
*/
if (muted) {
@@ -505,7 +506,7 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
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);
}
@@ -537,7 +538,7 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
/* 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)
+ /* 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) {
@@ -569,7 +570,7 @@ static void nla_draw_strip_text(
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);
@@ -577,7 +578,7 @@ static void nla_draw_strip_text(
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;
@@ -585,14 +586,14 @@ static void nla_draw_strip_text(
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
+ /* set bounding-box for text
* - padding of 2 'units' on either side
*/
/* TODO: make this centered? */
@@ -618,8 +619,8 @@ static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, V
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.
+ * 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
*/
@@ -639,32 +640,32 @@ 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
+ * - 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)
+
+ /* 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) )
@@ -677,7 +678,7 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
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)) {
@@ -686,13 +687,13 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
/* 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),
+
+ /* 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)
@@ -711,8 +712,8 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
/* 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
*/
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
+ 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];
@@ -723,10 +724,10 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
* but also slightly shorter for some more contrast when viewing the strips
*/
immRectf(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
-
+
/* draw 'embossed' lines above and below the strip for effect */
/* white base-lines */
- glLineWidth(2.0f);
+ GPU_line_width(2.0f);
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.3f);
immBegin(GWN_PRIM_LINES, 4);
immVertex2f(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP);
@@ -736,7 +737,7 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
immEnd();
/* black top-lines */
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
immUniformColor3f(0.0f, 0.0f, 0.0f);
immBegin(GWN_PRIM_LINES, 4);
immVertex2f(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP);
@@ -752,7 +753,7 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
/* draw keyframes in the action */
nla_action_draw_keyframes(adt, ale->data, y, yminc + NLACHANNEL_SKIP, ymaxc - NLACHANNEL_SKIP);
- glDisable(GL_BLEND);
+ GPU_blend(false);
break;
}
}
@@ -761,7 +762,7 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
/* adjust y-position for next one */
y -= NLACHANNEL_STEP(snla);
}
-
+
/* free tempolary channels */
ANIM_animdata_freelist(&anim_data);
}
@@ -774,40 +775,40 @@ 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
+ * - 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)
+ /* 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) )
@@ -815,7 +816,7 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
/* 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++;
@@ -824,18 +825,18 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
{ /* second pass: UI widgets */
uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
size_t channel_index = 0;
-
+
y = (float)(-NLACHANNEL_HEIGHT(snla));
-
+
/* set blending again, as may not be set in previous step */
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
-
+ 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) )
@@ -843,18 +844,18 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
/* draw all channels using standard channel-drawing API */
ANIM_channel_draw_widgets(C, ac, ale, block, yminc, ymaxc, channel_index);
}
-
+
/* adjust y-position for next one */
y -= NLACHANNEL_STEP(snla);
channel_index++;
}
-
+
UI_block_end(C, block);
UI_block_draw(C, block);
-
- glDisable(GL_BLEND);
+
+ 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 c86e9872c0a..23cd504978c 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
* All rights reserved.
*
- *
+ *
* Contributor(s): Joshua Leung (major recode)
*
* ***** END GPL LICENSE BLOCK *****
@@ -83,15 +83,15 @@ void ED_nla_postop_refresh(bAnimContext *ac)
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);
-
+
for (ale = anim_data.first; ale; ale = ale->next) {
/* performing auto-blending, extend-mode validation, etc. */
BKE_nla_validate_state(ale->data);
}
-
+
/* free temp memory */
ANIM_animdata_freelist(&anim_data);
}
@@ -100,62 +100,62 @@ void ED_nla_postop_refresh(bAnimContext *ac)
/* 'Special' Editing */
/* ******************** Tweak-Mode Operators ***************************** */
-/* 'Tweak mode' allows the action referenced by the active NLA-strip to be edited
- * as if it were the normal Active-Action of its AnimData block.
+/* 'Tweak mode' allows the action referenced by the active NLA-strip to be edited
+ * as if it were the normal Active-Action of its AnimData block.
*/
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);
}
}
}
-
+
/* free temp data */
ANIM_animdata_freelist(&anim_data);
-
- /* if we managed to enter tweakmode on at least one AnimData block,
+
+ /* 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);
}
@@ -163,27 +163,27 @@ static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op)
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, "
@@ -198,47 +198,47 @@ bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
- int filter;
-
+ 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))
+ (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);
}
-
+
/* free temp data */
ANIM_animdata_freelist(&anim_data);
-
- /* if we managed to enter tweakmode on at least one AnimData block,
+
+ /* 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;
}
@@ -247,40 +247,40 @@ bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo)
static int nlaedit_disable_tweakmode_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
-
+
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;
-
+
/* perform operation */
ok = nlaedit_disable_tweakmode(&ac, do_solo);
-
+
/* 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 "
@@ -300,38 +300,38 @@ static void get_nlastrip_extents(bAnimContext *ac, float *min, float *max, const
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) {
@@ -352,40 +352,40 @@ 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;
}
-
+
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";
-
+
/* api callbacks */
ot->exec = nlaedit_previewrange_exec;
ot->poll = ED_operator_nla_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -404,33 +404,33 @@ static bool nla_channels_get_selected_extents(bAnimContext *ac, float *min, floa
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
-
+
SpaceNla *snla = (SpaceNla *)ac->sl;
const float half_height = NLACHANNEL_HEIGHT_HALF(snla);
short found = 0; /* NOTE: not bool, since we want prioritise individual channels over expanders */
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) &&
+ 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
*/
@@ -438,14 +438,14 @@ static bool nla_channels_get_selected_extents(bAnimContext *ac, float *min, floa
break;
}
}
-
+
/* adjust y-position for next one */
y -= NLACHANNEL_STEP(snla);
}
-
+
/* free all temp data */
ANIM_animdata_freelist(&anim_data);
-
+
return (found != 0);
}
@@ -454,19 +454,19 @@ 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... */
@@ -477,30 +477,30 @@ static int nlaedit_viewall(bContext *C, const bool only_sel)
/* 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);
}
@@ -510,18 +510,18 @@ static int nlaedit_viewsel_exec(bContext *C, wmOperator *UNUSED(op))
/* 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";
-
+
/* api callbacks */
ot->exec = nlaedit_viewall_exec;
ot->poll = ED_operator_nla_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -532,11 +532,11 @@ void NLA_OT_view_selected(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -556,11 +556,11 @@ void NLA_OT_view_frame(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -577,7 +577,7 @@ static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
Scene *scene;
-
+
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
size_t items;
@@ -586,17 +586,17 @@ static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op)
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)->action, 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);
@@ -610,68 +610,68 @@ static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op)
"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
+ * - 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,
+ 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
+
+ /* 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,
+ 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),
+ /* 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);
-
+
/* set notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
-
+
/* done */
return OPERATOR_FINISHED;
}
@@ -684,15 +684,15 @@ void NLA_OT_actionclip_add(wmOperatorType *ot)
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", "");
@@ -707,45 +707,45 @@ 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,
+ /* 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))
@@ -753,48 +753,48 @@ static int nlaedit_add_transition_exec(bContext *C, wmOperator *op)
/* 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
+
+ /* generic settings
* - selected flag to highlight this to the user
- * - auto-blends to ensure that blend in/out values are automatically
+ * - 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;
}
@@ -810,11 +810,11 @@ void NLA_OT_transition_add(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -825,66 +825,66 @@ void NLA_OT_transition_add(wmOperatorType *ot)
static int nlaedit_add_sound_exec(bContext *C, wmOperator *UNUSED(op))
{
bAnimContext ac;
-
+
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
-
+
Scene *scene;
int cfra;
-
+
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
+
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);
-
+
/* 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;
-
+
/* 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);
-
+
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),
+ /* 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);
-
+
/* set notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
-
+
/* done */
return OPERATOR_FINISHED;
}
@@ -895,11 +895,11 @@ void NLA_OT_soundclip_add(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -911,28 +911,28 @@ void NLA_OT_soundclip_add(wmOperatorType *ot)
static int nlaedit_add_meta_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);
-
+
/* 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);
-
+
/* name the metas */
for (strip = nlt->strips.first; strip; strip = strip->next) {
/* auto-name this strip if selected (that means it is a meta) */
@@ -940,13 +940,13 @@ static int nlaedit_add_meta_exec(bContext *C, wmOperator *UNUSED(op))
BKE_nlastrip_validate_name(adt, strip);
}
}
-
+
/* free temp 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;
}
@@ -957,11 +957,11 @@ void NLA_OT_meta_add(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -972,33 +972,33 @@ void NLA_OT_meta_add(wmOperatorType *ot)
static int nlaedit_remove_meta_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);
-
+
/* 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);
}
-
+
/* free temp 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;
}
@@ -1009,11 +1009,11 @@ void NLA_OT_meta_remove(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1022,27 +1022,27 @@ void NLA_OT_meta_remove(wmOperatorType *ot)
/* Duplicates the selected NLA-Strips, putting them on new tracks above the one
* the originals were housed in.
*/
-
+
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
+
+ /* 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) {
@@ -1050,46 +1050,46 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *op)
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(strip, linked);
-
+ nstrip = BKE_nlastrip_copy(ac.bmain, strip, linked);
+
/* 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
+ * - 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);
-
+
/* set notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
-
+
/* done */
return OPERATOR_FINISHED;
}
@@ -1100,7 +1100,7 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *op)
static int nlaedit_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
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);
@@ -1113,18 +1113,18 @@ void NLA_OT_duplicate(wmOperatorType *ot)
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", "");
}
@@ -1135,52 +1135,52 @@ void NLA_OT_duplicate(wmOperatorType *ot)
static int nlaedit_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;
-
+
/* 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 (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))
+ if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION))
BKE_nlastrip_free(&nlt->strips, strip->prev);
if ((nstrip) && (nstrip->type == NLASTRIP_TYPE_TRANSITION)) {
nstrip = nstrip->next;
BKE_nlastrip_free(&nlt->strips, strip->next);
}
-
+
/* finally, delete this strip */
BKE_nlastrip_free(&nlt->strips, 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;
}
@@ -1191,29 +1191,29 @@ void NLA_OT_delete(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Split Strips Operator ***************************** */
/* Splits the selected NLA-Strips into two strips at the midpoint of the strip */
-// TODO's?
+// TODO's?
// - multiple splits
// - variable-length splits?
/* split a given Action-Clip strip */
-static void nlaedit_split_strip_actclip(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
+
+ /* 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 */
@@ -1223,14 +1223,14 @@ static void nlaedit_split_strip_actclip(AnimData *adt, NlaTrack *nlt, NlaStrip *
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))
@@ -1238,28 +1238,28 @@ static void nlaedit_split_strip_actclip(AnimData *adt, NlaTrack *nlt, NlaStrip *
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(strip, true);
+ nstrip = BKE_nlastrip_copy(bmain, strip, true);
BLI_insertlinkafter(&nlt->strips, strip, nstrip);
-
- /* set the endpoint of the first strip and the start of the new strip
+
+ /* set the endpoint of the first strip and the start of the new strip
* to the splitframe 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);
}
@@ -1276,56 +1276,56 @@ static void nlaedit_split_strip_meta(NlaTrack *nlt, NlaStrip *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(adt, nlt, strip, (float)ac.scene->r.cfra);
+ 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;
}
@@ -1336,11 +1336,11 @@ void NLA_OT_split(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1351,34 +1351,34 @@ void NLA_OT_split(wmOperatorType *ot)
static int nlaedit_bake_exec(bContext *C, wmOperator *UNUSED(op))
{
bAnimContext ac;
-
+
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
// int flag = 0;
-
+
/* 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_ANIMDATA | ANIMFILTER_FOREDIT);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
+
/* for each AnimData block, bake strips to animdata... */
for (ale = anim_data.first; ale; ale = ale->next) {
//BKE_nla_bake(ac.scene, ale->id, ale->data, flag);
}
-
+
/* 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;
}
@@ -1390,11 +1390,11 @@ static void UNUSED_FUNCTION(NLA_OT_bake)(wmOperatorType *ot)
ot->name = "Bake Strips";
ot->idname = "NLA_OT_bake";
ot->description = "Bake all strips of selected AnimData blocks";
-
+
/* api callbacks */
ot->exec = nlaedit_bake_exec;
ot->poll = nlaop_poll_tweakmode_off;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1408,44 +1408,44 @@ static void UNUSED_FUNCTION(NLA_OT_bake)(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;
}
@@ -1456,11 +1456,11 @@ void NLA_OT_mute_toggle(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1471,35 +1471,35 @@ 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,
+
+ /* 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))
{
@@ -1507,13 +1507,13 @@ static int nlaedit_swap_exec(bContext *C, wmOperator *op)
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) {
@@ -1530,10 +1530,10 @@ static int nlaedit_swap_exec(bContext *C, wmOperator *op)
}
}
}
-
+
if (strip) {
/* too many selected warning */
- BKE_reportf(op->reports, RPT_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);
}
@@ -1548,11 +1548,11 @@ static int nlaedit_swap_exec(bContext *C, wmOperator *op)
}
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;
@@ -1560,16 +1560,16 @@ static int nlaedit_swap_exec(bContext *C, wmOperator *op)
/* 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]) &&
+ 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);
@@ -1586,25 +1586,25 @@ static int nlaedit_swap_exec(bContext *C, wmOperator *op)
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;
}
@@ -1615,11 +1615,11 @@ void NLA_OT_swap(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1630,19 +1630,19 @@ 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
*/
@@ -1650,15 +1650,15 @@ static int nlaedit_move_up_exec(bContext *C, wmOperator *UNUSED(op))
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)) {
@@ -1669,16 +1669,16 @@ static int nlaedit_move_up_exec(bContext *C, wmOperator *UNUSED(op))
}
}
}
-
+
/* 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;
}
@@ -1689,11 +1689,11 @@ void NLA_OT_move_up(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1704,19 +1704,19 @@ 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
*/
@@ -1724,15 +1724,15 @@ static int nlaedit_move_down_exec(bContext *C, wmOperator *UNUSED(op))
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)) {
@@ -1743,16 +1743,16 @@ static int nlaedit_move_down_exec(bContext *C, wmOperator *UNUSED(op))
}
}
}
-
+
/* 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;
}
@@ -1763,11 +1763,11 @@ void NLA_OT_move_down(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1778,26 +1778,26 @@ 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) {
@@ -1808,27 +1808,27 @@ static int nlaedit_sync_actlen_exec(bContext *C, wmOperator *op)
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)
+ 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);
}
}
}
-
+
/* free temp 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;
}
@@ -1839,14 +1839,14 @@ void NLA_OT_action_sync_length(wmOperatorType *ot)
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");
}
@@ -1858,19 +1858,19 @@ 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;
-
+
/* 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
@@ -1878,34 +1878,34 @@ static int nlaedit_make_single_user_exec(bContext *C, wmOperator *UNUSED(op))
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)
+ 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;
}
}
}
}
-
+
/* free temp 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;
}
@@ -1916,12 +1916,12 @@ void NLA_OT_make_single_user(wmOperatorType *ot)
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;
}
@@ -1934,12 +1934,12 @@ 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;
-
+
/* 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;
}
@@ -1948,61 +1948,61 @@ 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;
-
+
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)
+ 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;
}
-
+
/* 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
+ * but leave everything else alone
*/
strip->scale = 1.0f;
calc_action_range(strip->act, &strip->actstart, &strip->actend, 0);
}
}
}
-
+
/* free temp 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;
}
@@ -2013,11 +2013,11 @@ void NLA_OT_apply_scale(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -2028,44 +2028,44 @@ void NLA_OT_apply_scale(wmOperatorType *ot)
static int nlaedit_clear_scale_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);
-
+
/* 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;
-
+
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);
-
+
/* 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;
}
@@ -2076,11 +2076,11 @@ void NLA_OT_clear_scale(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -2100,27 +2100,27 @@ static const EnumPropertyItem prop_nlaedit_snap_types[] = {
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};
@@ -2128,23 +2128,23 @@ static int nlaedit_snap_exec(bContext *C, wmOperator *op)
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 */
@@ -2163,54 +2163,54 @@ static int nlaedit_snap_exec(bContext *C, wmOperator *op)
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;
}
@@ -2221,15 +2221,15 @@ void NLA_OT_snap(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", prop_nlaedit_snap_types, 0, "Type", "");
}
@@ -2244,31 +2244,31 @@ static const EnumPropertyItem *nla_fmodifier_itemf(bContext *C, PointerRNA *UNUS
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;
}
@@ -2276,28 +2276,28 @@ static const EnumPropertyItem *nla_fmodifier_itemf(bContext *C, PointerRNA *UNUS
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) {
@@ -2310,14 +2310,14 @@ static int nla_fmodifier_add_exec(bContext *C, wmOperator *op)
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;
@@ -2329,37 +2329,37 @@ static int nla_fmodifier_add_exec(bContext *C, wmOperator *op)
}
}
}
-
+
/* 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;
-
+ 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");
}
@@ -2372,36 +2372,36 @@ static int nla_fmodifier_copy_exec(bContext *C, wmOperator *op)
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");
@@ -2412,21 +2412,21 @@ static int nla_fmodifier_copy_exec(bContext *C, wmOperator *op)
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";
-
+
/* api callbacks */
ot->exec = nla_fmodifier_copy_exec;
- ot->poll = nlaop_poll_tweakmode_off;
-
+ ot->poll = nlaop_poll_tweakmode_off;
+
/* 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");
}
@@ -2439,23 +2439,23 @@ static int nla_fmodifier_paste_exec(bContext *C, wmOperator *op)
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) {
@@ -2468,17 +2468,17 @@ static int nla_fmodifier_paste_exec(bContext *C, wmOperator *op)
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);
@@ -2489,24 +2489,24 @@ static int nla_fmodifier_paste_exec(bContext *C, wmOperator *op)
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",
+ 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 806fbe90ff2..c090b3b8106 100644
--- a/source/blender/editors/space_nla/nla_intern.h
+++ b/source/blender/editors/space_nla/nla_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation, Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
@@ -159,4 +159,3 @@ void nla_operatortypes(void);
void nla_keymap(wmKeyConfig *keyconf);
#endif /* __NLA_INTERN_H__ */
-
diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c
index 48037a10b2d..8109cff58fb 100644
--- a/source/blender/editors/space_nla/nla_ops.c
+++ b/source/blender/editors/space_nla/nla_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
* All rights reserved.
*
- *
+ *
* Contributor(s): Joshua Leung (major recode)
*
* ***** END GPL LICENSE BLOCK *****
@@ -55,21 +55,21 @@
int nlaop_poll_tweakmode_off(bContext *C)
{
Scene *scene;
-
- /* for now, we check 2 things:
+
+ /* for now, we check 2 things:
* 1) active editor must be NLA
- * 2) tweakmode is currently set as a 'per-scene' flag
+ * 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
+ * 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;
}
@@ -77,21 +77,21 @@ int nlaop_poll_tweakmode_off(bContext *C)
int nlaop_poll_tweakmode_on(bContext *C)
{
Scene *scene;
-
- /* for now, we check 2 things:
+
+ /* for now, we check 2 things:
* 1) active editor must be NLA
- * 2) tweakmode is currently set as a 'per-scene' flag
+ * 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
+ * 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;
}
@@ -109,61 +109,61 @@ void nla_operatortypes(void)
{
/* view */
WM_operatortype_append(NLA_OT_properties);
-
+
/* 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_tracks_add);
WM_operatortype_append(NLA_OT_tracks_delete);
-
+
WM_operatortype_append(NLA_OT_selected_objects_add);
-
+
/* select */
WM_operatortype_append(NLA_OT_click_select);
WM_operatortype_append(NLA_OT_select_border);
WM_operatortype_append(NLA_OT_select_all_toggle);
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);
-
+
WM_operatortype_append(NLA_OT_previewrange_set);
-
+
/* 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_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_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_action_sync_length);
-
+
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_snap);
-
+
WM_operatortype_append(NLA_OT_fmodifier_add);
WM_operatortype_append(NLA_OT_fmodifier_copy);
WM_operatortype_append(NLA_OT_fmodifier_paste);
@@ -176,7 +176,7 @@ static void nla_keymap_channels(wmKeyMap *keymap)
wmKeyMapItem *kmi;
/* keymappings here are NLA-specific (different to standard channels keymap) */
-
+
/* selection --------------------------------------------------------------------- */
/* click-select */
// XXX for now, only leftmouse....
@@ -184,30 +184,32 @@ static void nla_keymap_channels(wmKeyMap *keymap)
RNA_boolean_set(kmi->ptr, "extend", false);
kmi = WM_keymap_add_item(keymap, "NLA_OT_channels_click", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "extend", true);
-
+
/* channel operations ------------------------------------------------------------ */
/* add tracks */
kmi = WM_keymap_add_item(keymap, "NLA_OT_tracks_add", AKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "above_selected", false);
kmi = WM_keymap_add_item(keymap, "NLA_OT_tracks_add", AKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "above_selected", true);
-
+
/* delete tracks */
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "NLA_OT_tracks_delete", XKEY, KM_PRESS, 0, 0);
+#endif
WM_keymap_add_item(keymap, "NLA_OT_tracks_delete", DELKEY, KM_PRESS, 0, 0);
}
static void nla_keymap_main(wmKeyConfig *keyconf, wmKeyMap *keymap)
{
wmKeyMapItem *kmi;
-
+
/* selection ------------------------------------------------ */
/* click select */
kmi = WM_keymap_add_item(keymap, "NLA_OT_click_select", SELECTMOUSE, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "extend", false);
kmi = WM_keymap_add_item(keymap, "NLA_OT_click_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "extend", true);
-
+
/* select left/right */
kmi = WM_keymap_add_item(keymap, "NLA_OT_select_leftright", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "extend", false);
@@ -215,92 +217,94 @@ static void nla_keymap_main(wmKeyConfig *keyconf, wmKeyMap *keymap)
kmi = WM_keymap_add_item(keymap, "NLA_OT_select_leftright", SELECTMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "extend", true);
RNA_enum_set(kmi->ptr, "mode", NLAEDIT_LRSEL_TEST);
-
+
kmi = WM_keymap_add_item(keymap, "NLA_OT_select_leftright", LEFTBRACKETKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "extend", false);
RNA_enum_set(kmi->ptr, "mode", NLAEDIT_LRSEL_LEFT);
kmi = WM_keymap_add_item(keymap, "NLA_OT_select_leftright", RIGHTBRACKETKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "extend", false);
RNA_enum_set(kmi->ptr, "mode", NLAEDIT_LRSEL_RIGHT);
-
-
+
+
/* deselect all */
/* TODO: uniformize with other select_all ops? */
kmi = WM_keymap_add_item(keymap, "NLA_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "invert", false);
kmi = WM_keymap_add_item(keymap, "NLA_OT_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "invert", true);
-
+
/* borderselect */
kmi = WM_keymap_add_item(keymap, "NLA_OT_select_border", BKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "axis_range", false);
kmi = WM_keymap_add_item(keymap, "NLA_OT_select_border", BKEY, KM_PRESS, KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "axis_range", true);
-
+
/* view ---------------------------------------------------- */
/* auto-set range */
WM_keymap_add_item(keymap, "NLA_OT_previewrange_set", PKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
-
+
WM_keymap_add_item(keymap, "NLA_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
#ifdef WITH_INPUT_NDOF
WM_keymap_add_item(keymap, "NLA_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0);
#endif
WM_keymap_add_item(keymap, "NLA_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "NLA_OT_view_frame", PAD0, KM_PRESS, 0, 0);
-
+
/* editing ------------------------------------------------ */
-
+
/* add strips */
WM_keymap_add_item(keymap, "NLA_OT_actionclip_add", AKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "NLA_OT_transition_add", TKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "NLA_OT_soundclip_add", KKEY, KM_PRESS, KM_SHIFT, 0);
-
+
/* meta-strips */
WM_keymap_add_item(keymap, "NLA_OT_meta_add", GKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "NLA_OT_meta_remove", GKEY, KM_PRESS, KM_ALT, 0);
-
+
/* duplicate */
kmi = WM_keymap_add_item(keymap, "NLA_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "linked", false);
-
+
kmi = WM_keymap_add_item(keymap, "NLA_OT_duplicate", DKEY, KM_PRESS, KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "linked", true);
-
+
/* single user */
WM_keymap_add_item(keymap, "NLA_OT_make_single_user", UKEY, KM_PRESS, 0, 0);
-
+
/* delete */
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "NLA_OT_delete", XKEY, KM_PRESS, 0, 0);
+#endif
WM_keymap_add_item(keymap, "NLA_OT_delete", DELKEY, KM_PRESS, 0, 0);
/* split */
WM_keymap_add_item(keymap, "NLA_OT_split", YKEY, KM_PRESS, 0, 0);
-
+
/* toggles */
WM_keymap_add_item(keymap, "NLA_OT_mute_toggle", HKEY, KM_PRESS, 0, 0);
-
+
/* swap */
WM_keymap_add_item(keymap, "NLA_OT_swap", FKEY, KM_PRESS, KM_ALT, 0);
-
+
/* move up */
WM_keymap_add_item(keymap, "NLA_OT_move_up", PAGEUPKEY, KM_PRESS, 0, 0);
/* move down */
WM_keymap_add_item(keymap, "NLA_OT_move_down", PAGEDOWNKEY, KM_PRESS, 0, 0);
-
+
/* apply scale */
WM_keymap_add_item(keymap, "NLA_OT_apply_scale", AKEY, KM_PRESS, KM_CTRL, 0);
/* clear scale */
WM_keymap_add_item(keymap, "NLA_OT_clear_scale", SKEY, KM_PRESS, KM_ALT, 0);
-
+
/* snap */
WM_keymap_add_item(keymap, "NLA_OT_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
-
+
/* add f-modifier */
WM_keymap_add_item(keymap, "NLA_OT_fmodifier_add", MKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
-
+
/* transform system */
transform_keymap_for_space(keyconf, keymap, SPACE_NLA);
-
+
/* special markers hotkeys for anim editors: see note in definition of this function */
ED_marker_keymap_animedit_conflictfree(keymap);
}
@@ -311,35 +315,35 @@ void nla_keymap(wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
wmKeyMapItem *kmi;
-
+
/* keymap for all regions ------------------------------------------- */
keymap = WM_keymap_find(keyconf, "NLA Generic", SPACE_NLA, 0);
-
+
/* region management */
WM_keymap_add_item(keymap, "NLA_OT_properties", NKEY, KM_PRESS, 0, 0);
-
+
/* tweakmode
* - enter and exit are separate operators with the same hotkey...
* This works as they use different poll()'s
*/
WM_keymap_add_item(keymap, "NLA_OT_tweakmode_enter", TABKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "NLA_OT_tweakmode_exit", TABKEY, KM_PRESS, 0, 0);
-
+
/* tweakmode for stashed actions
* - similar to normal tweakmode, except we mark the tracks as being "solo"
* too so that the action can be edited in isolation
*/
kmi = WM_keymap_add_item(keymap, "NLA_OT_tweakmode_enter", TABKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "isolate_action", true);
-
+
kmi = WM_keymap_add_item(keymap, "NLA_OT_tweakmode_exit", TABKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "isolate_action", true);
-
+
/* find (i.e. a shortcut for setting the name filter) */
WM_keymap_add_item(keymap, "ANIM_OT_channels_find", FKEY, KM_PRESS, KM_CTRL, 0);
-
+
/* channels ---------------------------------------------------------- */
- /* Channels are not directly handled by the NLA Editor module, but are inherited from the Animation module.
+ /* 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.
*
@@ -347,7 +351,7 @@ void nla_keymap(wmKeyConfig *keyconf)
*/
keymap = WM_keymap_find(keyconf, "NLA Channels", SPACE_NLA, 0);
nla_keymap_channels(keymap);
-
+
/* data ------------------------------------------------------------- */
keymap = WM_keymap_find(keyconf, "NLA Editor", SPACE_NLA, 0);
nla_keymap_main(keyconf, keymap);
diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c
index e09e4417d5d..f22c211af64 100644
--- a/source/blender/editors/space_nla/nla_select.c
+++ b/source/blender/editors/space_nla/nla_select.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
* All rights reserved.
*
- *
+ *
* Contributor(s): Joshua Leung (major recode)
*
* ***** END GPL LICENSE BLOCK *****
@@ -89,12 +89,12 @@ enum {
DESELECT_STRIPS_TEST,
DESELECT_STRIPS_CLEARACTIVE,
} /*eDeselectNlaStrips*/;
-
+
/* Deselects strips in the NLA Editor
* - This is called by the deselect all operator, as well as other ones!
*
* - test: check if select or deselect all (1) or clear all active (2)
- * - sel: how to select keyframes
+ * - sel: how to select keyframes
* 0 = deselect
* 1 = select
* 2 = invert
@@ -105,20 +105,20 @@ static void deselect_nla_strips(bAnimContext *ac, short test, short sel)
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) {
@@ -126,32 +126,32 @@ static void deselect_nla_strips(bAnimContext *ac, short test, short sel)
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);
}
@@ -161,37 +161,37 @@ static void deselect_nla_strips(bAnimContext *ac, short test, short sel)
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 */
if (RNA_boolean_get(op->ptr, "invert"))
deselect_nla_strips(&ac, DESELECT_STRIPS_NOTEST, SELECT_INVERT);
else
deselect_nla_strips(&ac, DESELECT_STRIPS_TEST, SELECT_ADD);
-
+
/* 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_toggle(wmOperatorType *ot)
{
/* identifiers */
ot->name = "(De)select All";
ot->idname = "NLA_OT_select_all_toggle";
ot->description = "Select or deselect all NLA-Strips";
-
+
/* api callbacks */
ot->exec = nlaedit_deselectall_exec;
ot->poll = nlaop_poll_tweakmode_off;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER /*|OPTYPE_UNDO*/;
-
+
/* props */
ot->prop = RNA_def_boolean(ot->srna, "invert", 0, "Invert", "");
RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
@@ -218,27 +218,27 @@ static void borderselect_nla_strips(bAnimContext *ac, rcti rect, short mode, sho
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 border select */
for (ale = anim_data.first; ale; ale = ale->next) {
ymin = ymax - NLACHANNEL_STEP(snla);
-
+
/* perform vertical suitability check (if applicable) */
if ((mode == NLA_BORDERSEL_FRAMERANGE) ||
!((ymax < rectf.ymin) || (ymin > rectf.ymax)))
@@ -247,7 +247,7 @@ static void borderselect_nla_strips(bAnimContext *ac, rcti rect, short mode, sho
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_BORDERSEL_CHANNELS) ||
@@ -255,18 +255,18 @@ static void borderselect_nla_strips(bAnimContext *ac, rcti rect, short mode, sho
{
/* 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);
}
@@ -280,7 +280,7 @@ static int nlaedit_borderselect_exec(bContext *C, wmOperator *op)
short mode = 0, 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;
@@ -302,7 +302,7 @@ static int nlaedit_borderselect_exec(bContext *C, wmOperator *op)
/* selection 'mode' depends on whether borderselect 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
+ /* 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...
@@ -312,17 +312,17 @@ static int nlaedit_borderselect_exec(bContext *C, wmOperator *op)
else
mode = NLA_BORDERSEL_CHANNELS;
}
- else
+ else
mode = NLA_BORDERSEL_ALLSTRIPS;
-
+
/* apply borderselect action */
borderselect_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_border(wmOperatorType *ot)
{
@@ -330,21 +330,21 @@ void NLA_OT_select_border(wmOperatorType *ot)
ot->name = "Border Select";
ot->idname = "NLA_OT_select_border";
ot->description = "Use box selection to grab NLA-Strips";
-
+
/* api callbacks */
ot->invoke = WM_gesture_border_invoke;
ot->exec = nlaedit_borderselect_exec;
ot->modal = WM_gesture_border_modal;
ot->cancel = WM_gesture_border_cancel;
-
+
ot->poll = nlaop_poll_tweakmode_off;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* rna */
WM_operator_properties_gesture_border_select(ot);
-
+
RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
}
@@ -366,24 +366,24 @@ static void nlaedit_select_leftright(bContext *C, bAnimContext *ac, short leftri
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;
@@ -393,19 +393,19 @@ static void nlaedit_select_leftright(bContext *C, bAnimContext *ac, short leftri
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)) {
@@ -413,7 +413,7 @@ static void nlaedit_select_leftright(bContext *C, bAnimContext *ac, short leftri
}
}
}
-
+
/* Cleanup */
ANIM_animdata_freelist(&anim_data);
}
@@ -425,28 +425,28 @@ static int nlaedit_select_leftright_exec(bContext *C, wmOperator *op)
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;
-
+
/* 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;
-
+
/* 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);
-
+
return OPERATOR_FINISHED;
}
@@ -454,18 +454,18 @@ static int nlaedit_select_leftright_invoke(bContext *C, wmOperator *op, const wm
{
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)
@@ -473,7 +473,7 @@ static int nlaedit_select_leftright_invoke(bContext *C, wmOperator *op, const wm
else
RNA_enum_set(op->ptr, "mode", NLAEDIT_LRSEL_RIGHT);
}
-
+
/* perform selection */
return nlaedit_select_leftright_exec(C, op);
}
@@ -481,24 +481,24 @@ static int nlaedit_select_leftright_invoke(bContext *C, wmOperator *op, const wm
void NLA_OT_select_leftright(wmOperatorType *ot)
{
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";
-
+
/* 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;
-
+
/* 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);
}
@@ -512,7 +512,7 @@ static void mouse_nla_strips(bContext *C, bAnimContext *ac, const int mval[2], s
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale = NULL;
int filter;
-
+
SpaceNla *snla = (SpaceNla *)ac->sl;
View2D *v2d = &ac->ar->v2d;
Scene *scene = ac->scene;
@@ -520,22 +520,22 @@ static void mouse_nla_strips(bContext *C, bAnimContext *ac, const int mval[2], s
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)
+
+ /* 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) {
@@ -548,65 +548,65 @@ static void mouse_nla_strips(bContext *C, bAnimContext *ac, const int mval[2], s
/* found some channel - we only really should do somethign 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...
+ * - 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);
}
@@ -626,7 +626,7 @@ static int nlaedit_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent
/* 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 */
@@ -637,33 +637,33 @@ static int nlaedit_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent
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;
-
+
/* identifiers */
- ot->name = "Mouse Select";
+ 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;
-
+
/* 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);
diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c
index 331fae606af..62144db0577 100644
--- a/source/blender/editors/space_nla/space_nla.c
+++ b/source/blender/editors/space_nla/space_nla.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -63,6 +63,7 @@
#include "UI_view2d.h"
#include "nla_intern.h" /* own include */
+#include "GPU_framebuffer.h"
/* ******************** manage regions ********************* */
@@ -78,15 +79,15 @@ ARegion *nla_has_buttons_region(ScrArea *sa)
/* is error! */
if (ar == NULL) return NULL;
-
+
arnew = MEM_callocN(sizeof(ARegion), "buttons for nla");
-
+
BLI_insertlinkafter(&sa->regionbase, ar, arnew);
arnew->regiontype = RGN_TYPE_UI;
arnew->alignment = RGN_ALIGN_RIGHT;
-
+
arnew->flag = RGN_FLAG_HIDDEN;
-
+
return arnew;
}
@@ -98,58 +99,58 @@ static SpaceLink *nla_new(const ScrArea *sa, const Scene *scene)
{
ARegion *ar;
SpaceNla *snla;
-
+
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;
-
+
/* set auto-snapping settings */
snla->autosnap = SACTSNAP_FRAME;
-
+
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for nla");
-
+
BLI_addtail(&snla->regionbase, ar);
ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = RGN_ALIGN_BOTTOM;
-
+ ar->alignment = 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;
-
+
/* 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");
-
+
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");
-
+
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.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] = 10000.0f;
@@ -161,15 +162,15 @@ static SpaceLink *nla_new(const ScrArea *sa, const Scene *scene)
ar->v2d.keepofs = V2D_KEEPOFS_Y;
ar->v2d.align = V2D_ALIGN_NO_POS_Y;
ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
-
+
return (SpaceLink *)snla;
}
/* not spacelink itself */
static void nla_free(SpaceLink *sl)
-{
+{
SpaceNla *snla = (SpaceNla *) sl;
-
+
if (snla->ads) {
BLI_freelistN(&snla->ads->chanbase);
MEM_freeN(snla->ads);
@@ -178,14 +179,14 @@ static void nla_free(SpaceLink *sl)
/* spacetype; init callback */
-static void nla_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
+static void nla_init(struct wmWindowManager *wm, ScrArea *sa)
{
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 *)G.main->scene.first; // XXX this is bad, but we need this to be set correct
+ snla->ads->source = (ID *)WM_window_get_active_scene(wm->winactive);
}
ED_area_tag_refresh(sa);
@@ -194,10 +195,10 @@ static void nla_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
static SpaceLink *nla_duplicate(SpaceLink *sl)
{
SpaceNla *snlan = MEM_dupallocN(sl);
-
+
/* clear or remove stuff from old */
snlan->ads = MEM_dupallocN(snlan->ads);
-
+
return (SpaceLink *)snlan;
}
@@ -205,12 +206,12 @@ static SpaceLink *nla_duplicate(SpaceLink *sl)
static void nla_channel_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
-
+
/* 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);
-
+
/* own keymap */
/* own channels map first to override some channel keymaps */
keymap = WM_keymap_find(wm->defaultconf, "NLA Channels", SPACE_NLA, 0);
@@ -218,7 +219,7 @@ static void nla_channel_region_init(wmWindowManager *wm, ARegion *ar)
/* now generic channels map for everything else that can apply */
keymap = WM_keymap_find(wm->defaultconf, "Animation Channels", 0, 0);
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
-
+
keymap = WM_keymap_find(wm->defaultconf, "NLA Generic", SPACE_NLA, 0);
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
@@ -229,21 +230,21 @@ static void nla_channel_region_draw(const bContext *C, ARegion *ar)
bAnimContext ac;
View2D *v2d = &ar->v2d;
View2DScrollers *scrollers;
-
+
/* clear and setup matrix */
UI_ThemeClearColor(TH_BACK);
- glClear(GL_COLOR_BUFFER_BIT);
-
+ GPU_clear(GPU_COLOR_BIT);
+
UI_view2d_view_ortho(v2d);
-
+
/* data */
if (ANIM_animdata_get_context(C, &ac)) {
draw_nla_channel_list(C, &ac, ar);
}
-
+
/* reset view matrix */
UI_view2d_view_restore(C);
-
+
/* scrollers */
scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
UI_view2d_scrollers_draw(C, v2d, scrollers);
@@ -255,9 +256,9 @@ static void nla_channel_region_draw(const bContext *C, ARegion *ar)
static void nla_main_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
-
+
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
-
+
/* own keymap */
keymap = WM_keymap_find(wm->defaultconf, "NLA Editor", SPACE_NLA, 0);
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
@@ -275,59 +276,59 @@ static void nla_main_region_draw(const bContext *C, ARegion *ar)
View2DGrid *grid;
View2DScrollers *scrollers;
short unit = 0, cfra_flag = 0;
-
+
/* clear and setup matrix */
UI_ThemeClearColor(TH_BACK);
- glClear(GL_COLOR_BUFFER_BIT);
-
+ 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);
ED_markers_draw(C, DRAW_MARKERS_MARGIN);
-
+
/* 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, 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);
@@ -351,16 +352,16 @@ static void nla_header_region_draw(const bContext *C, ARegion *ar)
static void nla_buttons_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
-
+
ED_region_panels_init(wm, ar);
-
+
keymap = WM_keymap_find(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, NULL, -1, true);
+ ED_region_panels(C, ar);
}
static void nla_region_listener(
@@ -527,6 +528,41 @@ static void nla_channel_region_listener(
}
}
+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__);
+ }
+ }
+}
+
/* editor level listener */
static void nla_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene),
WorkSpace *UNUSED(workspace))
@@ -568,10 +604,10 @@ static void nla_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scen
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 = (Group *)new_id;
+ snla->ads->filter_grp = (Collection *)new_id;
}
if ((ID *)snla->ads->source == old_id) {
snla->ads->source = new_id;
@@ -584,10 +620,10 @@ 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;
@@ -607,30 +643,31 @@ void ED_spacetype_nla(void)
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;
@@ -639,11 +676,11 @@ void ED_spacetype_nla(void)
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/drawnode.c b/source/blender/editors/space_node/drawnode.c
index ca6ae5955a9..12da5086c52 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -56,6 +56,7 @@
#include "GPU_batch.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -94,7 +95,7 @@ static void node_buts_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *p
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);
}
@@ -106,14 +107,14 @@ static void node_buts_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr
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);
}
static void node_buts_mix_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
-{
+{
uiLayout *row, *col;
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
@@ -134,7 +135,7 @@ static void node_buts_time(uiLayout *layout, bContext *UNUSED(C), PointerRNA *pt
/* 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)
@@ -194,7 +195,7 @@ static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA *
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);
}
@@ -205,9 +206,9 @@ static void node_browse_tex_cb(bContext *C, void *ntree_v, void *node_v)
bNodeTree *ntree = ntree_v;
bNode *node = node_v;
Tex *tex;
-
+
if (node->menunr < 1) return;
-
+
if (node->id) {
id_us_min(node->id);
node->id = NULL;
@@ -217,16 +218,16 @@ static void node_browse_tex_cb(bContext *C, void *ntree_v, void *node_v)
node->id = &tex->id;
id_us_plus(node->id);
BLI_strncpy(node->name, node->id->name + 2, sizeof(node->name));
-
+
nodeSetActive(ntree, node);
-
+
if (ntree->type == NTREE_TEXTURE)
ntreeTexCheckCyclics(ntree);
-
+
// allqueue(REDRAWBUTSSHADING, 0);
// allqueue(REDRAWNODE, 0);
- NodeTagChanged(ntree, node);
-
+ NodeTagChanged(ntree, node);
+
node->menunr = 0;
}
#endif
@@ -241,9 +242,9 @@ static void node_buts_texture(uiLayout *layout, bContext *UNUSED(C), PointerRNA
(node->type != CMP_NODE_TEXTURE) &&
(node->type != TEX_NODE_TEXTURE)
);
-
+
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);
@@ -251,7 +252,7 @@ static void node_buts_texture(uiLayout *layout, bContext *UNUSED(C), PointerRNA
}
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);
}
@@ -271,7 +272,7 @@ static int node_resize_area_default(bNode *node, int x, int y)
const float size = 10.0f;
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)
@@ -300,11 +301,11 @@ static void node_draw_frame_prepare(const bContext *UNUSED(C), bNodeTree *ntree,
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 */
@@ -313,14 +314,14 @@ static void node_draw_frame_prepare(const bContext *UNUSED(C), bNodeTree *ntree,
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;
@@ -330,13 +331,13 @@ static void node_draw_frame_prepare(const bContext *UNUSED(C), bNodeTree *ntree,
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;
}
@@ -361,7 +362,7 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp
BLF_enable(fontid, BLF_ASPECT);
BLF_aspect(fontid, aspect, aspect, 1.0f);
BLF_size(fontid, MIN2(24, font_size), U.dpi); /* clamp otherwise it can suck up a LOT of memory */
-
+
/* title color */
UI_GetThemeColorBlendShade3ubv(TH_TEXT, color_id, 0.4f, 10, color);
BLF_color3ubv(fontid, color);
@@ -369,7 +370,7 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp
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;
@@ -431,7 +432,7 @@ static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode,
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);
@@ -441,10 +442,10 @@ static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode,
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);
@@ -467,9 +468,9 @@ static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode,
/* 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;
@@ -481,11 +482,11 @@ static int node_resize_area_frame(bNode *node, int x, int y)
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;
-
+
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)
@@ -494,7 +495,7 @@ static int node_resize_area_frame(bNode *node, int x, int y)
dir |= NODE_RESIZE_TOP;
if (x >= totr.xmin && x < totr.xmax && y >= totr.ymin && y < totr.ymin + size)
dir |= NODE_RESIZE_BOTTOM;
-
+
return dir;
}
@@ -513,10 +514,10 @@ static void node_draw_reroute_prepare(const bContext *UNUSED(C), bNodeTree *UNUS
bNodeSocket *nsock;
float locx, locy;
float size = NODE_REROUTE_SIZE;
-
+
/* 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;
@@ -562,8 +563,8 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(
/* outline active and selected emphasis */
if (node->flag & SELECT) {
- glEnable(GL_BLEND);
- glEnable(GL_LINE_SMOOTH);
+ 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);
@@ -573,8 +574,8 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(
}
UI_draw_roundbox_4fv(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size, debug_color);
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
+ GPU_line_smooth(false);
+ GPU_blend(false);
}
#endif
@@ -604,7 +605,7 @@ static int node_tweak_area_reroute(bNode *node, int x, int y)
{
/* 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;
@@ -644,9 +645,9 @@ static void node_buts_image_user(uiLayout *layout, bContext *C, PointerRNA *ptr,
return;
col = uiLayoutColumn(layout, false);
-
+
uiItemR(col, imaptr, "source", 0, "", ICON_NONE);
-
+
source = RNA_enum_get(imaptr, "source");
if (source == IMA_SRC_SEQUENCE) {
@@ -715,12 +716,12 @@ static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), Poin
}
static void node_shader_buts_vect_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
-{
+{
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);
@@ -827,7 +828,7 @@ static void node_shader_buts_tex_environment_ex(uiLayout *layout, bContext *C, P
}
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);
@@ -849,11 +850,11 @@ static void node_shader_buts_tex_magic(uiLayout *layout, bContext *UNUSED(C), Po
static void node_shader_buts_tex_brick(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
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, "squash", 0, IFACE_("Squash"), ICON_NONE);
uiItemR(col, ptr, "squash_frequency", 0, IFACE_("Frequency"), ICON_NONE);
@@ -1021,6 +1022,21 @@ static void node_shader_buts_hair(uiLayout *layout, bContext *UNUSED(C), Pointer
uiItemR(layout, ptr, "component", 0, "", ICON_NONE);
}
+static void node_shader_buts_ies(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiLayout *row;
+
+ row = uiLayoutRow(layout, false);
+ uiItemR(row, ptr, "mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+
+ row = uiLayoutRow(layout, true);
+
+ if (RNA_enum_get(ptr, "mode") == NODE_IES_INTERNAL)
+ uiItemR(row, ptr, "ies", 0, "", ICON_NONE);
+ else
+ uiItemR(row, ptr, "filepath", 0, "", ICON_NONE);
+}
+
static void node_shader_buts_script(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayout *row;
@@ -1065,6 +1081,13 @@ static void node_shader_buts_bevel(uiLayout *layout, bContext *UNUSED(C), Pointe
uiItemR(layout, ptr, "samples", 0, NULL, ICON_NONE);
}
+static void node_shader_buts_ambient_occlusion(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "samples", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "inside", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "only_local", 0, NULL, ICON_NONE);
+}
+
/* only once called */
static void node_shader_set_butfunc(bNodeType *ntype)
{
@@ -1093,15 +1116,15 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_VALTORGB:
ntype->draw_buttons = node_buts_colorramp;
break;
- case SH_NODE_MATH:
+ case SH_NODE_MATH:
ntype->draw_buttons = node_buts_math;
- break;
- case SH_NODE_VECT_MATH:
+ break;
+ case SH_NODE_VECT_MATH:
ntype->draw_buttons = node_shader_buts_vect_math;
- break;
- case SH_NODE_VECT_TRANSFORM:
+ break;
+ case SH_NODE_VECT_TRANSFORM:
ntype->draw_buttons = node_shader_buts_vect_transform;
- break;
+ break;
case SH_NODE_ATTRIBUTE:
ntype->draw_buttons = node_shader_buts_attribute;
break;
@@ -1189,9 +1212,15 @@ static void node_shader_set_butfunc(bNodeType *ntype)
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;
}
}
@@ -1219,14 +1248,14 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *
{
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",
NULL, "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL);
if (!node->id) return;
-
+
imaptr = RNA_pointer_get(ptr, "image");
node_buts_image_user(layout, C, ptr, &imaptr, &iuserptr, true);
@@ -1255,17 +1284,17 @@ static void node_composit_buts_viewlayers(uiLayout *layout, bContext *C, Pointer
char scene_name[MAX_ID_NAME - 2];
uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL);
-
+
if (!node->id) return;
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;
-
+
scn_ptr = RNA_pointer_get(ptr, "scene");
RNA_string_get(&scn_ptr, "name", scene_name);
@@ -1280,7 +1309,7 @@ static void node_composit_buts_blur(uiLayout *layout, bContext *UNUSED(C), Point
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");
@@ -1293,14 +1322,14 @@ static void node_composit_buts_blur(uiLayout *layout, bContext *UNUSED(C), Point
}
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);
@@ -1316,31 +1345,31 @@ static void node_composit_buts_blur(uiLayout *layout, bContext *UNUSED(C), Point
static void node_composit_buts_dblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayout *col;
-
+
uiItemR(layout, ptr, "iterations", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "use_wrap", 0, NULL, ICON_NONE);
-
+
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);
-
+
col = uiLayoutColumn(layout, true);
uiItemR(col, ptr, "distance", 0, NULL, ICON_NONE);
uiItemR(col, ptr, "angle", 0, NULL, ICON_NONE);
-
+
uiItemS(layout);
-
+
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)
-{
+{
uiLayout *col;
-
+
col = uiLayoutColumn(layout, true);
uiItemR(col, ptr, "iterations", 0, NULL, ICON_NONE);
uiItemR(col, ptr, "sigma_color", 0, NULL, ICON_NONE);
@@ -1350,7 +1379,7 @@ static void node_composit_buts_bilateralblur(uiLayout *layout, bContext *UNUSED(
static void node_composit_buts_defocus(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
uiLayout *sub, *col;
-
+
col = uiLayoutColumn(layout, false);
uiItemL(col, IFACE_("Bokeh Type:"), ICON_NONE);
uiItemR(col, ptr, "bokeh", 0, "", ICON_NONE);
@@ -1379,17 +1408,17 @@ static void node_composit_buts_defocus(uiLayout *layout, bContext *C, PointerRNA
/* 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);
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);
}
-
+
uiItemR(layout, ptr, "mix", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "threshold", 0, NULL, ICON_NONE);
@@ -1399,7 +1428,7 @@ static void node_composit_buts_glare(uiLayout *layout, bContext *UNUSED(C), Poin
}
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);
}
@@ -1409,7 +1438,7 @@ static void node_composit_buts_glare(uiLayout *layout, bContext *UNUSED(C), Poin
}
static void node_composit_buts_tonemap(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
-{
+{
uiLayout *col;
col = uiLayoutColumn(layout, false);
@@ -1443,11 +1472,11 @@ static void node_composit_buts_lensdist(uiLayout *layout, bContext *UNUSED(C), P
static void node_composit_buts_vecblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
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, true);
uiItemL(col, IFACE_("Speed:"), ICON_NONE);
uiItemR(col, ptr, "speed_min", 0, IFACE_("Min"), ICON_NONE);
@@ -1491,7 +1520,7 @@ static void node_composit_buts_crop(uiLayout *layout, bContext *UNUSED(C), Point
static void node_composit_buts_splitviewer(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayout *row, *col;
-
+
col = uiLayoutColumn(layout, false);
row = uiLayoutRow(col, false);
uiItemR(row, ptr, "axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
@@ -1521,17 +1550,17 @@ static void node_composit_buts_map_range(uiLayout *layout, bContext *UNUSED(C),
static void node_composit_buts_map_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
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, "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);
@@ -1540,18 +1569,18 @@ static void node_composit_buts_map_value(uiLayout *layout, bContext *UNUSED(C),
}
static void node_composit_buts_alphaover(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
-{
+{
uiLayout *col;
-
+
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;
-
+
col = uiLayoutColumn(layout, true);
uiItemR(col, ptr, "use_alpha", 0, NULL, ICON_NONE);
uiItemR(col, ptr, "use_antialias_z", 0, NULL, ICON_NONE);
@@ -1588,7 +1617,7 @@ static void node_composit_buts_despeckle(uiLayout *layout, bContext *UNUSED(C),
static void node_composit_buts_diff_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
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);
@@ -1597,7 +1626,7 @@ static void node_composit_buts_diff_matte(uiLayout *layout, bContext *UNUSED(C),
static void node_composit_buts_distance_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayout *col, *row;
-
+
col = uiLayoutColumn(layout, true);
uiItemL(layout, IFACE_("Color Space:"), ICON_NONE);
@@ -1611,7 +1640,7 @@ static void node_composit_buts_distance_matte(uiLayout *layout, bContext *UNUSED
static void node_composit_buts_color_spill(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
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);
@@ -1637,11 +1666,11 @@ static void node_composit_buts_color_spill(uiLayout *layout, bContext *UNUSED(C)
static void node_composit_buts_chroma_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
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, 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);
@@ -1651,7 +1680,7 @@ static void node_composit_buts_chroma_matte(uiLayout *layout, bContext *UNUSED(C
static void node_composit_buts_color_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
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);
@@ -1659,7 +1688,7 @@ static void node_composit_buts_color_matte(uiLayout *layout, bContext *UNUSED(C)
}
static void node_composit_buts_channel_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
-{
+{
uiLayout *col, *row;
uiItemL(layout, IFACE_("Color Space:"), ICON_NONE);
@@ -1687,7 +1716,7 @@ static void node_composit_buts_channel_matte(uiLayout *layout, bContext *UNUSED(
static void node_composit_buts_luma_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
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);
@@ -1725,22 +1754,22 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
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_ZOOMIN, "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) {
@@ -1757,18 +1786,18 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
}
/* 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);
@@ -1777,20 +1806,20 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
}
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);
@@ -1822,7 +1851,7 @@ static void node_composit_buts_rotate(uiLayout *layout, bContext *UNUSED(C), Poi
static void node_composit_buts_invert(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayout *col;
-
+
col = uiLayoutColumn(layout, false);
uiItemR(col, ptr, "invert_rgb", 0, NULL, ICON_NONE);
uiItemR(col, ptr, "invert_alpha", 0, NULL, ICON_NONE);
@@ -1841,22 +1870,22 @@ static void node_composit_buts_view_levels(uiLayout *layout, bContext *UNUSED(C)
static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayout *split, *col, *row;
-
+
uiItemR(layout, ptr, "correction_method", 0, NULL, ICON_NONE);
-
+
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);
-
+
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);
@@ -1864,19 +1893,19 @@ static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C
}
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);
-
+
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);
@@ -1929,7 +1958,7 @@ static void node_composit_buts_huecorrect(uiLayout *layout, bContext *UNUSED(C),
}
static void node_composit_buts_ycc(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
-{
+{
uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
}
@@ -1992,7 +2021,7 @@ static void node_composit_buts_moviedistortion(uiLayout *layout, bContext *C, Po
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);
@@ -2046,7 +2075,7 @@ static void node_composit_buts_colorcorrection(uiLayout *layout, bContext *UNUSE
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);
@@ -2075,7 +2104,7 @@ static void node_composit_buts_colorcorrection_ex(uiLayout *layout, bContext *UN
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);
@@ -2102,11 +2131,11 @@ static void node_composit_buts_switch_view_ex(uiLayout *layout, bContext *UNUSED
static void node_composit_buts_boxmask(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);
@@ -2275,7 +2304,7 @@ static void node_composit_buts_viewer(uiLayout *layout, bContext *UNUSED(C), Poi
static void node_composit_buts_viewer_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayout *col;
-
+
uiItemR(layout, ptr, "use_alpha", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "tile_order", 0, NULL, ICON_NONE);
if (RNA_enum_get(ptr, "tile_order") == 0) {
@@ -2673,11 +2702,11 @@ static void node_composit_set_butfunc(bNodeType *ntype)
static void node_texture_buts_bricks(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
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, "squash", 0, IFACE_("Squash"), ICON_NONE);
uiItemR(col, ptr, "squash_frequency", 0, IFACE_("Frequency"), ICON_NONE);
@@ -2690,7 +2719,7 @@ static void node_texture_buts_proc(uiLayout *layout, bContext *UNUSED(C), Pointe
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);
@@ -2734,7 +2763,7 @@ static void node_texture_buts_proc(uiLayout *layout, bContext *UNUSED(C), Pointe
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);
@@ -2743,7 +2772,7 @@ static void node_texture_buts_proc(uiLayout *layout, bContext *UNUSED(C), Pointe
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);
@@ -2844,7 +2873,7 @@ static void node_socket_template_properties_update(bNodeType *ntype, bNodeSocket
{
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);
}
@@ -2852,7 +2881,7 @@ static void node_socket_template_properties_update(bNodeType *ntype, bNodeSocket
static void node_template_properties_update(bNodeType *ntype)
{
bNodeSocketTemplate *stemp;
-
+
if (ntype->inputs) {
for (stemp = ntype->inputs; stemp->type >= 0; ++stemp)
node_socket_template_properties_update(ntype, stemp);
@@ -2898,7 +2927,7 @@ void ED_node_init_butfuncs(void)
/*extern bNodeTreeType NodeTreeTypeUndefined;*/
extern bNodeType NodeTypeUndefined;
extern bNodeSocketType NodeSocketTypeUndefined;
-
+
/* default ui functions */
NodeTypeUndefined.draw_nodetype = node_draw_default;
NodeTypeUndefined.draw_nodetype_prepare = node_update_default;
@@ -2907,12 +2936,12 @@ void ED_node_init_butfuncs(void)
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 */
@@ -2923,17 +2952,17 @@ void ED_node_init_butfuncs(void)
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_RENDERLAYERS;
ntreeType_Shader->ui_icon = ICON_MATERIAL;
@@ -2990,16 +3019,16 @@ static void node_file_output_socket_draw(bContext *C, uiLayout *layout, PointerR
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 {
@@ -3008,12 +3037,12 @@ static void node_file_output_socket_draw(bContext *C, uiLayout *layout, PointerR
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);
@@ -3030,7 +3059,7 @@ static void std_node_socket_draw(bContext *C, uiLayout *layout, PointerRNA *ptr,
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);
@@ -3041,7 +3070,7 @@ static void std_node_socket_draw(bContext *C, uiLayout *layout, PointerRNA *ptr,
node_socket_button_label(C, layout, ptr, node_ptr, text);
return;
}
-
+
switch (type) {
case SOCK_FLOAT:
case SOCK_INT:
@@ -3070,7 +3099,7 @@ static void std_node_socket_interface_draw(bContext *UNUSED(C), uiLayout *layout
bNodeSocket *sock = ptr->data;
int type = sock->typeinfo->type;
/*int subtype = sock->typeinfo->subtype;*/
-
+
switch (type) {
case SOCK_FLOAT:
{
@@ -3133,38 +3162,39 @@ void ED_init_node_socket_type_virtual(bNodeSocketType *stype)
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(IMA_TYPE_COMPOSITE, "Viewer Node");
+
+ ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (ibuf) {
- float x, y;
+ float x, y;
gpuPushProjectionMatrix();
gpuPushMatrix();
/* 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)
@@ -3185,21 +3215,21 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b
GPU_shader_unbind();
}
else if (snode->flag & SNODE_USE_ALPHA) {
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST, snode->zoom, snode->zoom);
- glDisable(GL_BLEND);
+ 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;
@@ -3212,7 +3242,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b
}
node = node->next;
}
-
+
if ((snode->nodetree->flag & NTREE_VIEWER_BORDER) &&
viewer_border->xmin < viewer_border->xmax &&
viewer_border->ymin < viewer_border->ymax)
@@ -3237,7 +3267,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b
gpuPopProjectionMatrix();
gpuPopMatrix();
}
-
+
BKE_image_release_ibuf(ima, ibuf, lock);
}
@@ -3248,14 +3278,14 @@ static bool node_link_bezier_handles(View2D *v2d, SpaceNode *snode, bNodeLink *l
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;
@@ -3334,7 +3364,7 @@ bool node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, flo
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;
@@ -3474,7 +3504,7 @@ static void nodelink_batch_draw(SpaceNode *snode)
if (g_batch_link.count == 0)
return;
- glEnable(GL_BLEND);
+ GPU_blend(true);
float colors[6][4] = {{0.0f}};
UI_GetThemeColor4fv(TH_WIRE_INNER, colors[nodelink_get_color_id(TH_WIRE_INNER)]);
@@ -3494,7 +3524,7 @@ static void nodelink_batch_draw(SpaceNode *snode)
nodelink_batch_reset();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
void nodelink_batch_start(SpaceNode *UNUSED(snode))
@@ -3577,10 +3607,10 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link,
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;
@@ -3618,7 +3648,7 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
void ED_node_draw_snap(View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned pos)
{
immBegin(GWN_PRIM_LINES, 4);
-
+
if (border & (NODE_LEFT | NODE_RIGHT)) {
immVertex2f(pos, cent[0], v2d->cur.ymin);
immVertex2f(pos, cent[0], v2d->cur.ymax);
@@ -3627,7 +3657,7 @@ void ED_node_draw_snap(View2D *v2d, const float cent[2], float size, NodeBorder
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]);
@@ -3636,6 +3666,6 @@ void ED_node_draw_snap(View2D *v2d, const float cent[2], float size, NodeBorder
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 c200c5a7612..329676d3061 100644
--- a/source/blender/editors/space_node/node_add.c
+++ b/source/blender/editors/space_node/node_add.c
@@ -70,32 +70,32 @@ bNode *node_add_node(const bContext *C, const char *idname, int type, float locx
SpaceNode *snode = CTX_wm_space_node(C);
Main *bmain = CTX_data_main(C);
bNode *node = NULL;
-
+
node_deselect_all(snode);
-
+
if (idname)
node = nodeAddNode(C, snode->edittree, idname);
else
node = nodeAddStaticNode(C, snode->edittree, type);
BLI_assert(node && node->typeinfo);
-
+
/* generics */
node->locx = locx;
node->locy = locy + 60.0f; /* arbitrary... so its visible, (0,0) is top of node */
nodeSetSelected(node, true);
-
+
node->locx = locx;
node->locy = locy + 60.0f;
-
+
ntreeUpdateTree(bmain, snode->edittree);
ED_node_set_active(bmain, snode->edittree, node);
-
+
snode_update(snode, node);
-
+
if (snode->nodetree->type == NTREE_TEXTURE) {
ntreeTexCheckCyclics(snode->edittree);
}
-
+
return node;
}
@@ -122,7 +122,7 @@ static bool add_reroute_intersect_check(bNodeLink *link, float mcoords[][2], int
typedef struct bNodeSocketLink {
struct bNodeSocketLink *next, *prev;
-
+
struct bNodeSocket *sock;
struct bNodeLink *link;
float point[2];
@@ -131,12 +131,12 @@ typedef struct bNodeSocketLink {
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;
@@ -153,18 +153,18 @@ static bNodeSocketLink *add_reroute_do_socket_section(bContext *C, bNodeSocketLi
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);
@@ -173,7 +173,7 @@ static bNodeSocketLink *add_reroute_do_socket_section(bContext *C, bNodeSocketLi
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;
@@ -183,21 +183,21 @@ static bNodeSocketLink *add_reroute_do_socket_section(bContext *C, bNodeSocketLi
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;
}
@@ -208,7 +208,7 @@ static int add_reroute_exec(bContext *C, wmOperator *op)
bNodeTree *ntree = snode->edittree;
float mcoords[256][2];
int i = 0;
-
+
/* Get the cut path */
RNA_BEGIN (op->ptr, itemptr, "path")
{
@@ -227,12 +227,12 @@ static int add_reroute_exec(bContext *C, wmOperator *op)
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);
@@ -243,12 +243,12 @@ static int add_reroute_exec(bContext *C, wmOperator *op)
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.
*/
@@ -260,18 +260,18 @@ static int add_reroute_exec(bContext *C, wmOperator *op)
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;
}
@@ -304,6 +304,7 @@ void NODE_OT_add_reroute(wmOperatorType *ot)
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;
@@ -327,29 +328,29 @@ static int node_add_file_exec(bContext *C, wmOperator *op)
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(ima, NULL, IMA_SIGNAL_RELOAD);
+ 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;
}
@@ -357,11 +358,11 @@ static int node_add_file_invoke(bContext *C, wmOperator *op, const wmEvent *even
{
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]);
-
+
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
@@ -400,6 +401,7 @@ static int node_add_mask_poll(bContext *C)
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;
@@ -407,7 +409,7 @@ static int node_add_mask_exec(bContext *C, wmOperator *op)
/* check input variables */
char name[MAX_ID_NAME - 2];
RNA_string_get(op->ptr, "name", name);
- mask = BKE_libblock_find_name(ID_MSK, 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;
@@ -460,7 +462,7 @@ static int new_node_tree_exec(bContext *C, wmOperator *op)
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);
@@ -469,7 +471,7 @@ static int new_node_tree_exec(bContext *C, wmOperator *op)
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;
@@ -477,14 +479,14 @@ static int new_node_tree_exec(bContext *C, wmOperator *op)
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);
@@ -500,10 +502,10 @@ static int new_node_tree_exec(bContext *C, wmOperator *op)
}
else if (snode) {
snode->nodetree = ntree;
-
+
ED_node_tree_update(C);
}
-
+
return OPERATOR_FINISHED;
}
@@ -515,20 +517,19 @@ static const EnumPropertyItem *new_node_tree_type_itemf(bContext *UNUSED(C), Poi
void NODE_OT_new_node_tree(wmOperatorType *ot)
{
PropertyRNA *prop;
-
+
/* 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;
-
+
/* 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", "");
}
-
diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c
index e8b4e6ec990..38183637750 100644
--- a/source/blender/editors/space_node/node_buttons.c
+++ b/source/blender/editors/space_node/node_buttons.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -62,7 +62,7 @@
static int active_nodetree_poll(const bContext *C, PanelType *UNUSED(pt))
{
SpaceNode *snode = CTX_wm_space_node(C);
-
+
return (snode && snode->nodetree);
}
#endif
@@ -70,7 +70,7 @@ static int active_nodetree_poll(const bContext *C, PanelType *UNUSED(pt))
static int node_sockets_poll(const bContext *C, PanelType *UNUSED(pt))
{
SpaceNode *snode = CTX_wm_space_node(C);
-
+
return (snode && snode->nodetree && G.debug_value == 777);
}
@@ -82,10 +82,10 @@ static void node_sockets_panel(const bContext *C, Panel *pa)
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);
@@ -98,7 +98,7 @@ static void node_sockets_panel(const bContext *C, Panel *pa)
static int node_tree_interface_poll(const bContext *C, PanelType *UNUSED(pt))
{
SpaceNode *snode = CTX_wm_space_node(C);
-
+
return (snode && snode->edittree && (snode->edittree->inputs.first || snode->edittree->outputs.first));
}
@@ -119,7 +119,7 @@ static bool node_tree_find_active_socket(bNodeTree *ntree, bNodeSocket **r_sock,
return true;
}
}
-
+
*r_sock = NULL;
*r_in_out = 0;
return false;
@@ -137,14 +137,14 @@ static void node_tree_interface_panel(const bContext *C, Panel *pa)
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);
@@ -153,26 +153,26 @@ static void node_tree_interface_panel(const bContext *C, Panel *pa)
NULL, 0, 0, 0, 0);
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);
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);
@@ -185,7 +185,7 @@ static void node_tree_interface_panel(const bContext *C, Panel *pa)
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->label, N_("Sockets"));
@@ -208,7 +208,7 @@ static int node_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = node_has_buttons_region(sa);
-
+
if (ar)
ED_region_toggle_hidden(C, ar);
@@ -224,13 +224,13 @@ static int node_properties_poll(bContext *C)
void NODE_OT_properties(wmOperatorType *ot)
{
- ot->name = "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;
-
+
/* 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 ae810b0fde0..01e22ec5245 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -58,6 +58,8 @@
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
+#include "GPU_framebuffer.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -100,7 +102,7 @@ static bNodeTree *node_tree_from_ID(ID *id)
{
if (id) {
short idtype = GS(id->name);
-
+
switch (idtype) {
case ID_NT:
return (bNodeTree *)id;
@@ -118,7 +120,7 @@ static bNodeTree *node_tree_from_ID(ID *id)
return ((FreestyleLineStyle *)id)->nodetree;
}
}
-
+
return NULL;
}
@@ -137,7 +139,7 @@ void ED_node_tag_update_id(ID *id)
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)
@@ -165,7 +167,7 @@ void ED_node_tag_update_nodetree(Main *bmain, bNodeTree *ntree, bNode *node)
bool do_tag_update = true;
if (node != NULL) {
- if (!node_connected_to_output(ntree, node)) {
+ if (!node_connected_to_output(bmain, ntree, node)) {
do_tag_update = false;
}
}
@@ -191,7 +193,7 @@ static bool compare_nodes(const bNode *a, const bNode *b)
*/
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) {
@@ -220,13 +222,13 @@ static bool compare_nodes(const bNode *a, const bNode *b)
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;
}
@@ -239,11 +241,11 @@ void ED_node_sort(bNodeTree *ntree)
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) {
@@ -252,7 +254,7 @@ void ED_node_sort(bNodeTree *ntree)
/* all batches merged? */
if (first_b == NULL)
break;
-
+
/* merge batches */
node_a = first_a;
node_b = first_b;
@@ -281,7 +283,7 @@ void ED_node_sort(bNodeTree *ntree)
}
first_a = first_b;
} while (first_b);
-
+
k = k << 1;
}
}
@@ -300,9 +302,9 @@ static void node_uiblocks_init(const bContext *C, bNodeTree *ntree)
{
bNode *node;
char uiblockstr[32];
-
+
/* 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);
@@ -344,52 +346,52 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
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());
/* 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;
@@ -407,28 +409,28 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
/* preview rect? */
if (node->flag & NODE_PREVIEW) {
float aspect = 1.0f;
-
- if (node->preview_xsize && node->preview_ysize)
+
+ 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);
@@ -443,18 +445,18 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
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());
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;
}
@@ -462,35 +464,35 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
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());
/* 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;
@@ -499,7 +501,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
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.
*/
@@ -518,7 +520,7 @@ static void node_update_hidden(bNode *node)
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);
@@ -529,20 +531,20 @@ static void node_update_hidden(bNode *node)
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 + 3 * hiddenrad + node->miniwidth;
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;
@@ -550,10 +552,10 @@ static void node_update_hidden(bNode *node)
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;
@@ -620,22 +622,22 @@ static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node)
{
bNodeLink *link;
- glEnable(GL_BLEND);
+ 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);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
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];
-
+
RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
sock->typeinfo->draw_color((bContext *)C, &ptr, &node_ptr, color);
-
+
immAttrib4fv(col, color);
immVertex2f(pos, sock->locx, sock->locy);
}
@@ -645,7 +647,7 @@ static void node_socket_circle_draw(const bContext *C, bNodeTree *ntree, Pointer
static void node_draw_preview_background(float tile, rctf *rect)
{
float x, y;
-
+
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -655,7 +657,7 @@ static void node_draw_preview_background(float tile, rctf *rect)
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;
@@ -692,7 +694,7 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv)
float yscale = yrect / ((float)preview->ysize);
float scale;
rctf draw_rect;
-
+
/* uniform scale and offset */
draw_rect = *prv;
if (xscale < yscale) {
@@ -707,17 +709,17 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv)
draw_rect.xmax -= offset;
scale = yscale;
}
-
+
node_draw_preview_background(BLI_rctf_size_x(prv) / 10.0f, &draw_rect);
-
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); /* premul graphics */
-
+
+ GPU_blend(true);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); /* premul graphics */
+
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);
-
- glDisable(GL_BLEND);
+
+ GPU_blend(false);
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -731,23 +733,23 @@ static void node_toggle_button_cb(struct bContext *C, void *node_argv, void *op_
{
bNode *node = (bNode *)node_argv;
const char *opname = (const char *)op_argv;
-
+
/* select & activate only the button's node */
node_select_single(C, node);
-
+
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);
@@ -773,7 +775,7 @@ void node_draw_sockets(View2D *v2d, const bContext *C, bNodeTree *ntree, bNode *
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
- glEnable(GL_BLEND);
+ GPU_blend(true);
GPU_enable_program_point_size();
immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA);
@@ -802,7 +804,7 @@ void node_draw_sockets(View2D *v2d, const bContext *C, bNodeTree *ntree, bNode *
node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
}
-
+
/* socket outputs */
short selected_output_ct = 0;
if (draw_outputs) {
@@ -864,7 +866,7 @@ void node_draw_sockets(View2D *v2d, const bContext *C, bNodeTree *ntree, bNode *
immUnbindProgram();
GPU_disable_program_point_size();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
@@ -878,17 +880,17 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
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) {
UI_GetThemeColorBlendShade4fv(color_id, TH_REDALERT, 0.5f, 0, color);
}
@@ -903,14 +905,14 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
}
}
- glLineWidth(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;
@@ -937,7 +939,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
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);
@@ -945,7 +947,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
else {
UI_GetThemeColorBlendShade4fv(TH_SELECT, color_id, 0.4f, 10, color);
}
-
+
/* open/close entirely? */
{
uiBut *but;
@@ -957,16 +959,16 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
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);
-
+
/* custom draw function for this button */
UI_draw_icon_tri(rct->xmin + 0.5f * U.widget_unit, rct->ymax - NODE_DY / 2.0f, 'v', color);
}
-
+
nodeLabel(ntree, node, showname, sizeof(showname));
-
+
//if (node->flag & NODE_MUTED)
// BLI_snprintf(showname, sizeof(showname), "[%s]", showname); /* XXX - don't print into self! */
-
+
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,
@@ -991,7 +993,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
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);
@@ -1007,9 +1009,9 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
}
}
}
-
+
UI_ThemeClearColor(color_id);
-
+
UI_block_end(C, node->block);
UI_block_draw(C, node->block);
node->block = NULL;
@@ -1027,7 +1029,7 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
float scale;
UI_view2d_scale_get(v2d, &scale, NULL);
-
+
/* shadow */
node_draw_shadow(snode, node, hiddenrad, 1.0f);
@@ -1036,9 +1038,9 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
UI_GetThemeColorBlendShade4fv(color_id, TH_REDALERT, 0.5f, 0, color);
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);
@@ -1048,13 +1050,13 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
/* custom color inline */
if (node->flag & NODE_CUSTOM_COLOR) {
- glEnable(GL_BLEND);
- glEnable(GL_LINE_SMOOTH);
+ 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);
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
+ GPU_line_smooth(false);
+ GPU_blend(false);
}
/* title */
@@ -1064,7 +1066,7 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
else {
UI_GetThemeColorBlendShade4fv(TH_SELECT, color_id, 0.4f, 10, color);
}
-
+
/* open entirely icon */
{
uiBut *but;
@@ -1076,11 +1078,11 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
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);
-
+
/* custom draw function for this button */
UI_draw_icon_tri(rct->xmin + 10.0f, centy, 'h', color);
}
-
+
/* disable lines */
if (node->flag & NODE_MUTED)
node_draw_mute_line(&ar->v2d, snode, node);
@@ -1150,7 +1152,7 @@ void node_set_cursor(wmWindow *win, SpaceNode *snode, float cursor[2])
bNode *node;
bNodeSocket *sock;
int wmcursor = CURSOR_STD;
-
+
if (ntree) {
if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN | SOCK_OUT)) {
/* pass */
@@ -1167,7 +1169,7 @@ void node_set_cursor(wmWindow *win, SpaceNode *snode, float cursor[2])
}
}
}
-
+
WM_cursor_set(win, wmcursor);
}
@@ -1188,10 +1190,10 @@ static void node_update(const bContext *C, bNodeTree *ntree, bNode *node)
void node_update_nodetree(const bContext *C, bNodeTree *ntree)
{
bNode *node;
-
+
/* 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);
@@ -1211,7 +1213,7 @@ void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeT
bNode *node;
bNodeLink *link;
int a;
-
+
if (ntree == NULL) return; /* groups... */
#ifdef USE_DRAW_TOT_UPDATE
@@ -1237,17 +1239,17 @@ void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeT
node->nr = a; /* index of node in list, used for exec event code */
node_draw(C, ar, snode, ntree, node, key);
}
-
+
/* node lines */
- glEnable(GL_BLEND);
+ 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);
- glDisable(GL_BLEND);
-
+ GPU_blend(false);
+
/* draw foreground nodes, last nodes in front */
for (a = 0, node = ntree->nodes.first; node; node = node->next, a++) {
bNodeInstanceKey key;
@@ -1264,9 +1266,9 @@ void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeT
static void draw_tree_path(SpaceNode *snode)
{
char info[256];
-
+
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));
}
@@ -1274,11 +1276,11 @@ static void draw_tree_path(SpaceNode *snode)
static void snode_setup_v2d(SpaceNode *snode, ARegion *ar, const float center[2])
{
View2D *v2d = &ar->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);
@@ -1303,13 +1305,13 @@ static void draw_group_overlay(const bContext *C, ARegion *ar)
float color[4];
/* shade node groups to separate them visually */
- glEnable(GL_BLEND);
+ GPU_blend(true);
UI_GetThemeColorShadeAlpha4fv(TH_NODE_GROUP, 0, -70, color);
UI_draw_roundbox_corner_set(UI_CNR_NONE);
UI_draw_roundbox_4fv(true, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0, color);
- glDisable(GL_BLEND);
-
+ 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);
@@ -1325,24 +1327,24 @@ void drawnodespace(const bContext *C, ARegion *ar)
View2D *v2d = &ar->v2d;
UI_ThemeClearColor(TH_BACK);
- glClear(GL_COLOR_BUFFER_BIT);
+ 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 */
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-
+ 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;
@@ -1352,50 +1354,50 @@ void drawnodespace(const bContext *C, ARegion *ar)
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);
@@ -1416,17 +1418,17 @@ void drawnodespace(const bContext *C, ARegion *ar)
draw_nodetree(C, ar, ntree, path->parent_key);
}
-
+
/* temporary links */
- glEnable(GL_BLEND);
- glEnable(GL_LINE_SMOOTH);
+ 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);
}
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
-
+ GPU_line_smooth(false);
+ GPU_blend(false);
+
if (snode->flag & SNODE_SHOW_GPENCIL) {
/* draw grease-pencil ('canvas' strokes) */
ED_gpencil_draw_view2d(C, true);
@@ -1435,16 +1437,16 @@ void drawnodespace(const bContext *C, ARegion *ar)
else {
/* default grid */
UI_view2d_multi_grid_draw(v2d, TH_BACK, ED_node_grid_size(), NODE_GRID_STEPS, 2);
-
+
/* 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) */
@@ -1454,7 +1456,7 @@ void drawnodespace(const bContext *C, ARegion *ar)
/* tree path info */
draw_tree_path(snode);
-
+
/* scrollers */
scrollers = UI_view2d_scrollers_calc(C, v2d, 10, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
UI_view2d_scrollers_draw(C, v2d, scrollers);
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index d91c330c853..ff87dcf409a 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -88,6 +88,7 @@ enum {
};
typedef struct CompoJob {
+ Main *bmain;
Scene *scene;
bNodeTree *ntree;
bNodeTree *localtree;
@@ -152,7 +153,7 @@ static int compo_get_recalc_flags(const bContext *C)
static int compo_breakjob(void *cjv)
{
CompoJob *cj = cjv;
-
+
/* without G.is_break 'ESC' wont quit - which annoys users */
return (*(cj->stop)
#ifdef USE_ESC_COMPO
@@ -166,7 +167,7 @@ static int compo_breakjob(void *cjv)
static void compo_statsdrawjob(void *cjv, const char *UNUSED(str))
{
CompoJob *cj = cjv;
-
+
*(cj->do_update) = true;
}
@@ -174,7 +175,7 @@ static void compo_statsdrawjob(void *cjv, const char *UNUSED(str))
static void compo_redrawjob(void *cjv)
{
CompoJob *cj = cjv;
-
+
*(cj->do_update) = true;
}
@@ -183,7 +184,7 @@ static void compo_freejob(void *cjv)
CompoJob *cj = cjv;
if (cj->localtree) {
- ntreeLocalMerge(cj->localtree, cj->ntree);
+ ntreeLocalMerge(cj->bmain, cj->localtree, cj->ntree);
}
MEM_freeN(cj);
}
@@ -209,7 +210,7 @@ static void compo_updatejob(void *UNUSED(cjv))
static void compo_progressjob(void *cjv, float progress)
{
CompoJob *cj = cjv;
-
+
*(cj->progress) = progress;
}
@@ -223,7 +224,7 @@ static void compo_startjob(void *cjv, short *stop, short *do_update, float *prog
if (scene->use_nodes == false)
return;
-
+
cj->stop = stop;
cj->do_update = do_update;
cj->progress = progress;
@@ -267,6 +268,7 @@ void ED_node_composite_job(const bContext *C, struct bNodeTree *nodetree, Scene
{
wmJob *wm_job;
CompoJob *cj;
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
/* to fix bug: [#32272] */
@@ -278,13 +280,14 @@ void ED_node_composite_job(const bContext *C, struct bNodeTree *nodetree, Scene
G.is_break = false;
#endif
- BKE_image_backup_render(scene, BKE_image_verify_viewer(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");
/* customdata for preview thread */
+ cj->bmain = bmain;
cj->scene = scene;
cj->ntree = nodetree;
cj->recalc_flags = compo_get_recalc_flags(C);
@@ -388,7 +391,7 @@ void ED_node_shader_default(const bContext *C, ID *id)
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)) {
@@ -435,14 +438,14 @@ void ED_node_shader_default(const bContext *C, ID *id)
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;
@@ -452,7 +455,7 @@ void ED_node_shader_default(const bContext *C, ID *id)
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) {
@@ -460,7 +463,7 @@ void ED_node_shader_default(const bContext *C, ID *id)
RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sockptr);
RNA_float_set(&sockptr, "default_value", strength);
}
-
+
ntreeUpdateTree(CTX_data_main(C), ntree);
}
@@ -470,32 +473,32 @@ void ED_node_composit_default(const bContext *C, struct Scene *sce)
{
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;
}
-
+
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;
-
+
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);
-
+
/* 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);
}
@@ -505,27 +508,27 @@ void ED_node_texture_default(const bContext *C, Tex *tx)
{
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;
}
-
+
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;
-
+
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);
-
+
ntreeUpdateTree(CTX_data_main(C), tx->nodetree);
}
@@ -536,7 +539,7 @@ void snode_set_context(const bContext *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)))
@@ -547,25 +550,25 @@ void snode_set_context(const bContext *C)
*/
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))
{
@@ -576,12 +579,12 @@ void snode_set_context(const bContext *C)
void snode_update(SpaceNode *snode, bNode *node)
{
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 ...
*/
-
+
/* update all edited group nodes */
path = snode->treepath.last;
if (path) {
@@ -601,38 +604,38 @@ 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_LAMP, 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);
@@ -652,7 +655,8 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
for (wo = bmain->world.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);
}
@@ -662,27 +666,27 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
/* 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() doesnt link this yet... */
- node->id = (ID *)BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ 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);
}
@@ -737,13 +741,13 @@ static int edit_node_invoke_properties(bContext *C, wmOperator *op)
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, "socket"))
RNA_int_set(op->ptr, "socket", 0);
-
+
return 1;
}
@@ -754,18 +758,18 @@ static void edit_node_properties_get(wmOperator *op, bNodeTree *ntree, bNode **r
char nodename[MAX_NAME];
int sockindex;
int in_out;
-
+
RNA_string_get(op->ptr, "node", nodename);
node = nodeFindNodebyName(ntree, nodename);
-
+
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;
}
-
+
if (rnode)
*rnode = node;
if (rsock)
@@ -781,7 +785,7 @@ static void edit_node_properties_get(wmOperator *op, bNodeTree *ntree, bNode **r
static bNode *visible_node(SpaceNode *snode, const rctf *rct)
{
bNode *node;
-
+
for (node = snode->edittree->nodes.last; node; node = node->prev) {
if (BLI_rctf_isect(&node->totr, rct, NULL))
break;
@@ -803,13 +807,13 @@ typedef struct NodeSizeWidget {
static void node_resize_init(bContext *C, wmOperator *op, const wmEvent *UNUSED(event), bNode *node, int dir)
{
SpaceNode *snode = CTX_wm_space_node(C);
-
+
NodeSizeWidget *nsw = MEM_callocN(sizeof(NodeSizeWidget), "size widget op data");
-
+
op->customdata = nsw;
nsw->mxstart = snode->cursor[0];
nsw->mystart = snode->cursor[1];
-
+
/* store old */
nsw->oldlocx = node->locx;
nsw->oldlocy = node->locy;
@@ -819,7 +823,7 @@ static void node_resize_init(bContext *C, wmOperator *op, const wmEvent *UNUSED(
nsw->oldheight = node->height;
nsw->oldminiwidth = node->miniwidth;
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);
@@ -828,7 +832,7 @@ static void node_resize_init(bContext *C, wmOperator *op, const wmEvent *UNUSED(
static void node_resize_exit(bContext *C, wmOperator *op, bool UNUSED(cancel))
{
WM_cursor_modal_restore(CTX_wm_window(C));
-
+
MEM_freeN(op->customdata);
op->customdata = NULL;
}
@@ -840,14 +844,14 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event)
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) {
/* width can use node->width or node->miniwidth (hidden nodes) */
float *pwidth;
@@ -865,7 +869,7 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event)
widthmin = node->typeinfo->minwidth;
}
widthmax = node->typeinfo->maxwidth;
-
+
{
if (nsw->directions & NODE_RESIZE_RIGHT) {
*pwidth = oldwidth + dx;
@@ -873,20 +877,20 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
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;
@@ -896,7 +900,7 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event)
CLAMP(node->height, heightmin, heightmax);
}
}
-
+
/* XXX make callback? */
if (node->type == NODE_FRAME) {
/* keep the offset symmetric around center point */
@@ -918,21 +922,23 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
}
}
-
+
ED_region_tag_redraw(ar);
break;
-
+
case LEFTMOUSE:
case MIDDLEMOUSE:
case RIGHTMOUSE:
-
- node_resize_exit(C, op, false);
- ED_node_post_apply_transform(C, snode->edittree);
-
- return OPERATOR_FINISHED;
+ 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;
}
@@ -942,7 +948,7 @@ static int node_resize_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ARegion *ar = CTX_wm_region(C);
bNode *node = nodeGetActive(snode->edittree);
int dir;
-
+
if (node) {
/* convert mouse coordinates to v2d space */
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
@@ -967,13 +973,13 @@ void NODE_OT_resize(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_BLOCKING;
}
@@ -984,7 +990,7 @@ void NODE_OT_resize(wmOperatorType *ot)
int node_has_hidden_sockets(bNode *node)
{
bNodeSocket *sock;
-
+
for (sock = node->inputs.first; sock; sock = sock->next)
if (sock->flag & SOCK_HIDDEN)
return 1;
@@ -1025,10 +1031,10 @@ int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **so
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) {
@@ -1045,7 +1051,7 @@ int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **so
rect.xmin -= NODE_SOCKSIZE;
}
}
-
+
if (in_out & SOCK_IN) {
for (sock = node->inputs.first; sock; sock = sock->next) {
if (!nodeSocketIsHidden(sock)) {
@@ -1073,7 +1079,7 @@ int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **so
}
}
}
-
+
return 0;
}
@@ -1082,9 +1088,9 @@ int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **so
static void node_duplicate_reparent_recursive(bNode *node)
{
bNode *parent;
-
+
node->flag |= NODE_TEST;
-
+
/* find first selected parent */
for (parent = node->parent; parent; parent = parent->parent) {
if (parent->flag & SELECT) {
@@ -1102,6 +1108,7 @@ static void node_duplicate_reparent_recursive(bNode *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;
@@ -1109,13 +1116,13 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
const bool keep_inputs = RNA_boolean_get(op->ptr, "keep_inputs");
bool do_tag_update = false;
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
-
+ 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 = nodeCopyNode(ntree, node);
-
+
if (newnode->id) {
/* simple id user adjustment, node internal functions don't touch this
* but operators and readfile.c do. */
@@ -1124,12 +1131,12 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
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!
*/
@@ -1154,15 +1161,15 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
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;
@@ -1170,32 +1177,32 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
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(ntree, newnode));
+ 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);
@@ -1210,14 +1217,14 @@ void NODE_OT_duplicate(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
RNA_def_boolean(ot->srna, "keep_inputs", 0, "Keep Inputs", "Keep the input links to duplicated nodes");
}
@@ -1264,7 +1271,7 @@ static int node_read_viewlayers_exec(bContext *C, wmOperator *UNUSED(op))
}
}
}
-
+
snode_notify(C, snode);
snode_dag_update(C, snode);
@@ -1273,15 +1280,15 @@ static int node_read_viewlayers_exec(bContext *C, wmOperator *UNUSED(op))
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->exec = node_read_viewlayers_exec;
-
+
ot->poll = composite_node_active;
-
+
/* flags */
ot->flag = 0;
}
@@ -1290,7 +1297,7 @@ int node_render_changed_exec(bContext *C, wmOperator *UNUSED(op))
{
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;
@@ -1298,21 +1305,21 @@ int node_render_changed_exec(bContext *C, wmOperator *UNUSED(op))
}
if (node) {
ViewLayer *view_layer = BLI_findlink(&sce->view_layers, node->custom1);
-
+
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);
-
+
/* 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_properties_free(&op_ptr);
-
+
return OPERATOR_FINISHED;
}
}
@@ -1324,11 +1331,11 @@ 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->exec = node_render_changed_exec;
-
+
ot->poll = composite_node_active;
-
+
/* flags */
ot->flag = 0;
}
@@ -1347,12 +1354,12 @@ static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag)
*/
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
@@ -1361,12 +1368,12 @@ static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag)
}
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
@@ -1378,11 +1385,11 @@ static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag)
static int node_hide_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceNode *snode = CTX_wm_space_node(C);
-
+
/* sanity checking (poll callback checks this already) */
if ((snode == NULL) || (snode->edittree == NULL))
return OPERATOR_CANCELLED;
-
+
node_flag_toggle_exec(snode, NODE_HIDDEN);
WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
@@ -1396,7 +1403,7 @@ void NODE_OT_hide_toggle(wmOperatorType *ot)
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;
@@ -1489,7 +1496,7 @@ static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op))
}
}
}
-
+
for (node = snode->edittree->nodes.first; node; node = node->next) {
if (node->flag & SELECT) {
node_set_hidden_sockets(snode, node, !hidden);
@@ -1522,26 +1529,27 @@ void NODE_OT_hide_socket_toggle(wmOperatorType *ot)
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;
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+ 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(snode->edittree, 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);
}
-
+
return OPERATOR_FINISHED;
}
@@ -1551,11 +1559,11 @@ void NODE_OT_mute_toggle(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1564,30 +1572,31 @@ void NODE_OT_mute_toggle(wmOperatorType *ot)
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;
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+ 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) {
/* check id user here, nodeFreeNode is called for free dbase too */
- do_tag_update |= (do_tag_update || node_connected_to_output(snode->edittree, node));
+ do_tag_update |= (do_tag_update || node_connected_to_output(bmain, snode->edittree, node));
if (node->id)
id_us_min(node->id);
nodeFreeNode(snode->edittree, node);
}
}
-
+
ntreeUpdateTree(CTX_data_main(C), snode->edittree);
snode_notify(C, snode);
if (do_tag_update) {
snode_dag_update(C, snode);
}
-
+
return OPERATOR_FINISHED;
}
@@ -1597,11 +1606,11 @@ void NODE_OT_delete(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1666,7 +1675,7 @@ static int node_delete_reconnect_exec(bContext *C, wmOperator *UNUSED(op))
next = node->next;
if (node->flag & SELECT) {
nodeInternalRelink(snode->edittree, node);
-
+
/* check id user here, nodeFreeNode is called for free dbase too */
if (node->id)
id_us_min(node->id);
@@ -1754,7 +1763,7 @@ static int node_output_file_remove_active_socket_exec(bContext *C, wmOperator *U
PointerRNA ptr = CTX_data_pointer_get(C, "node");
bNodeTree *ntree = NULL;
bNode *node = NULL;
-
+
if (ptr.data) {
node = ptr.data;
ntree = ptr.id.data;
@@ -1766,12 +1775,12 @@ static int node_output_file_remove_active_socket_exec(bContext *C, wmOperator *U
if (!node || node->type != CMP_NODE_OUTPUT_FILE)
return OPERATOR_CANCELLED;
-
+
if (!ntreeCompositOutputFileRemoveActiveSocket(ntree, node))
return OPERATOR_CANCELLED;
-
+
snode_notify(C, snode);
-
+
return OPERATOR_FINISHED;
}
@@ -1781,11 +1790,11 @@ void NODE_OT_output_file_remove_active_socket(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1800,7 +1809,7 @@ static int node_output_file_move_active_socket_exec(bContext *C, wmOperator *op)
NodeImageMultiFile *nimf;
bNodeSocket *sock;
int direction;
-
+
if (ptr.data)
node = ptr.data;
else if (snode && snode->edittree)
@@ -1810,13 +1819,13 @@ static int node_output_file_move_active_socket_exec(bContext *C, wmOperator *op)
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)
@@ -1833,9 +1842,9 @@ static int node_output_file_move_active_socket_exec(bContext *C, wmOperator *op)
BLI_insertlinkafter(&node->inputs, after, sock);
nimf->active_input++;
}
-
+
snode_notify(C, snode);
-
+
return OPERATOR_FINISHED;
}
@@ -1846,19 +1855,19 @@ void NODE_OT_output_file_move_active_socket(wmOperatorType *ot)
{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";
-
+
/* callbacks */
ot->exec = node_output_file_move_active_socket_exec;
ot->poll = composite_node_editable;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
RNA_def_enum(ot->srna, "direction", direction_items, 2, "Direction", "");
}
@@ -1869,13 +1878,13 @@ 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;
-
+
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) {
@@ -1934,7 +1943,7 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
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 */
@@ -2053,7 +2062,7 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
/* 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;
@@ -2108,9 +2117,9 @@ static int ntree_socket_add_exec(bContext *C, wmOperator *op)
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";
@@ -2119,7 +2128,7 @@ static int ntree_socket_add_exec(bContext *C, wmOperator *op)
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);
@@ -2130,7 +2139,7 @@ static int ntree_socket_add_exec(bContext *C, wmOperator *op)
/* 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;
@@ -2138,11 +2147,11 @@ static int ntree_socket_add_exec(bContext *C, wmOperator *op)
tsock->flag &= ~SELECT;
/* make the new socket active */
sock->flag |= SELECT;
-
+
ntreeUpdateTree(CTX_data_main(C), ntree);
WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -2152,14 +2161,14 @@ void NODE_OT_tree_socket_add(wmOperatorType *ot)
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;
-
+
/* 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", "");
}
@@ -2170,25 +2179,25 @@ 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;
-
+
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);
-
+
/* set active socket */
if (active_sock)
active_sock->flag |= SELECT;
-
+
ntreeUpdateTree(CTX_data_main(C), ntree);
WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -2198,11 +2207,11 @@ void NODE_OT_tree_socket_remove(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -2222,7 +2231,7 @@ static int ntree_socket_move_exec(bContext *C, wmOperator *op)
int direction = RNA_enum_get(op->ptr, "direction");
bNodeSocket *iosock;
ListBase *lb;
-
+
lb = &ntree->inputs;
iosock = ntree_get_active_interface_socket(lb);
if (!iosock) {
@@ -2231,7 +2240,7 @@ static int ntree_socket_move_exec(bContext *C, wmOperator *op)
}
if (!iosock)
return OPERATOR_CANCELLED;
-
+
switch (direction) {
case 1:
{ /* up */
@@ -2254,11 +2263,11 @@ static int ntree_socket_move_exec(bContext *C, wmOperator *op)
break;
}
}
-
+
ntreeUpdateTree(CTX_data_main(C), ntree);
WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -2268,14 +2277,14 @@ void NODE_OT_tree_socket_move(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
RNA_def_enum(ot->srna, "direction", move_direction_items, 1, "Direction", "");
}
@@ -2322,9 +2331,9 @@ static bool node_shader_script_update_text_recursive(RenderEngine *engine, Rende
{
bool found = false;
bNode *node;
-
+
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) {
@@ -2337,7 +2346,7 @@ static bool node_shader_script_update_text_recursive(RenderEngine *engine, Rende
found = true;
}
}
-
+
return found;
}
@@ -2384,7 +2393,7 @@ static int node_shader_script_update_exec(bContext *C, wmOperator *op)
if (ntree->type == NTREE_SHADER)
ntree->done = false;
} FOREACH_NODETREE_END
-
+
FOREACH_NODETREE(bmain, ntree, id) {
if (ntree->type == NTREE_SHADER) {
if (!ntree->done)
@@ -2434,13 +2443,14 @@ static void viewer_border_corner_to_backdrop(SpaceNode *snode, ARegion *ar, int
static int viewer_border_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
Image *ima;
void *lock;
ImBuf *ibuf;
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+ ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
- ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (ibuf) {
diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c
index 7eaf35c6c4f..926fff7a3b6 100644
--- a/source/blender/editors/space_node/node_group.c
+++ b/source/blender/editors/space_node/node_group.c
@@ -69,7 +69,7 @@ static int 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.
@@ -88,7 +88,7 @@ static int 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.
@@ -112,14 +112,14 @@ static const char *group_ntree_idname(bContext *C)
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 "";
}
@@ -127,7 +127,7 @@ 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
@@ -142,22 +142,22 @@ static int node_group_edit_exec(bContext *C, wmOperator *op)
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));
-
+
gnode = node_group_get_active(C, node_idname);
-
+
if (gnode && !exit) {
bNodeTree *ngroup = (bNodeTree *)gnode->id;
-
+
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);
-
+
return OPERATOR_FINISHED;
}
@@ -167,45 +167,45 @@ void NODE_OT_group_edit(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
RNA_def_boolean(ot->srna, "exit", false, "Exit", "");
}
/* ******************** Ungroup operator ********************** */
/* returns 1 if its OK */
-static int node_group_ungroup(bNodeTree *ntree, bNode *gnode)
+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, G.main, false);
-
+ 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.
*/
@@ -213,43 +213,43 @@ static int node_group_ungroup(bNodeTree *ntree, bNode *gnode)
/* 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)
+
+ /* 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) {
@@ -257,40 +257,40 @@ static int node_group_ungroup(bNodeTree *ntree, bNode *gnode)
bAction *waction;
/* firstly, wgroup needs to temporary dummy action that can be destroyed, as it shares copies */
- waction = wgroup->adt->action = BKE_action_copy(G.main, wgroup->adt->action);
-
+ waction = wgroup->adt->action = BKE_action_copy(bmain, wgroup->adt->action);
+
/* now perform the moving */
- BKE_animdata_separate_by_basepath(&wgroup->id, &ntree->id, &anim_basepaths);
-
+ 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_libblock_free(G.main, waction);
+ BKE_libblock_free(bmain, waction);
wgroup->adt->action = NULL;
}
}
-
+
/* free the group tree (takes care of user count) */
- BKE_libblock_free(G.main, wgroup);
-
+ BKE_libblock_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)) {
@@ -298,24 +298,24 @@ static int node_group_ungroup(bNodeTree *ntree, bNode *gnode)
++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 */
@@ -326,18 +326,18 @@ static int node_group_ungroup(bNodeTree *ntree, bNode *gnode)
}
}
}
-
+
/* 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);
nodeFreeNode(ntree, node);
@@ -345,27 +345,28 @@ static int node_group_ungroup(bNodeTree *ntree, bNode *gnode)
/* delete the group instance */
nodeFreeNode(ntree, gnode);
-
+
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), CTX_data_main(C));
+ 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(snode->edittree, gnode)) {
- ntreeUpdateTree(CTX_data_main(C), snode->nodetree);
+
+ if (gnode->id && node_group_ungroup(bmain, snode->edittree, gnode)) {
+ ntreeUpdateTree(bmain, snode->nodetree);
}
else {
BKE_report(op->reports, RPT_WARNING, "Cannot ungroup");
@@ -384,11 +385,11 @@ void NODE_OT_group_ungroup(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -396,32 +397,33 @@ void NODE_OT_group_ungroup(wmOperatorType *ot)
/* ******************** Separate operator ********************** */
/* returns 1 if its OK */
-static int node_group_separate_selected(bNodeTree *ntree, bNodeTree *ngroup, float offx, float offy, int make_copy)
+static int node_group_separate_selected(
+ 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 nodeCopyNode */
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 = nodeCopyNode(ngroup, node);
@@ -430,44 +432,44 @@ static int node_group_separate_selected(bNodeTree *ntree, bNodeTree *ngroup, flo
/* use the existing node */
newnode = node;
}
-
- /* keep track of this node's RNA "base" path (the part of the path identifying the 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;
+ 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)
@@ -484,28 +486,28 @@ static int node_group_separate_selected(bNodeTree *ntree, bNodeTree *ngroup, flo
}
}
}
-
+
/* 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(&ngroup->id, &ntree->id, &anim_basepaths);
-
+ 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;
}
@@ -523,12 +525,13 @@ static const EnumPropertyItem node_group_separate_types[] = {
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), CTX_data_main(C));
+ ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
/* are we inside of a group? */
ngroup = snode->edittree;
@@ -539,27 +542,27 @@ static int node_group_separate_exec(bContext *C, wmOperator *op)
}
/* get node tree offset */
snode_group_offset(snode, &offx, &offy);
-
+
switch (type) {
case NODE_GS_COPY:
- if (!node_group_separate_selected(nparent, ngroup, offx, offy, 1)) {
+ if (!node_group_separate_selected(bmain, nparent, ngroup, offx, offy, 1)) {
BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes");
return OPERATOR_CANCELLED;
}
break;
case NODE_GS_MOVE:
- if (!node_group_separate_selected(nparent, ngroup, offx, offy, 0)) {
+ if (!node_group_separate_selected(bmain, nparent, ngroup, offx, offy, 0)) {
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);
@@ -570,13 +573,13 @@ static int node_group_separate_invoke(bContext *C, wmOperator *UNUSED(op), const
{
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);
-
+
UI_popup_menu_end(C, pup);
-
+
return OPERATOR_INTERFACE;
}
@@ -586,15 +589,15 @@ void NODE_OT_group_separate(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
RNA_def_enum(ot->srna, "type", node_group_separate_types, NODE_GS_COPY, "Type", "");
}
@@ -613,10 +616,10 @@ static bool node_group_make_test_selected(bNodeTree *ntree, bNode *gnode, const
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)) {
@@ -629,13 +632,13 @@ static bool node_group_make_test_selected(bNodeTree *ntree, bNode *gnode, const
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) {
@@ -660,7 +663,7 @@ static int node_get_selected_minmax(bNodeTree *ntree, bNode *gnode, float *min,
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)) {
@@ -669,17 +672,18 @@ static int node_get_selected_minmax(bNodeTree *ntree, bNode *gnode, float *min,
++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;
@@ -689,89 +693,89 @@ static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree,
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)
+ /* 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(&ntree->id, &ngroup->id, &anim_basepaths);
-
+
+ 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.
@@ -785,17 +789,17 @@ static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree,
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);
@@ -842,7 +846,7 @@ static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree,
node->locy -= center[1];
}
}
-
+
/* expose all unlinked sockets too */
if (expose_all) {
for (node = ngroup->nodes.first; node; node = node->next) {
@@ -858,16 +862,16 @@ static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree,
}
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;
@@ -876,11 +880,11 @@ static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree,
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);
@@ -902,22 +906,22 @@ static bNode *node_group_make_from_selected(const bContext *C, bNodeTree *ntree,
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;
-
+
/* new nodetree */
ngroup = ntreeAddTree(bmain, "NodeGroup", ntreetype);
-
+
/* 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]);
-
+
node_group_make_insert_selected(C, ntree, gnode);
/* update of the tree containing the group instance node */
@@ -935,29 +939,29 @@ static int node_group_make_exec(bContext *C, wmOperator *op)
bNodeTree *ngroup;
bNode *gnode;
Main *bmain = 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;
-
+
gnode = node_group_make_from_selected(C, ntree, node_idname, ntree_idname);
-
+
if (gnode) {
ngroup = (bNodeTree *)gnode->id;
-
+
nodeSetActive(ntree, gnode);
if (ngroup) {
ED_node_tree_push(snode, ngroup, gnode);
ntreeUpdateTree(bmain, ngroup);
}
}
-
+
ntreeUpdateTree(bmain, ntree);
snode_notify(C, snode);
snode_dag_update(C, snode);
-
+
return OPERATOR_FINISHED;
}
@@ -967,11 +971,11 @@ void NODE_OT_group_make(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -986,29 +990,29 @@ static int node_group_insert_exec(bContext *C, wmOperator *op)
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));
-
+
gnode = node_group_get_active(C, node_idname);
-
+
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;
-
+
node_group_make_insert_selected(C, ntree, gnode);
-
+
nodeSetActive(ntree, gnode);
ED_node_tree_push(snode, ngroup, gnode);
ntreeUpdateTree(bmain, ngroup);
-
+
ntreeUpdateTree(bmain, ntree);
-
+
snode_notify(C, snode);
snode_dag_update(C, snode);
-
+
return OPERATOR_FINISHED;
}
@@ -1018,11 +1022,11 @@ void NODE_OT_group_insert(wmOperatorType *ot)
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;
-
+
/* 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 1235133f8ac..2cc37a4e0fe 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -41,6 +41,7 @@ struct ARegion;
struct ARegionType;
struct View2D;
struct bContext;
+struct Main;
struct wmWindow;
struct bNode;
struct bNodeSocket;
@@ -50,7 +51,7 @@ struct wmKeyConfig;
/* 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.
@@ -157,7 +158,7 @@ void NODE_OT_group_edit(struct wmOperatorType *ot);
/* node_relationships.c */
-bool node_connected_to_output(struct bNodeTree *ntree, struct bNode *node);
+bool node_connected_to_output(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node);
void NODE_OT_link(struct wmOperatorType *ot);
void NODE_OT_link_make(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_node/node_manipulators.c b/source/blender/editors/space_node/node_manipulators.c
index 73b0f44b043..851e3973288 100644
--- a/source/blender/editors/space_node/node_manipulators.c
+++ b/source/blender/editors/space_node/node_manipulators.c
@@ -31,6 +31,7 @@
#include "BKE_context.h"
#include "BKE_image.h"
+#include "BKE_main.h"
#include "ED_screen.h"
#include "ED_manipulator_library.h"
@@ -140,13 +141,14 @@ static void WIDGETGROUP_node_transform_setup(const bContext *UNUSED(C), wmManipu
static void WIDGETGROUP_node_transform_refresh(const bContext *C, wmManipulatorGroup *mgroup)
{
+ Main *bmain = CTX_data_main(C);
wmManipulator *cage = ((wmManipulatorWrapper *)mgroup->customdata)->manipulator;
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(IMA_TYPE_COMPOSITE, "Viewer Node");
+ Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (ibuf) {
@@ -340,11 +342,12 @@ static void WIDGETGROUP_node_crop_draw_prepare(const bContext *C, wmManipulatorG
static void WIDGETGROUP_node_crop_refresh(const bContext *C, wmManipulatorGroup *mgroup)
{
+ Main *bmain = CTX_data_main(C);
struct NodeCropWidgetGroup *crop_group = mgroup->customdata;
wmManipulator *mpr = crop_group->border;
void *lock;
- Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (ibuf) {
@@ -451,11 +454,12 @@ static void WIDGETGROUP_node_sbeam_draw_prepare(const bContext *C, wmManipulator
static void WIDGETGROUP_node_sbeam_refresh(const bContext *C, wmManipulatorGroup *mgroup)
{
+ Main *bmain = CTX_data_main(C);
struct NodeSunBeamsWidgetGroup *sbeam_group = mgroup->customdata;
wmManipulator *mpr = sbeam_group->manipulator;
void *lock;
- Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (ibuf) {
@@ -563,10 +567,11 @@ static void WIDGETGROUP_node_corner_pin_draw_prepare(const bContext *C, wmManipu
static void WIDGETGROUP_node_corner_pin_refresh(const bContext *C, wmManipulatorGroup *mgroup)
{
+ Main *bmain = CTX_data_main(C);
struct NodeCornerPinWidgetGroup *cpin_group = mgroup->customdata;
void *lock;
- Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (ibuf) {
diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c
index c9c29212f02..2e429155ff7 100644
--- a/source/blender/editors/space_node/node_ops.c
+++ b/source/blender/editors/space_node/node_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation, Nathan Letwory
*
* ***** END GPL LICENSE BLOCK *****
@@ -50,7 +50,7 @@ void node_operatortypes(void)
{
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);
@@ -60,9 +60,9 @@ void node_operatortypes(void)
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_view_all);
WM_operatortype_append(NODE_OT_view_selected);
@@ -72,12 +72,12 @@ void node_operatortypes(void)
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_link);
WM_operatortype_append(NODE_OT_link_make);
WM_operatortype_append(NODE_OT_links_cut);
@@ -89,36 +89,36 @@ void node_operatortypes(void)
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_insert_offset);
-
+
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_add_file);
WM_operatortype_append(NODE_OT_add_mask);
-
+
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_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_shader_script_update);
WM_operatortype_append(NODE_OT_viewer_border);
@@ -135,7 +135,7 @@ 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);
@@ -149,7 +149,7 @@ void ED_operatormacros_node(void)
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",
@@ -212,7 +212,7 @@ static void node_select_keymap(wmKeyMap *keymap, int extend)
const int *mod = (extend ? mod_extend : mod_single);
wmKeyMapItem *kmi;
int i;
-
+
for (i = 0; mod[i] >= 0; ++i) {
kmi = WM_keymap_add_item(keymap, "NODE_OT_select", ACTIONMOUSE, KM_PRESS, mod[i], 0);
RNA_boolean_set(kmi->ptr, "extend", extend);
@@ -225,17 +225,17 @@ void node_keymap(struct wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
wmKeyMapItem *kmi;
-
+
/* Entire Editor only ----------------- */
keymap = WM_keymap_find(keyconf, "Node Generic", SPACE_NODE, 0);
-
+
WM_keymap_add_item(keymap, "NODE_OT_properties", NKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "NODE_OT_toolbar", TKEY, KM_PRESS, 0, 0);
-
+
/* Main Region only ----------------- */
keymap = WM_keymap_find(keyconf, "Node Editor", SPACE_NODE, 0);
-
- /* mouse select in nodes used to be both keys, but perhaps this should be reduced?
+
+ /* mouse select in nodes used to be both keys, but perhaps this should be reduced?
* NOTE: mouse-clicks on left-mouse will fall through to allow transform-tweak, but also link/resize
* NOTE 2: socket select is part of the node select operator, to handle overlapping cases
* NOTE 3: select op is registered for various combinations of modifier key, so the specialized
@@ -243,10 +243,10 @@ void node_keymap(struct wmKeyConfig *keyconf)
*/
node_select_keymap(keymap, false);
node_select_keymap(keymap, true);
-
+
kmi = WM_keymap_add_item(keymap, "NODE_OT_select_border", EVT_TWEAK_S, KM_ANY, 0, 0);
RNA_boolean_set(kmi->ptr, "tweak", true);
-
+
kmi = WM_keymap_add_item(keymap, "NODE_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "deselect", false);
kmi = WM_keymap_add_item(keymap, "NODE_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_SHIFT | KM_ALT, 0);
@@ -259,13 +259,13 @@ void node_keymap(struct wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "detach", false);
kmi = WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "detach", true);
-
+
WM_keymap_add_item(keymap, "NODE_OT_resize", LEFTMOUSE, KM_PRESS, 0, 0);
-
+
WM_keymap_add_item(keymap, "NODE_OT_add_reroute", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "NODE_OT_links_cut", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "NODE_OT_select_link_viewer", LEFTMOUSE, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
-
+
WM_keymap_add_item(keymap, "NODE_OT_backimage_move", MIDDLEMOUSE, KM_PRESS, KM_ALT, 0);
kmi = WM_keymap_add_item(keymap, "NODE_OT_backimage_zoom", VKEY, KM_PRESS, 0, 0);
RNA_float_set(kmi->ptr, "factor", 0.83333f);
@@ -274,6 +274,8 @@ void node_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "NODE_OT_backimage_fit", HOMEKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "NODE_OT_backimage_sample", ACTIONMOUSE, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_menu(keymap, "NODE_MT_specials", WKEY, KM_PRESS, 0, 0);
+
kmi = WM_keymap_add_item(keymap, "NODE_OT_link_make", FKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "replace", false);
kmi = WM_keymap_add_item(keymap, "NODE_OT_link_make", FKEY, KM_PRESS, KM_SHIFT, 0);
@@ -283,16 +285,16 @@ void node_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "NODE_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
/* modified operator call for duplicating with input links */
WM_keymap_add_item(keymap, "NODE_OT_duplicate_move_keep_inputs", DKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
-
+
WM_keymap_add_item(keymap, "NODE_OT_parent_set", PKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "NODE_OT_detach", PKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "NODE_OT_join", JKEY, KM_PRESS, KM_CTRL, 0);
-
+
WM_keymap_add_item(keymap, "NODE_OT_hide_toggle", HKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "NODE_OT_mute_toggle", MKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "NODE_OT_preview_toggle", HKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "NODE_OT_hide_socket_toggle", HKEY, KM_PRESS, KM_CTRL, 0);
-
+
WM_keymap_add_item(keymap, "NODE_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
#ifdef WITH_INPUT_NDOF
WM_keymap_add_item(keymap, "NODE_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0);
@@ -302,9 +304,12 @@ void node_keymap(struct wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "NODE_OT_select_border", BKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "tweak", false);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "NODE_OT_delete", XKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "NODE_OT_delete", DELKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "NODE_OT_delete_reconnect", XKEY, KM_PRESS, KM_CTRL, 0);
+#endif
+ WM_keymap_add_item(keymap, "NODE_OT_delete", DELKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "NODE_OT_delete_reconnect", DELKEY, KM_PRESS, KM_CTRL, 0);
kmi = WM_keymap_add_item(keymap, "NODE_OT_select_all", AKEY, KM_PRESS, 0, 0);
RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE);
@@ -322,9 +327,9 @@ void node_keymap(struct wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "prev", false);
kmi = WM_keymap_add_item(keymap, "NODE_OT_select_same_type_step", LEFTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "prev", true);
-
+
WM_keymap_add_item(keymap, "NODE_OT_find_node", FKEY, KM_PRESS, KM_CTRL, 0);
-
+
/* node group operators */
WM_keymap_add_item(keymap, "NODE_OT_group_make", GKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "NODE_OT_group_ungroup", GKEY, KM_PRESS, KM_ALT, 0);
@@ -336,7 +341,7 @@ void node_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "NODE_OT_read_viewlayers", RKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "NODE_OT_render_changed", ZKEY, KM_PRESS, 0, 0);
-
+
WM_keymap_add_item(keymap, "NODE_OT_clipboard_copy", CKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "NODE_OT_clipboard_paste", VKEY, KM_PRESS, KM_CTRL, 0);
#ifdef __APPLE__
diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c
index 70f7553cf41..c4cd59b65f4 100644
--- a/source/blender/editors/space_node/node_relationships.c
+++ b/source/blender/editors/space_node/node_relationships.c
@@ -131,9 +131,8 @@ static bool node_group_has_output_dfs(bNode *node)
return false;
}
-static bool node_group_has_output(bNode *node)
+static bool node_group_has_output(Main *bmain, bNode *node)
{
- Main *bmain = G.main;
BLI_assert(node->type == NODE_GROUP);
bNodeTree *ntree = (bNodeTree *)node->id;
if (ntree == NULL) {
@@ -143,7 +142,7 @@ static bool node_group_has_output(bNode *node)
return node_group_has_output_dfs(node);
}
-bool node_connected_to_output(bNodeTree *ntree, bNode *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
@@ -170,7 +169,7 @@ bool node_connected_to_output(bNodeTree *ntree, bNode *node)
return true;
}
if (ntree_check_nodes_connected(ntree, node, current_node) &&
- node_group_has_output(current_node))
+ node_group_has_output(bmain, current_node))
{
return true;
}
@@ -313,7 +312,7 @@ static bool snode_autoconnect_input(SpaceNode *snode, bNode *node_fr, bNodeSocke
return true;
}
-static void snode_autoconnect(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");
@@ -390,7 +389,7 @@ static void snode_autoconnect(SpaceNode *snode, const bool allow_multiple, const
}
if (numlinks > 0) {
- ntreeUpdateTree(G.main, ntree);
+ ntreeUpdateTree(bmain, ntree);
}
BLI_freelistN(nodelist);
@@ -533,7 +532,7 @@ static void node_link_update_header(bContext *C, bNodeLinkDrag *UNUSED(nldrag))
char header[UI_MAX_DRAW_STR];
BLI_strncpy(header, IFACE_("LMB: drag node link, RMB: cancel"), sizeof(header));
- ED_area_headerprint(CTX_wm_area(C), header);
+ ED_workspace_status_text(C, header);
}
static int node_count_links(bNodeTree *ntree, bNodeSocket *sock)
@@ -556,12 +555,12 @@ static void node_remove_extra_links(SpaceNode *snode, bNodeLink *link)
bNodeLink *tlink, *tlink_next;
int to_count = node_count_links(ntree, to);
int from_count = node_count_links(ntree, from);
-
+
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);
@@ -569,7 +568,7 @@ static void node_remove_extra_links(SpaceNode *snode, bNodeLink *link)
--from_count;
}
}
-
+
if (tlink && tlink->tosock == to) {
if (to_count > to->limit) {
nodeRemLink(ntree, tlink);
@@ -582,6 +581,7 @@ static void node_remove_extra_links(SpaceNode *snode, bNodeLink *link)
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;
@@ -607,20 +607,20 @@ static void node_link_exit(bContext *C, wmOperator *op, bool apply_links)
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(ntree, link->tonode));
+ do_tag_update |= (do_tag_update || node_connected_to_output(bmain, ntree, link->tonode));
}
}
else {
@@ -628,13 +628,13 @@ static void node_link_exit(bContext *C, wmOperator *op, bool apply_links)
}
}
ntree->is_updating = false;
-
- ntreeUpdateTree(CTX_data_main(C), ntree);
+
+ 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);
@@ -653,14 +653,14 @@ static void node_link_find_socket(bContext *C, wmOperator *op, float cursor[2])
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;
@@ -669,7 +669,7 @@ static void node_link_find_socket(bContext *C, wmOperator *op, float cursor[2])
else {
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
bNodeLink *link = linkdata->data;
-
+
link->tonode = NULL;
link->tosock = NULL;
}
@@ -679,14 +679,14 @@ static void node_link_find_socket(bContext *C, wmOperator *op, float cursor[2])
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;
@@ -695,7 +695,7 @@ static void node_link_find_socket(bContext *C, wmOperator *op, float cursor[2])
else {
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
bNodeLink *link = linkdata->data;
-
+
link->fromnode = NULL;
link->fromsock = NULL;
}
@@ -710,35 +710,38 @@ 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:
{
- node_link_exit(C, op, true);
-
- ED_area_headerprint(CTX_wm_area(C), NULL);
- ED_region_tag_redraw(ar);
- return OPERATOR_FINISHED;
+ 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(SpaceNode *snode, float cursor[2], bool detach)
+static bNodeLinkDrag *node_link_init(Main *bmain, SpaceNode *snode, float cursor[2], bool detach)
{
bNode *node;
bNodeSocket *sock;
@@ -772,7 +775,7 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, float cursor[2], bool det
* using TEST flag.
*/
oplink->flag &= ~NODE_LINK_TEST;
- if (node_connected_to_output(snode->edittree, link->tonode)) {
+ if (node_connected_to_output(bmain, snode->edittree, link->tonode)) {
oplink->flag |= NODE_LINK_TEST;
}
@@ -791,7 +794,7 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, float cursor[2], bool det
oplink->fromsock = sock;
oplink->flag |= NODE_LINK_VALID;
oplink->flag &= ~NODE_LINK_TEST;
- if (node_connected_to_output(snode->edittree, node)) {
+ if (node_connected_to_output(bmain, snode->edittree, node)) {
oplink->flag |= NODE_LINK_TEST;
}
@@ -816,13 +819,13 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, float cursor[2], bool det
oplink->next = oplink->prev = NULL;
oplink->flag |= NODE_LINK_VALID;
oplink->flag &= ~NODE_LINK_TEST;
- if (node_connected_to_output(snode->edittree, link->tonode)) {
+ 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);
@@ -839,32 +842,33 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, float cursor[2], bool det
oplink->tosock = sock;
oplink->flag |= NODE_LINK_VALID;
oplink->flag &= ~NODE_LINK_TEST;
- if (node_connected_to_output(snode->edittree, node)) {
+ 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];
-
+
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]);
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+ ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
- nldrag = node_link_init(snode, cursor, detach);
+ nldrag = node_link_init(bmain, snode, cursor, detach);
if (nldrag) {
op->customdata = nldrag;
@@ -915,12 +919,13 @@ 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");
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+ ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
- snode_autoconnect(snode, 1, replace);
+ snode_autoconnect(bmain, snode, 1, replace);
/* deselect sockets after linking */
node_deselect_all_input_sockets(snode, 0);
@@ -968,6 +973,7 @@ static bool cut_links_intersect(bNodeLink *link, float mcoords[][2], int tot)
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];
@@ -989,9 +995,9 @@ static int cut_links_exec(bContext *C, wmOperator *op)
if (i > 1) {
bool found = false;
bNodeLink *link, *next;
-
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
-
+
+ ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
+
for (link = snode->edittree->links.first; link; link = next) {
next = link->next;
if (nodeLinkIsHidden(link))
@@ -1001,11 +1007,11 @@ static int cut_links_exec(bContext *C, wmOperator *op)
if (found == false) {
/* TODO(sergey): Why did we kill jobs twice? */
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+ ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
found = true;
}
- do_tag_update |= (do_tag_update || node_connected_to_output(snode->edittree, link->tonode));
+ do_tag_update |= (do_tag_update || node_connected_to_output(bmain, snode->edittree, link->tonode));
snode_update(snode, link->tonode);
nodeRemLink(snode->edittree, link);
@@ -1294,7 +1300,7 @@ void NODE_OT_attach(wmOperatorType *ot)
ot->idname = "NODE_OT_attach";
/* api callbacks */
-
+
ot->invoke = node_attach_invoke;
ot->poll = ED_operator_node_editable;
@@ -1413,7 +1419,7 @@ static bool ed_node_link_conditions(ScrArea *sa, bool test, SpaceNode **r_snode,
for (link = snode->edittree->links.first; link; link = link->next) {
if (nodeLinkIsHidden(link))
continue;
-
+
if (link->tonode == select || link->fromnode == select)
return false;
}
@@ -1830,7 +1836,7 @@ void NODE_OT_insert_offset(wmOperatorType *ot)
}
/* assumes link with NODE_LINKFLAG_HILITE set */
-void ED_node_link_insert(ScrArea *sa)
+void ED_node_link_insert(Main *bmain, ScrArea *sa)
{
bNode *node, *select;
SpaceNode *snode;
@@ -1847,18 +1853,18 @@ void ED_node_link_insert(ScrArea *sa)
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__);
@@ -1870,7 +1876,7 @@ void ED_node_link_insert(ScrArea *sa)
snode->iofsd = iofsd;
}
- ntreeUpdateTree(G.main, snode->edittree); /* needed for pointers */
+ 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 4b4add0e698..636ed755cb1 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation, Nathan Letwory
*
* ***** END GPL LICENSE BLOCK *****
@@ -65,7 +65,7 @@
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))
@@ -78,7 +78,7 @@ static bNode *node_under_mouse_select(bNodeTree *ntree, int mx, int my)
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))
@@ -96,7 +96,7 @@ static void node_toggle(bNode *node)
void node_socket_select(bNode *node, bNodeSocket *sock)
{
sock->flag |= SELECT;
-
+
/* select node too */
if (node)
node->flag |= SELECT;
@@ -105,10 +105,10 @@ void node_socket_select(bNode *node, bNodeSocket *sock)
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) {
@@ -122,7 +122,7 @@ void node_socket_deselect(bNode *node, bNodeSocket *sock, const bool deselect_no
break;
}
}
-
+
if (!sel)
node->flag &= ~SELECT;
}
@@ -140,7 +140,7 @@ static void node_socket_toggle(bNode *node, bNodeSocket *sock, int deselect_node
void node_deselect_all(SpaceNode *snode)
{
bNode *node;
-
+
for (node = snode->edittree->nodes.first; node; node = node->next)
nodeSetSelected(node, false);
}
@@ -149,18 +149,18 @@ 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) {
@@ -169,7 +169,7 @@ void node_deselect_all_input_sockets(SpaceNode *snode, const bool deselect_nodes
break;
}
}
-
+
if (!sel)
node->flag &= ~SELECT;
}
@@ -180,18 +180,18 @@ void node_deselect_all_output_sockets(SpaceNode *snode, const bool deselect_node
{
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) {
@@ -200,7 +200,7 @@ void node_deselect_all_output_sockets(SpaceNode *snode, const bool deselect_node
break;
}
}
-
+
if (!sel)
node->flag &= ~SELECT;
}
@@ -364,32 +364,32 @@ void node_select_single(bContext *C, bNode *node)
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);
-
+
ED_node_set_active(bmain, snode->edittree, node);
ED_node_set_active_viewer_key(snode);
-
+
ED_node_sort(snode->edittree);
-
+
WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
}
/* ****** Click Select ****** */
-
+
static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const int mval[2], short extend)
{
bNode *node, *tnode;
bNodeSocket *sock, *tsock;
float cursor[2];
int selected = 0;
-
+
/* get mouse coordinates in view2d space */
UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &cursor[0], &cursor[1]);
-
+
if (extend) {
/* first do socket selection, these generally overlap with nodes.
* socket selection only in extend mode.
@@ -417,7 +417,7 @@ static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const i
else {
/* 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
@@ -435,10 +435,10 @@ static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const i
}
}
else { /* extend == 0 */
-
+
/* 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);
@@ -448,13 +448,13 @@ static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const i
selected = 1;
}
}
-
+
/* update node order */
if (selected) {
ED_node_set_active_viewer_key(snode);
ED_node_sort(snode->edittree);
}
-
+
return selected;
}
@@ -465,18 +465,18 @@ static int node_select_exec(bContext *C, wmOperator *op)
ARegion *ar = CTX_wm_region(C);
int mval[2];
short extend;
-
+
/* 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");
-
+
/* perform the select */
if (node_mouse_select(bmain, snode, ar, mval, extend)) {
/* send notifiers */
WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
-
+
/* allow tweak event to work too */
return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
}
@@ -501,15 +501,15 @@ void NODE_OT_select(wmOperatorType *ot)
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);
@@ -526,10 +526,10 @@ static int node_borderselect_exec(bContext *C, wmOperator *op)
rctf rectf;
const bool select = !RNA_boolean_get(op->ptr, "deselect");
const bool extend = RNA_boolean_get(op->ptr, "extend");
-
+
WM_operator_properties_border_to_rctf(op, &rectf);
UI_view2d_region_to_view_rctf(&ar->v2d, &rectf, &rectf);
-
+
for (node = snode->edittree->nodes.first; node; node = node->next) {
bool is_inside;
if (node->type == NODE_FRAME) {
@@ -546,9 +546,9 @@ static int node_borderselect_exec(bContext *C, wmOperator *op)
nodeSetSelected(node, false);
}
}
-
+
ED_node_sort(snode->edittree);
-
+
WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
@@ -557,7 +557,7 @@ static int node_borderselect_exec(bContext *C, wmOperator *op)
static int node_border_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
const bool tweak = RNA_boolean_get(op->ptr, "tweak");
-
+
if (tweak) {
/* prevent initiating the border select if the mouse is over a node */
/* this allows border select on empty space, but drag-translate on nodes */
@@ -566,11 +566,11 @@ static int node_border_select_invoke(bContext *C, wmOperator *op, const wmEvent
float mx, my;
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &mx, &my);
-
+
if (node_under_mouse_tweak(snode->edittree, mx, my))
return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
}
-
+
return WM_gesture_border_invoke(C, op, event);
}
@@ -580,18 +580,18 @@ void NODE_OT_select_border(wmOperatorType *ot)
ot->name = "Border Select";
ot->idname = "NODE_OT_select_border";
ot->description = "Use box selection to select nodes";
-
+
/* api callbacks */
ot->invoke = node_border_select_invoke;
ot->exec = node_borderselect_exec;
ot->modal = WM_gesture_border_modal;
ot->cancel = WM_gesture_border_cancel;
-
+
ot->poll = ED_operator_node_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* rna */
WM_operator_properties_gesture_border_select(ot);
RNA_def_boolean(ot->srna, "tweak", 0, "Tweak", "Only activate when mouse is not over a node - useful for tweak gesture");
@@ -653,7 +653,7 @@ void NODE_OT_select_circle(wmOperatorType *ot)
/* ****** Lasso Select ****** */
-static bool do_lasso_select_node(bContext *C, const int mcords[][2], short moves, short select)
+static bool do_lasso_select_node(bContext *C, const int mcords[][2], short moves, bool select, bool extend)
{
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node;
@@ -668,6 +668,11 @@ static bool do_lasso_select_node(bContext *C, const int mcords[][2], short moves
/* do actual selection */
for (node = snode->edittree->nodes.first; node; node = node->next) {
+
+ if (node->flag & NODE_SELECT && select && extend) {
+ continue;
+ }
+
int screen_co[2];
const float cent[2] = {BLI_rctf_cent_x(&node->totr),
BLI_rctf_cent_y(&node->totr)};
@@ -680,6 +685,10 @@ static bool do_lasso_select_node(bContext *C, const int mcords[][2], short moves
nodeSetSelected(node, select);
changed = true;
}
+ else if (select && !extend) {
+ nodeSetSelected(node, false);
+ changed = true;
+ }
}
if (changed) {
@@ -695,10 +704,9 @@ static int node_lasso_select_exec(bContext *C, wmOperator *op)
const int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
if (mcords) {
- short select;
-
- select = !RNA_boolean_get(op->ptr, "deselect");
- do_lasso_select_node(C, mcords, mcords_tot, select);
+ const bool select = !RNA_boolean_get(op->ptr, "deselect");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ do_lasso_select_node(C, mcords, mcords_tot, select, extend);
MEM_freeN((void *)mcords);
@@ -759,7 +767,7 @@ static int node_select_all_exec(bContext *C, wmOperator *op)
}
ED_node_sort(snode->edittree);
-
+
WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
}
@@ -770,11 +778,11 @@ void NODE_OT_select_all(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -788,7 +796,7 @@ 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;
@@ -798,14 +806,14 @@ static int node_select_linked_to_exec(bContext *C, wmOperator *UNUSED(op))
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;
}
@@ -816,11 +824,11 @@ void NODE_OT_select_linked_to(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -832,7 +840,7 @@ 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;
@@ -842,14 +850,14 @@ static int node_select_linked_from_exec(bContext *C, wmOperator *UNUSED(op))
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;
}
@@ -860,11 +868,11 @@ void NODE_OT_select_linked_from(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -878,29 +886,29 @@ static int node_select_same_type_step_exec(bContext *C, wmOperator *op)
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;
@@ -922,7 +930,7 @@ static int node_select_same_type_step_exec(bContext *C, wmOperator *op)
active = node_array[a + 1];
}
}
-
+
node_select_single(C, active);
/* is note outside view? */
@@ -933,10 +941,10 @@ static int node_select_same_type_step_exec(bContext *C, wmOperator *op)
space_node_view_flag(C, snode, ar, NODE_SELECT, smooth_viewtx);
}
}
-
+
if (node_array)
MEM_freeN(node_array);
-
+
return OPERATOR_FINISHED;
}
@@ -946,14 +954,14 @@ void NODE_OT_select_same_type_step(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
RNA_def_boolean(ot->srna, "prev", 0, "Previous", "");
}
@@ -965,12 +973,12 @@ static void node_find_cb(const struct bContext *C, void *UNUSED(arg), const char
{
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
@@ -985,11 +993,11 @@ 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)
@@ -1008,18 +1016,18 @@ static uiBlock *node_find_menu(bContext *C, ARegion *ar, void *arg_op)
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);
-
+
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, node_find_call_cb, NULL);
-
+
/* 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);
-
+
UI_block_bounds_set_popup(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */
-
+
// UI_but_active_only(C, ar, block, but); XXX using this here makes Blender hang - investigate
wm_event_init_from_window(win, &event);
event.type = EVT_BUT_OPEN;
@@ -1027,7 +1035,7 @@ static uiBlock *node_find_menu(bContext *C, ARegion *ar, void *arg_op)
event.customdata = but;
event.customdatafree = false;
wm_event_add(win, &event);
-
+
return block;
}
@@ -1045,16 +1053,14 @@ void NODE_OT_find_node(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "prev", 0, "Previous", "");
-
-}
+ 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 5f48b7d7a0f..b884db1ced4 100644
--- a/source/blender/editors/space_node/node_templates.c
+++ b/source/blender/editors/space_node/node_templates.c
@@ -64,7 +64,7 @@ typedef struct NodeLinkItem {
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 */
} NodeLinkItem;
@@ -82,16 +82,16 @@ static bool node_link_item_compare(bNode *node, NodeLinkItem *item)
return true;
}
-static void node_link_item_apply(bNode *node, NodeLinkItem *item)
+static void node_link_item_apply(Main *bmain, bNode *node, NodeLinkItem *item)
{
if (node->type == NODE_GROUP) {
node->id = (ID *)item->ngroup;
- ntreeUpdateTree(G.main, item->ngroup);
+ ntreeUpdateTree(bmain, item->ngroup);
}
else {
/* nothing to do for now */
}
-
+
if (node->id)
id_us_plus(node->id);
}
@@ -191,6 +191,7 @@ static void node_socket_remove(Main *bmain, bNodeTree *ntree, bNode *node_to, bN
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;
@@ -232,8 +233,8 @@ static void node_socket_add_replace(const bContext *C, bNodeTree *ntree, bNode *
node_from->locx = node_to->locx - (node_from->typeinfo->width + 50);
node_from->locy = node_to->locy - (node_from->typeinfo->height * index);
}
-
- node_link_item_apply(node_from, item);
+
+ node_link_item_apply(bmain, node_from, item);
}
nodeSetActive(ntree, node_from);
@@ -307,19 +308,19 @@ static void ui_node_link_items(NodeLinkArg *arg, int in_out, NodeLinkItem **r_it
/* 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->nodetree.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->nodetree.first; ngroup; ngroup = ngroup->id.next) {
ListBase *lb = (in_out == SOCK_IN ? &ngroup->inputs : &ngroup->outputs);
@@ -327,7 +328,7 @@ static void ui_node_link_items(NodeLinkArg *arg, int in_out, NodeLinkItem **r_it
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.
@@ -344,17 +345,17 @@ static void ui_node_link_items(NodeLinkArg *arg, int in_out, NodeLinkItem **r_it
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;
@@ -362,7 +363,7 @@ static void ui_node_link_items(NodeLinkArg *arg, int in_out, NodeLinkItem **r_it
}
}
}
-
+
*r_items = items;
*r_totitems = totitems;
}
@@ -446,7 +447,7 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
NodeLinkArg *argN;
int first = 1;
int compatibility = 0;
-
+
if (ntree->type == NTREE_SHADER) {
compatibility = NODE_NEW_SHADING;
}
@@ -483,29 +484,29 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
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;
@@ -521,15 +522,15 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
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);
}
@@ -634,7 +635,7 @@ static void ui_node_draw_node(uiLayout *layout, bContext *C, bNodeTree *ntree, b
if (node->typeinfo->draw_buttons) {
if (node->type != NODE_GROUP) {
- split = uiLayoutSplit(layout, 0.35f, false);
+ split = uiLayoutSplit(layout, 0.5f, false);
col = uiLayoutColumn(split, false);
col = uiLayoutColumn(split, false);
@@ -677,10 +678,10 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
label[i] = ' ';
}
label[indent] = '\0';
- BLI_snprintf(label + indent, UI_MAX_NAME_STR - indent, "%s:", IFACE_(input->name));
+ BLI_snprintf(label + indent, UI_MAX_NAME_STR - indent, "%s", IFACE_(input->name));
/* split in label and value */
- split = uiLayoutSplit(layout, 0.35f, false);
+ split = uiLayoutSplit(layout, 0.5f, false);
row = uiLayoutRow(split, true);
@@ -702,7 +703,7 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
uiItemL(row, label, ICON_NONE);
bt = block->buttons.last;
- bt->drawflag = UI_BUT_TEXT_LEFT;
+ bt->drawflag = UI_BUT_TEXT_RIGHT;
if (dependency_loop) {
row = uiLayoutRow(split, false);
@@ -736,7 +737,7 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
col = uiLayoutColumn(row, false);
uiItemR(col, &inputptr, "default_value", 0, "", ICON_NONE);
break;
-
+
default:
row = uiLayoutRow(split, false);
break;
@@ -768,4 +769,3 @@ void uiTemplateNodeView(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *
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 e3e263f2e44..21278dd9fa5 100644
--- a/source/blender/editors/space_node/node_toolbar.c
+++ b/source/blender/editors/space_node/node_toolbar.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2012 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Lukas Toenne
*
* ***** END GPL LICENSE BLOCK *****
@@ -55,7 +55,7 @@ static int node_toolbar_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = node_has_tools_region(sa);
-
+
if (ar)
ED_region_toggle_hidden(C, ar);
@@ -74,10 +74,10 @@ void NODE_OT_toolbar(wmOperatorType *ot)
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;
-
+
/* 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 f497a06cb12..00eab0c69c1 100644
--- a/source/blender/editors/space_node/node_view.c
+++ b/source/blender/editors/space_node/node_view.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation, Nathan Letwory
*
* ***** END GPL LICENSE BLOCK *****
@@ -36,8 +36,9 @@
#include "BKE_context.h"
#include "BKE_image.h"
-#include "BKE_screen.h"
+#include "BKE_main.h"
#include "BKE_node.h"
+#include "BKE_screen.h"
#include "ED_node.h" /* own include */
#include "ED_screen.h"
@@ -73,7 +74,7 @@ int space_node_view_flag(bContext *C, SpaceNode *snode, ARegion *ar,
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);
@@ -154,11 +155,11 @@ void NODE_OT_view_all(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -225,11 +226,12 @@ static int snode_bg_viewmove_modal(bContext *C, wmOperator *op, const wmEvent *e
case LEFTMOUSE:
case MIDDLEMOUSE:
case RIGHTMOUSE:
-
- MEM_freeN(nvm);
- op->customdata = NULL;
-
- return OPERATOR_FINISHED;
+ if (event->val == KM_RELEASE) {
+ MEM_freeN(nvm);
+ op->customdata = NULL;
+ return OPERATOR_FINISHED;
+ }
+ break;
}
return OPERATOR_RUNNING_MODAL;
@@ -237,6 +239,7 @@ static int snode_bg_viewmove_modal(bContext *C, wmOperator *op, const wmEvent *e
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;
@@ -246,7 +249,7 @@ static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *
void *lock;
- ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (ibuf == NULL) {
@@ -330,6 +333,7 @@ void NODE_OT_backimage_zoom(wmOperatorType *ot)
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);
@@ -342,7 +346,7 @@ static int backimage_fit_exec(bContext *C, wmOperator *UNUSED(op))
float facx, facy;
- ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ 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)) {
@@ -394,7 +398,7 @@ typedef struct ImageSampleInfo {
unsigned char col[4];
float colf[4];
float linearcol[4];
-
+
int z;
float zf;
@@ -420,7 +424,7 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info)
/* 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(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;
@@ -435,7 +439,7 @@ bool ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], floa
return false;
}
- ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (!ibuf) {
return false;
@@ -476,6 +480,7 @@ bool ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], floa
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;
@@ -484,7 +489,7 @@ static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event)
ImBuf *ibuf;
float fx, fy, bufx, bufy;
- ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (!ibuf) {
info->draw = 0;
@@ -545,7 +550,7 @@ static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event)
info->color_manage = true;
}
-
+
if (ibuf->zbuf) {
info->z = ibuf->zbuf[y * ibuf->x + x];
info->zp = &info->z;
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index a5f96ee04d6..fd485028f8e 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -54,6 +54,8 @@
#include "UI_view2d.h"
#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -71,30 +73,30 @@ void ED_node_tree_start(SpaceNode *snode, bNodeTree *ntree, ID *id, ID *from)
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;
-
+
/* 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));
-
+
BLI_addtail(&snode->treepath, path);
-
+
id_us_ensure_real(&ntree->id);
}
-
+
/* update current tree */
snode->nodetree = snode->edittree = ntree;
snode->id = id;
snode->from = from;
-
+
ED_node_set_active_viewer_key(snode);
-
+
WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
}
@@ -108,44 +110,44 @@ void ED_node_tree_push(SpaceNode *snode, bNodeTree *ntree, bNode *gnode)
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;
-
+
/* copy initial offset from bNodeTree */
copy_v2_v2(path->view_center, ntree->view_center);
-
+
BLI_addtail(&snode->treepath, path);
-
+
id_us_ensure_real(&ntree->id);
-
+
/* update current tree */
snode->edittree = ntree;
-
+
ED_node_set_active_viewer_key(snode);
-
+
WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
}
void ED_node_tree_pop(SpaceNode *snode)
{
bNodeTreePath *path = snode->treepath.last;
-
+
/* don't remove root */
if (path == snode->treepath.first)
return;
-
+
BLI_remlink(&snode->treepath, path);
MEM_freeN(path);
-
+
/* update current tree */
path = snode->treepath.last;
snode->edittree = path->nodetree;
-
+
ED_node_set_active_viewer_key(snode);
-
+
/* listener updates the View2D center from edittree */
WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
}
@@ -183,7 +185,7 @@ 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) {
@@ -201,7 +203,7 @@ void ED_node_tree_path_get_fixedbuf(SpaceNode *snode, char *value, int max_lengt
{
bNodeTreePath *path;
int size, i;
-
+
value[0] = '\0';
for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) {
if (i == 0) {
@@ -228,7 +230,7 @@ void ED_node_set_active_viewer_key(SpaceNode *snode)
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);
@@ -268,24 +270,24 @@ ARegion *node_has_buttons_region(ScrArea *sa)
ARegion *node_has_tools_region(ScrArea *sa)
{
ARegion *ar, *arnew;
-
+
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);
-
+
/* is error! */
if (ar == NULL) return NULL;
-
+
arnew = MEM_callocN(sizeof(ARegion), "node tools");
-
+
BLI_insertlinkafter(&sa->regionbase, ar, arnew);
arnew->regiontype = RGN_TYPE_TOOLS;
arnew->alignment = RGN_ALIGN_LEFT;
-
+
arnew->flag = RGN_FLAG_HIDDEN;
-
+
return arnew;
}
@@ -317,7 +319,7 @@ static SpaceLink *node_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scen
BLI_addtail(&snode->regionbase, ar);
ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = RGN_ALIGN_BOTTOM;
+ ar->alignment = RGN_ALIGN_TOP;
/* buttons/list view */
ar = MEM_callocN(sizeof(ARegion), "buttons for node");
@@ -401,7 +403,7 @@ static void node_area_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn
/* 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;
}
@@ -526,7 +528,7 @@ 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) {
@@ -601,7 +603,7 @@ static void node_buttons_region_init(wmWindowManager *wm, ARegion *ar)
static void node_buttons_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
/* add handlers, stuff you only do once or on area/region changes */
@@ -617,7 +619,7 @@ static void node_toolbar_region_init(wmWindowManager *wm, ARegion *ar)
static void node_toolbar_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
static void node_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
@@ -627,14 +629,14 @@ static void node_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
/* 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]);
-
+
/* 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. */
@@ -770,7 +772,6 @@ static void node_region_listener(
WM_manipulatormap_tag_refresh(mmap);
}
switch (wmn->data) {
- case ND_SCREENCAST:
case ND_ANIMPLAY:
case ND_LAYER:
ED_region_tag_redraw(ar);
@@ -942,6 +943,32 @@ static void node_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID
}
}
+
+static int node_space_subtype_get(ScrArea *sa)
+{
+ 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));
+}
+
+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);
+ }
+}
+
/* only called once, from space/spacetypes.c */
void ED_spacetype_node(void)
{
@@ -963,6 +990,9 @@ void ED_spacetype_node(void)
st->dropboxes = node_dropboxes;
st->manipulators = 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");
@@ -1009,9 +1039,8 @@ void ED_spacetype_node(void)
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/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index 1cfe5b16fe1..b97cc13d713 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -24,9 +24,14 @@
* \ingroup spoutliner
*/
+#include <string.h>
+
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
+#include "DNA_group_types.h"
+#include "DNA_object_types.h"
+
#include "BKE_context.h"
#include "BKE_collection.h"
#include "BKE_layer.h"
@@ -36,9 +41,8 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
-#include "DNA_group_types.h"
-#include "DNA_object_types.h"
-
+#include "ED_object.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
#include "WM_api.h"
@@ -52,26 +56,44 @@
#include "outliner_intern.h" /* own include */
-/* Prototypes. */
-static int collection_delete_exec(struct bContext *C, struct wmOperator *op);
-
/* -------------------------------------------------------------------- */
-static LayerCollection *outliner_collection_active(bContext *C)
+bool outliner_is_collection_tree_element(const TreeElement *te)
{
- return CTX_data_layer_collection(C);
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ 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;
+ }
+
+ return false;
}
-SceneCollection *outliner_scene_collection_from_tree_element(TreeElement *te)
+Collection *outliner_collection_from_tree_element(const TreeElement *te)
{
TreeStoreElem *tselem = TREESTORE(te);
- if (tselem->type == TSE_SCENE_COLLECTION) {
- return te->directdata;
+ if (!tselem) {
+ return false;
}
- else if (tselem->type == TSE_LAYER_COLLECTION) {
+
+ if (tselem->type == TSE_LAYER_COLLECTION) {
LayerCollection *lc = te->directdata;
- return lc->scene_collection;
+ 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;
@@ -80,961 +102,616 @@ SceneCollection *outliner_scene_collection_from_tree_element(TreeElement *te)
/* -------------------------------------------------------------------- */
/* Poll functions. */
-static int collections_editor_poll(bContext *C)
+int ED_outliner_collections_editor_poll(bContext *C)
{
SpaceOops *so = CTX_wm_space_outliner(C);
- return (so != NULL) && (so->outlinevis == SO_COLLECTIONS);
+ return (so != NULL) && ELEM(so->outlinevis, SO_VIEW_LAYER, SO_SCENES, SO_LIBRARIES);
}
-static int outliner_objects_collection_poll(bContext *C)
-{
- SpaceOops *so = CTX_wm_space_outliner(C);
- if (so == NULL) {
- return 0;
- }
-
- /* Groups don't support filtering. */
- if ((so->outlinevis != SO_GROUPS) && (so->filter & SO_FILTER_NO_COLLECTION)) {
- return 0;
- }
+/********************************* New Collection ****************************/
- return ELEM(so->outlinevis, SO_COLLECTIONS, SO_GROUPS);
-}
-
-/* -------------------------------------------------------------------- */
-/* collection manager operators */
-
-/**
- * Recursively get the collection for a given index
- */
-static SceneCollection *scene_collection_from_index(ListBase *lb, const int number, int *i)
+struct CollectionNewData
{
- for (SceneCollection *sc = lb->first; sc; sc = sc->next) {
- if (*i == number) {
- return sc;
- }
+ bool error;
+ Collection *collection;
+};
- (*i)++;
+static TreeTraversalAction collection_find_selected_to_add(TreeElement *te, void *customdata)
+{
+ struct CollectionNewData *data = customdata;
+ Collection *collection = outliner_collection_from_tree_element(te);
- SceneCollection *sc_nested = scene_collection_from_index(&sc->scene_collections, number, i);
- if (sc_nested) {
- return sc_nested;
- }
+ if (!collection) {
+ return TRAVERSE_SKIP_CHILDS;
}
- return NULL;
-}
-
-typedef struct TreeElementFindData {
- SceneCollection *collection;
- TreeElement *r_result_te;
-} TreeElementFindData;
-
-static TreeTraversalAction tree_element_find_by_scene_collection_cb(TreeElement *te, void *customdata)
-{
- TreeElementFindData *data = customdata;
- const SceneCollection *current_element_sc = outliner_scene_collection_from_tree_element(te);
- if (current_element_sc == data->collection) {
- data->r_result_te = te;
+ if (data->collection != NULL) {
+ data->error = true;
return TRAVERSE_BREAK;
}
+ data->collection = collection;
return TRAVERSE_CONTINUE;
}
-static TreeElement *outliner_tree_element_from_layer_collection_index(
- SpaceOops *soops, ViewLayer *view_layer,
- const int index)
+static int collection_new_exec(bContext *C, wmOperator *op)
{
- LayerCollection *lc = BKE_layer_collection_from_index(view_layer, index);
-
- if (lc == NULL) {
- return NULL;
- }
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
- /* Find the tree element containing the LayerCollection's scene_collection. */
- TreeElementFindData data = {
- .collection = lc->scene_collection,
- .r_result_te = NULL,
+ struct CollectionNewData data = {
+ .error = false,
+ .collection = NULL,
};
- outliner_tree_traverse(soops, &soops->tree, 0, 0, tree_element_find_by_scene_collection_cb, &data);
- return data.r_result_te;
-}
+ if (RNA_boolean_get(op->ptr, "nested")) {
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_selected_to_add, &data);
-static int collection_link_exec(bContext *C, wmOperator *op)
-{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- SceneCollection *sc_master = BKE_collection_master(&scene->id);
- SceneCollection *sc;
-
- int scene_collection_index = RNA_enum_get(op->ptr, "scene_collection");
- if (scene_collection_index == 0) {
- sc = sc_master;
- }
- else {
- int index = 1;
- sc = scene_collection_from_index(&sc_master->scene_collections, scene_collection_index, &index);
- BLI_assert(sc);
+ if (data.error) {
+ BKE_report(op->reports, RPT_ERROR, "More than one collection is selected");
+ return OPERATOR_CANCELLED;
+ }
}
- BKE_collection_link(view_layer, sc);
+ if (!data.collection && (soops->outlinevis == SO_VIEW_LAYER)) {
+ data.collection = BKE_collection_master(scene);
+ }
- DEG_relations_tag_update(CTX_data_main(C));
+ BKE_collection_add(
+ bmain,
+ data.collection,
+ NULL);
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(&scene->id, 0);
+ DEG_id_tag_update(&data.collection->id, DEG_TAG_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+ outliner_cleanup_tree(soops);
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
return OPERATOR_FINISHED;
}
-static int collection_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- Scene *scene = CTX_data_scene(C);
- SceneCollection *master_collection = BKE_collection_master(&scene->id);
- if (master_collection->scene_collections.first == NULL) {
- RNA_enum_set(op->ptr, "scene_collection", 0);
- return collection_link_exec(C, op);
- }
- else {
- return WM_enum_search_invoke(C, op, event);
- }
-}
-
-static void collection_scene_collection_itemf_recursive(
- EnumPropertyItem *tmp, EnumPropertyItem **item, int *totitem, int *value, SceneCollection *sc)
-{
- tmp->value = *value;
- tmp->icon = ICON_COLLAPSEMENU;
- tmp->identifier = sc->name;
- tmp->name = sc->name;
- RNA_enum_item_add(item, totitem, tmp);
-
- (*value)++;
-
- for (SceneCollection *ncs = sc->scene_collections.first; ncs; ncs = ncs->next) {
- collection_scene_collection_itemf_recursive(tmp, item, totitem, value, ncs);
- }
-}
-
-static const EnumPropertyItem *collection_scene_collection_itemf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
-{
- EnumPropertyItem tmp = {0, "", 0, "", ""};
- EnumPropertyItem *item = NULL;
- int value = 0, totitem = 0;
-
- Scene *scene = CTX_data_scene(C);
- SceneCollection *sc = BKE_collection_master(&scene->id);
-
- collection_scene_collection_itemf_recursive(&tmp, &item, &totitem, &value, sc);
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
-}
-
-void OUTLINER_OT_collection_link(wmOperatorType *ot)
+void OUTLINER_OT_collection_new(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
/* identifiers */
- ot->name = "Link Collection";
- ot->idname = "OUTLINER_OT_collection_link";
- ot->description = "Link a new collection to the active layer";
+ ot->name = "New Collection";
+ ot->idname = "OUTLINER_OT_collection_new";
+ ot->description = "Add a new collection inside selected collection";
/* api callbacks */
- ot->exec = collection_link_exec;
- ot->invoke = collection_link_invoke;
+ ot->exec = collection_new_exec;
+ ot->poll = ED_outliner_collections_editor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- prop = RNA_def_enum(ot->srna, "scene_collection", DummyRNA_NULL_items, 0, "Scene Collection", "");
- RNA_def_enum_funcs(prop, collection_scene_collection_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ /* 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);
}
-/**
- * Returns true if selected element is a collection directly
- * linked to the active ViewLayer (not a nested collection)
- */
-static int collection_unlink_poll(bContext *C)
-{
- if (collections_editor_poll(C) == 0) {
- return 0;
- }
+/**************************** Delete Collection ******************************/
- LayerCollection *lc = outliner_collection_active(C);
-
- if (lc == NULL) {
- return 0;
- }
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
- return BLI_findindex(&view_layer->layer_collections, lc) != -1 ? 1 : 0;
-}
+struct CollectionEditData {
+ Scene *scene;
+ SpaceOops *soops;
+ GSet *collections_to_edit;
+};
-static int collection_unlink_exec(bContext *C, wmOperator *op)
+static TreeTraversalAction collection_find_data_to_edit(TreeElement *te, void *customdata)
{
- LayerCollection *lc = outliner_collection_active(C);
- SpaceOops *soops = CTX_wm_space_outliner(C);
+ struct CollectionEditData *data = customdata;
+ Collection *collection = outliner_collection_from_tree_element(te);
- if (lc == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Active element is not a collection");
- return OPERATOR_CANCELLED;
+ if (!collection) {
+ return TRAVERSE_SKIP_CHILDS;
}
- ViewLayer *view_layer = CTX_data_view_layer(C);
- BKE_collection_unlink(view_layer, lc);
-
- if (soops) {
- outliner_cleanup_tree(soops);
+ if (collection == BKE_collection_master(data->scene)) {
+ /* skip - showing warning/error message might be missleading
+ * 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;
}
- DEG_relations_tag_update(CTX_data_main(C));
-
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(&CTX_data_scene(C)->id, 0);
-
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- return OPERATOR_FINISHED;
+ return TRAVERSE_CONTINUE;
}
-void OUTLINER_OT_collection_unlink(wmOperatorType *ot)
+static int collection_delete_exec(bContext *C, wmOperator *op)
{
- /* identifiers */
- ot->name = "Unlink Collection";
- ot->idname = "OUTLINER_OT_collection_unlink";
- ot->description = "Unlink collection from the active layer";
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ struct CollectionEditData data = {.scene = scene, .soops = soops};
+ bool hierarchy = RNA_boolean_get(op->ptr, "hierarchy");
- /* api callbacks */
- ot->exec = collection_unlink_exec;
- ot->poll = collection_unlink_poll;
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
+ /* 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);
-/**********************************************************************************/
-/* Add new collection. */
+ /* 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);
-static int collection_new_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);
- SceneCollection *scene_collection_parent = BKE_collection_master(&scene->id);
- SceneCollection *scene_collection = BKE_collection_add(&scene->id, scene_collection_parent, COLLECTION_TYPE_NONE, NULL);
- BKE_collection_link(view_layer, scene_collection);
+ /* Test in case collection got deleted as part of another one. */
+ if (BLI_findindex(&bmain->collection, collection) != -1) {
+ BKE_collection_delete(bmain, collection, hierarchy);
+ }
+ }
+ BLI_gset_free(data.collections_to_edit, NULL);
+
+ DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
DEG_relations_tag_update(bmain);
+
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
return OPERATOR_FINISHED;
}
-void OUTLINER_OT_collection_new(wmOperatorType *ot)
+void OUTLINER_OT_collection_delete(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "New Collection";
- ot->idname = "OUTLINER_OT_collection_new";
- ot->description = "Add a new collection to the scene";
+ ot->name = "Delete Collection";
+ ot->idname = "OUTLINER_OT_collection_delete";
+ ot->description = "Delete selected collections";
/* api callbacks */
- ot->exec = collection_new_exec;
+ ot->exec = collection_delete_exec;
+ ot->poll = ED_outliner_collections_editor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ PropertyRNA *prop = RNA_def_boolean(ot->srna, "hierarchy", false, "Hierarchy", "Delete child objects and collections");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/**********************************************************************************/
-/* Add new nested collection. */
+/****************************** Select Objects *******************************/
-struct CollectionNewData
-{
+struct CollectionObjectsSelectData {
bool error;
- SceneCollection *scene_collection;
+ LayerCollection *layer_collection;
};
-static TreeTraversalAction collection_find_selected_to_add(TreeElement *te, void *customdata)
+static TreeTraversalAction outliner_find_first_selected_layer_collection(TreeElement *te, void *customdata)
{
- struct CollectionNewData *data = customdata;
- SceneCollection *scene_collection = outliner_scene_collection_from_tree_element(te);
-
- if (!scene_collection) {
- return TRAVERSE_SKIP_CHILDS;
- }
+ struct CollectionObjectsSelectData *data = customdata;
+ TreeStoreElem *tselem = TREESTORE(te);
- if (data->scene_collection != NULL) {
- data->error = true;
- return TRAVERSE_BREAK;
+ 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;
}
-
- data->scene_collection = scene_collection;
- return TRAVERSE_CONTINUE;
}
-static int collection_nested_new_exec(bContext *C, wmOperator *op)
+static LayerCollection *outliner_active_layer_collection(bContext *C)
{
SpaceOops *soops = CTX_wm_space_outliner(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- struct CollectionNewData data = {
- .error = false,
- .scene_collection = NULL,
+ struct CollectionObjectsSelectData data = {
+ .layer_collection = NULL,
};
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_selected_to_add, &data);
+ 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");
- if (data.error) {
- BKE_report(op->reports, RPT_ERROR, "More than one collection is selected");
+ if (layer_collection == NULL) {
return OPERATOR_CANCELLED;
}
- BKE_collection_add(
- &scene->id,
- data.scene_collection,
- COLLECTION_TYPE_NONE,
- NULL);
+ BKE_layer_collection_objects_select(view_layer, layer_collection, deselect);
+
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
- outliner_cleanup_tree(soops);
- DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
return OPERATOR_FINISHED;
}
-void OUTLINER_OT_collection_nested_new(wmOperatorType *ot)
+void OUTLINER_OT_collection_objects_select(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "New Nested Collection";
- ot->idname = "OUTLINER_OT_collection_nested_new";
- ot->description = "Add a new collection inside selected collection";
+ ot->name = "Select Objects";
+ ot->idname = "OUTLINER_OT_collection_objects_select";
+ ot->description = "Select objects in collection";
/* api callbacks */
- ot->exec = collection_nested_new_exec;
- ot->poll = collections_editor_poll;
+ ot->exec = collection_objects_select_exec;
+ ot->poll = ED_outliner_collections_editor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/**********************************************************************************/
-/* Delete selected collection. */
-
-void OUTLINER_OT_collection_delete_selected(wmOperatorType *ot)
+void OUTLINER_OT_collection_objects_deselect(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Delete Selected Collections";
- ot->idname = "OUTLINER_OT_collection_delete_selected";
- ot->description = "Delete all the selected collections";
+ ot->name = "Deselect Objects";
+ ot->idname = "OUTLINER_OT_collection_objects_deselect";
+ ot->description = "Deselect objects in collection";
/* api callbacks */
- ot->exec = collection_delete_exec;
- ot->poll = collections_editor_poll;
+ ot->exec = collection_objects_select_exec;
+ ot->poll = ED_outliner_collections_editor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/**********************************************************************************/
-/* Add new selected objects. */
+/************************** Duplicate Collection *****************************/
-struct SceneCollectionSelectedData {
- ListBase scene_collections_array;
+struct CollectionDuplicateData {
+ TreeElement *te;
};
-static TreeTraversalAction collection_find_selected_scene_collections(TreeElement *te, void *customdata)
+static TreeTraversalAction outliner_find_first_selected_collection(TreeElement *te, void *customdata)
{
- struct SceneCollectionSelectedData *data = customdata;
- SceneCollection *scene_collection = outliner_scene_collection_from_tree_element(te);
+ struct CollectionDuplicateData *data = customdata;
+ TreeStoreElem *tselem = TREESTORE(te);
- if (!scene_collection) {
- return TRAVERSE_SKIP_CHILDS;
+ 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;
}
-
- BLI_addtail(&data->scene_collections_array, BLI_genericNodeN(scene_collection));
- return TRAVERSE_CONTINUE;
}
-static int collection_objects_add_exec(bContext *C, wmOperator *op)
+static TreeElement *outliner_active_collection(bContext *C)
{
SpaceOops *soops = CTX_wm_space_outliner(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- struct SceneCollectionSelectedData data = {
- .scene_collections_array = {NULL, NULL},
+ struct CollectionDuplicateData data = {
+ .te = NULL,
};
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_selected_scene_collections, &data);
-
- if (BLI_listbase_is_empty(&data.scene_collections_array)) {
- BKE_report(op->reports, RPT_ERROR, "No collection is selected");
- return OPERATOR_CANCELLED;
- }
-
- CTX_DATA_BEGIN (C, struct Object *, ob, selected_objects)
- {
- LISTBASE_FOREACH (LinkData *, link, &data.scene_collections_array) {
- SceneCollection *scene_collection = link->data;
- BKE_collection_object_add(
- &scene->id,
- scene_collection,
- ob);
- }
- }
- CTX_DATA_END;
- BLI_freelistN(&data.scene_collections_array);
-
- outliner_cleanup_tree(soops);
- DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- return OPERATOR_FINISHED;
-}
-
-void OUTLINER_OT_collection_objects_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Objects";
- ot->idname = "OUTLINER_OT_collection_objects_add";
- ot->description = "Add selected objects to collection";
-
- /* api callbacks */
- ot->exec = collection_objects_add_exec;
- ot->poll = collections_editor_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_first_selected_collection, &data);
+ return data.te;
}
-/**********************************************************************************/
-/* Remove selected objects. */
-
-
-static int collection_objects_remove_exec(bContext *C, wmOperator *op)
+static int collection_duplicate_exec(bContext *C, wmOperator *op)
{
- SpaceOops *soops = CTX_wm_space_outliner(C);
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
-
- struct SceneCollectionSelectedData data = {
- .scene_collections_array = {NULL, NULL},
- };
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ TreeElement *te = outliner_active_collection(C);
+ BLI_assert(te != NULL);
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_selected_scene_collections, &data);
+ Collection *collection = outliner_collection_from_tree_element(te);
+ Collection *parent = (te->parent) ? outliner_collection_from_tree_element(te->parent) : NULL;
- if (BLI_listbase_is_empty(&data.scene_collections_array)) {
- BKE_report(op->reports, RPT_ERROR, "No collection is selected");
+ if (collection->flag & COLLECTION_IS_MASTER) {
+ BKE_report(op->reports, RPT_ERROR, "Can't duplicate the master collection");
return OPERATOR_CANCELLED;
}
- CTX_DATA_BEGIN (C, struct Object *, ob, selected_objects)
- {
- LISTBASE_FOREACH (LinkData *, link, &data.scene_collections_array) {
- SceneCollection *scene_collection = link->data;
- BKE_collection_object_remove(
- bmain,
- &scene->id,
- scene_collection,
- ob,
- true);
- }
+ switch (soops->outlinevis) {
+ case SO_SCENES:
+ case SO_VIEW_LAYER:
+ case SO_LIBRARIES:
+ BKE_collection_copy(bmain, parent, collection);
+ break;
}
- CTX_DATA_END;
- BLI_freelistN(&data.scene_collections_array);
- outliner_cleanup_tree(soops);
DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, CTX_data_scene(C));
+
return OPERATOR_FINISHED;
}
-void OUTLINER_OT_collection_objects_remove(wmOperatorType *ot)
+void OUTLINER_OT_collection_duplicate(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Remove Objects";
- ot->idname = "OUTLINER_OT_collection_objects_remove";
- ot->description = "Remove selected objects from collection";
+ ot->name = "Duplicate Collection";
+ ot->idname = "OUTLINER_OT_collection_duplicate";
+ ot->description = "Duplicate selected collections";
/* api callbacks */
- ot->exec = collection_objects_remove_exec;
- ot->poll = collections_editor_poll;
+ ot->exec = collection_duplicate_exec;
+ ot->poll = ED_outliner_collections_editor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static TreeElement *outliner_collection_parent_element_get(TreeElement *te)
-{
- TreeElement *te_parent = te;
- while ((te_parent = te_parent->parent)) {
- if (outliner_scene_collection_from_tree_element(te->parent)) {
- return te_parent;
- }
- }
- return NULL;
-}
+/**************************** Link Collection ******************************/
-static int object_collection_remove_exec(bContext *C, wmOperator *UNUSED(op))
+static int collection_link_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceOops *soops = CTX_wm_space_outliner(C);
Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Collection *active_collection = CTX_data_layer_collection(C)->collection;
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ struct CollectionEditData data = {.scene = scene, .soops = soops};
- struct ObjectsSelectedData data = {
- .objects_selected_array = {NULL, NULL},
- };
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &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);
- LISTBASE_FOREACH (LinkData *, link, &data.objects_selected_array) {
- TreeElement *te = (TreeElement *)link->data;
- Object *ob = (Object *)TREESTORE(te)->id;
- SceneCollection *scene_collection = NULL;
-
- TreeElement *te_parent = outliner_collection_parent_element_get(te);
- if (te_parent != NULL) {
- scene_collection = outliner_scene_collection_from_tree_element(te_parent);
- ID *owner_id = TREESTORE(te_parent)->id;
- BKE_collection_object_remove(bmain, owner_id, scene_collection, ob, true);
- DEG_id_tag_update(owner_id, DEG_TAG_BASE_FLAGS_UPDATE);
- }
+ /* 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_freelistN(&data.objects_selected_array);
+ BLI_gset_free(data.collections_to_edit, NULL);
- outliner_cleanup_tree(soops);
+ DEG_id_tag_update(&active_collection->id, DEG_TAG_COPY_ON_WRITE);
DEG_relations_tag_update(bmain);
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- WM_main_add_notifier(NC_SCENE | ND_OB_ACTIVE, NULL);
- WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, NULL);
return OPERATOR_FINISHED;
}
-void OUTLINER_OT_object_remove_from_collection(wmOperatorType *ot)
+void OUTLINER_OT_collection_link(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Remove Object from Collection";
- ot->idname = "OUTLINER_OT_object_remove_from_collection";
- ot->description = "Remove selected objects from their respective collection";
+ ot->name = "Link Collection";
+ ot->idname = "OUTLINER_OT_collection_link";
+ ot->description = "Link selected collections to active scene";
/* api callbacks */
- ot->exec = object_collection_remove_exec;
- ot->poll = outliner_objects_collection_poll;
+ ot->exec = collection_link_exec;
+ ot->poll = ED_outliner_collections_editor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int object_add_to_new_collection_exec(bContext *C, wmOperator *op)
-{
- int operator_result = OPERATOR_CANCELLED;
+/************************** Instance Collection ******************************/
- SpaceOops *soops = CTX_wm_space_outliner(C);
+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);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ struct CollectionEditData data = {.scene = scene, .soops = soops};
- SceneCollection *scene_collection_parent, *scene_collection_new;
- TreeElement *te_active, *te_parent;
-
- struct ObjectsSelectedData data = {{NULL}}, active = {{NULL}};
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_HIGHLIGHTED, outliner_find_selected_objects, &active);
- if (BLI_listbase_is_empty(&active.objects_selected_array)) {
- BKE_report(op->reports, RPT_ERROR, "No object is selected");
- goto cleanup;
- }
+ /* 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);
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &data);
- if (BLI_listbase_is_empty(&data.objects_selected_array)) {
- BKE_report(op->reports, RPT_ERROR, "No objects are selected");
- goto cleanup;
- }
+ /* Find an active collection to add to, that doesn't give dependency cycles. */
+ LayerCollection *active_lc = BKE_layer_collection_get_active(view_layer);
- /* Heuristic to get the "active" / "last object" */
- te_active = ((LinkData *)active.objects_selected_array.first)->data;
- te_parent = outliner_collection_parent_element_get(te_active);
+ 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 (te_parent == NULL) {
- BKE_reportf(op->reports, RPT_ERROR, "Couldn't find collection of \"%s\" object", te_active->name);
- goto cleanup;
+ while (BKE_collection_find_cycle(active_lc->collection, collection)) {
+ active_lc = BKE_layer_collection_activate_parent(view_layer, active_lc);
+ }
}
- ID *owner_id = TREESTORE(te_parent)->id;
- scene_collection_parent = outliner_scene_collection_from_tree_element(te_parent);
- scene_collection_new = BKE_collection_add(owner_id, scene_collection_parent, scene_collection_parent->type, NULL);
-
- LISTBASE_FOREACH (LinkData *, link, &data.objects_selected_array) {
- TreeElement *te = (TreeElement *)link->data;
- Object *ob = (Object *)TREESTORE(te)->id;
- BKE_collection_object_add(owner_id, scene_collection_new, ob);
+ /* 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, scene->layact);
+ ob->dup_group = collection;
+ ob->transflag |= OB_DUPLICOLLECTION;
+ id_lib_extern(&collection->id);
}
- outliner_cleanup_tree(soops);
+ BLI_gset_free(data.collections_to_edit, NULL);
+
DEG_relations_tag_update(bmain);
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- operator_result = OPERATOR_FINISHED;
-cleanup:
- BLI_freelistN(&active.objects_selected_array);
- BLI_freelistN(&data.objects_selected_array);
- return operator_result;
+ return OPERATOR_FINISHED;
}
-void OUTLINER_OT_object_add_to_new_collection(wmOperatorType *ot)
+void OUTLINER_OT_collection_instance(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Add Objects to New Collection";
- ot->idname = "OUTLINER_OT_object_add_to_new_collection";
- ot->description = "Add objects to a new collection";
+ ot->name = "Instance Collection";
+ ot->idname = "OUTLINER_OT_collection_instance";
+ ot->description = "Instance selected collections to active scene";
/* api callbacks */
- ot->exec = object_add_to_new_collection_exec;
- ot->poll = outliner_objects_collection_poll;
+ ot->exec = collection_instance_exec;
+ ot->poll = ED_outliner_collections_editor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-struct CollectionDeleteData {
- Scene *scene;
- SpaceOops *soops;
- GSet *collections_to_delete;
-};
+/************************** Exclude Collection ******************************/
-static TreeTraversalAction collection_find_data_to_delete(TreeElement *te, void *customdata)
+static TreeTraversalAction layer_collection_find_data_to_edit(TreeElement *te, void *customdata)
{
- struct CollectionDeleteData *data = customdata;
- SceneCollection *scene_collection = outliner_scene_collection_from_tree_element(te);
+ struct CollectionEditData *data = customdata;
+ TreeStoreElem *tselem = TREESTORE(te);
- if (!scene_collection) {
- return TRAVERSE_SKIP_CHILDS;
+ if (!(tselem && tselem->type == TSE_LAYER_COLLECTION)) {
+ return TRAVERSE_CONTINUE;
}
- if (scene_collection == BKE_collection_master(&data->scene->id)) {
+ LayerCollection *lc = te->directdata;
+
+ if (lc->collection->flag & COLLECTION_IS_MASTER) {
/* skip - showing warning/error message might be missleading
* when deleting multiple collections, so just do nothing */
}
else {
- BLI_gset_add(data->collections_to_delete, scene_collection);
- return TRAVERSE_SKIP_CHILDS; /* Childs will be gone anyway, no need to recurse deeper. */
+ /* 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;
}
-static TreeTraversalAction collection_delete_elements_from_collection(TreeElement *te, void *customdata)
+static int collections_view_layer_poll(bContext *C, bool include)
{
- struct CollectionDeleteData *data = customdata;
- SceneCollection *scene_collection = outliner_scene_collection_from_tree_element(te);
-
- if (!scene_collection) {
- return TRAVERSE_SKIP_CHILDS;
- }
-
- const bool will_be_deleted = BLI_gset_haskey(data->collections_to_delete, scene_collection);
- if (will_be_deleted) {
- outliner_free_tree_element(te, te->parent ? &te->parent->subtree : &data->soops->tree);
- /* Childs are freed now, so don't recurse into them. */
- return TRAVERSE_SKIP_CHILDS;
+ /* Poll function so the right click menu show current state of selected collections. */
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ if (!(soops && soops->outlinevis == SO_VIEW_LAYER)) {
+ return false;
}
- return TRAVERSE_CONTINUE;
-}
-
-static int collection_delete_exec(bContext *C, wmOperator *UNUSED(op))
-{
Scene *scene = CTX_data_scene(C);
- SpaceOops *soops = CTX_wm_space_outliner(C);
- struct CollectionDeleteData data = {.scene = scene, .soops = soops};
+ struct CollectionEditData data = {.scene = scene, .soops = soops};
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
+ bool result = false;
- data.collections_to_delete = BLI_gset_ptr_new(__func__);
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, layer_collection_find_data_to_edit, &data);
- /* We first walk over and find the SceneCollections we actually want to delete (ignoring duplicates). */
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_data_to_delete, &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);
- /* Now, delete all tree elements representing a collection that will be deleted. We'll look for a
- * new element to select in a few lines, so we can't wait until the tree is recreated on redraw. */
- outliner_tree_traverse(soops, &soops->tree, 0, 0, collection_delete_elements_from_collection, &data);
-
- /* Effectively delete the collections. */
- GSetIterator collections_to_delete_iter;
- GSET_ITER(collections_to_delete_iter, data.collections_to_delete) {
- SceneCollection *sc = BLI_gsetIterator_getKey(&collections_to_delete_iter);
- BKE_collection_remove(&data.scene->id, sc);
- }
-
- BLI_gset_free(data.collections_to_delete, NULL);
-
- TreeElement *select_te = outliner_tree_element_from_layer_collection_index(soops, CTX_data_view_layer(C), 0);
- if (select_te) {
- outliner_item_select(soops, select_te, false, false);
+ if (include && (lc->flag & LAYER_COLLECTION_EXCLUDE)) {
+ result = true;
+ }
+ else if (!include && !(lc->flag & LAYER_COLLECTION_EXCLUDE)) {
+ result = true;
+ }
}
- DEG_relations_tag_update(CTX_data_main(C));
-
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(&scene->id, 0);
-
- soops->storeflag |= SO_TREESTORE_REDRAW;
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
-
- return OPERATOR_FINISHED;
+ BLI_gset_free(data.collections_to_edit, NULL);
+ return result;
}
-void OUTLINER_OT_collections_delete(wmOperatorType *ot)
+static int collections_exclude_poll(bContext *C)
{
- /* identifiers */
- ot->name = "Delete";
- ot->idname = "OUTLINER_OT_collections_delete";
- ot->description = "Delete selected overrides or collections";
-
- /* api callbacks */
- ot->exec = collection_delete_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ return collections_view_layer_poll(C, false);
}
-static int collection_select_exec(bContext *C, wmOperator *op)
+static int collections_include_poll(bContext *C)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const int collection_index = RNA_int_get(op->ptr, "collection_index");
- view_layer->active_collection = collection_index;
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- return OPERATOR_FINISHED;
+ return collections_view_layer_poll(C, true);
}
-void OUTLINER_OT_collection_select(wmOperatorType *ot)
+static void layer_collection_exclude_recursive_set(LayerCollection *lc)
{
- /* identifiers */
- ot->name = "Select";
- ot->idname = "OUTLINER_OT_collection_select";
- ot->description = "Change active collection or override";
-
- /* api callbacks */
- ot->exec = collection_select_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
+ if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
+ nlc->flag |= LAYER_COLLECTION_EXCLUDE;
+ }
+ else {
+ nlc->flag &= ~LAYER_COLLECTION_EXCLUDE;
+ }
- RNA_def_int(ot->srna, "collection_index", 0, 0, INT_MAX, "Index",
- "Index of collection to select", 0, INT_MAX);
+ layer_collection_exclude_recursive_set(nlc);
+ }
}
-#define ACTION_DISABLE 0
-#define ACTION_ENABLE 1
-#define ACTION_TOGGLE 2
-
-static int collection_toggle_exec(bContext *C, wmOperator *op)
+static int collection_view_layer_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- int action = RNA_enum_get(op->ptr, "action");
- LayerCollection *layer_collection = CTX_data_layer_collection(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ struct CollectionEditData data = {.scene = scene, .soops = soops};
+ bool include = STREQ(op->idname, "OUTLINER_OT_collection_include_set");
- if (layer_collection->flag & COLLECTION_DISABLED) {
- if (ELEM(action, ACTION_TOGGLE, ACTION_ENABLE)) {
- layer_collection->flag &= ~COLLECTION_DISABLED;
- }
- else { /* ACTION_DISABLE */
- BKE_reportf(op->reports, RPT_ERROR, "Layer collection %s already disabled",
- layer_collection->scene_collection->name);
- return OPERATOR_CANCELLED;
- }
- }
- else {
- if (ELEM(action, ACTION_TOGGLE, ACTION_DISABLE)) {
- layer_collection->flag |= COLLECTION_DISABLED;
- }
- else { /* ACTION_ENABLE */
- BKE_reportf(op->reports, RPT_ERROR, "Layer collection %s already enabled",
- layer_collection->scene_collection->name);
- return OPERATOR_CANCELLED;
+ 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);
+
+ 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 (!(lc->collection->flag & COLLECTION_IS_MASTER)) {
+ if (include) {
+ lc->flag &= ~LAYER_COLLECTION_EXCLUDE;
+ }
+ else {
+ lc->flag |= LAYER_COLLECTION_EXCLUDE;
+ }
+
+ layer_collection_exclude_recursive_set(lc);
}
}
+ BLI_gset_free(data.collections_to_edit, NULL);
+
+ BKE_layer_collection_sync(scene, view_layer);
DEG_relations_tag_update(bmain);
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(&scene->id, 0);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
return OPERATOR_FINISHED;
}
-void OUTLINER_OT_collection_toggle(wmOperatorType *ot)
+void OUTLINER_OT_collection_exclude_set(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- static EnumPropertyItem actions_items[] = {
- {ACTION_DISABLE, "DISABLE", 0, "Disable", "Disable selected markers"},
- {ACTION_ENABLE, "ENABLE", 0, "Enable", "Enable selected markers"},
- {ACTION_TOGGLE, "TOGGLE", 0, "Toggle", "Toggle disabled flag for selected markers"},
- {0, NULL, 0, NULL, NULL}
- };
-
/* identifiers */
- ot->name = "Toggle Collection";
- ot->idname = "OUTLINER_OT_collection_toggle";
- ot->description = "Deselect collection objects";
+ ot->name = "Exclude from View Layer";
+ ot->idname = "OUTLINER_OT_collection_exclude_set";
+ ot->description = "Exclude collection from the active view layer";
/* api callbacks */
- ot->exec = collection_toggle_exec;
+ ot->exec = collection_view_layer_exec;
+ ot->poll = collections_exclude_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_int(ot->srna, "collection_index", -1, -1, INT_MAX, "Collection Index", "Index of collection to toggle", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_enum(ot->srna, "action", actions_items, ACTION_TOGGLE, "Action", "Selection action to execute");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-}
-
-#undef ACTION_TOGGLE
-#undef ACTION_ENABLE
-#undef ACTION_DISABLE
-
-struct CollectionObjectsSelectData {
- bool error;
- LayerCollection *layer_collection;
-};
-
-static TreeTraversalAction outliner_find_first_selected_layer_collection(TreeElement *te, void *customdata)
-{
- 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_LAYER_COLLECTION_BASE:
- return TRAVERSE_CONTINUE;
- default:
- return TRAVERSE_SKIP_CHILDS;
- }
}
-static LayerCollection *outliner_active_layer_collection(bContext *C)
-{
- SpaceOops *soops = CTX_wm_space_outliner(C);
-
- 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;
-}
-
-static int collection_objects_select_exec(bContext *C, wmOperator *UNUSED(op))
-{
- LayerCollection *layer_collection = outliner_active_layer_collection(C);
-
- if (layer_collection == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- BKE_layer_collection_objects_select(layer_collection);
- WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
-
- return OPERATOR_FINISHED;
-}
-
-void OUTLINER_OT_collection_objects_select(wmOperatorType *ot)
+void OUTLINER_OT_collection_include_set(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Select Objects";
- ot->idname = "OUTLINER_OT_collection_objects_select";
- ot->description = "Select all the collection objects";
+ ot->name = "Include in View Layer";
+ ot->idname = "OUTLINER_OT_collection_include_set";
+ ot->description = "Include collection in the active view layer";
/* api callbacks */
- ot->exec = collection_objects_select_exec;
- ot->poll = collections_editor_poll;
+ ot->exec = collection_view_layer_exec;
+ ot->poll = collections_include_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-struct CollectionDuplicateData {
- TreeElement *te;
-};
-
-static TreeTraversalAction outliner_find_first_selected_collection(TreeElement *te, void *customdata)
-{
- struct CollectionDuplicateData *data = customdata;
- TreeStoreElem *tselem = TREESTORE(te);
-
- switch (tselem->type) {
- case TSE_LAYER_COLLECTION:
- case TSE_SCENE_COLLECTION:
- data->te = te;
- return TRAVERSE_BREAK;
- case TSE_LAYER_COLLECTION_BASE:
- default:
- return TRAVERSE_CONTINUE;
- }
-}
-
-static TreeElement *outliner_active_collection(bContext *C)
-{
- SpaceOops *soops = CTX_wm_space_outliner(C);
-
- struct CollectionDuplicateData data = {
- .te = NULL,
- };
-
- 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)
+/**
+ * Populates the \param objects ListBase with all the outliner selected objects
+ * We store it as (Object *)LinkData->data
+ * \param objects expected to be empty
+ */
+void ED_outliner_selected_objects_get(const bContext *C, ListBase *objects)
{
SpaceOops *soops = CTX_wm_space_outliner(C);
- TreeElement *te = outliner_active_collection(C);
-
- BLI_assert(te != NULL);
- if (BKE_collection_master(TREESTORE(te)->id) == outliner_scene_collection_from_tree_element(te)) {
- BKE_report(op->reports, RPT_ERROR, "You can't duplicate the master collection");
- return OPERATOR_CANCELLED;
- }
-
- switch (soops->outlinevis) {
- case SO_SCENES:
- BKE_collection_duplicate(TREESTORE(te)->id, (SceneCollection *)te->directdata);
- break;
- case SO_COLLECTIONS:
- case SO_GROUPS:
- BKE_layer_collection_duplicate(TREESTORE(te)->id, (LayerCollection *)te->directdata);
- break;
+ struct ObjectsSelectedData data = {{NULL}};
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &data);
+ LISTBASE_FOREACH (LinkData *, link, &data.objects_selected_array) {
+ TreeElement *ten_selected = (TreeElement *)link->data;
+ Object *ob = (Object *)TREESTORE(ten_selected)->id;
+ BLI_addtail(objects, BLI_genericNodeN(ob));
}
-
- DEG_relations_tag_update(CTX_data_main(C));
- WM_main_add_notifier(NC_SCENE | ND_LAYER, CTX_data_scene(C));
-
- return OPERATOR_FINISHED;
-}
-
-void OUTLINER_OT_collection_duplicate(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Duplicate Collection";
- ot->idname = "OUTLINER_OT_collection_duplicate";
- ot->description = "Duplicate collection";
-
- /* api callbacks */
- ot->exec = collection_duplicate_exec;
- ot->poll = collections_editor_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ BLI_freelistN(&data.objects_selected_array);
}
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 5d981bdad0d..19e5217cdd2 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -51,6 +51,7 @@
#include "BKE_deform.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
+#include "BKE_idcode.h"
#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_main.h"
@@ -71,6 +72,7 @@
#include "WM_types.h"
#include "GPU_immediate.h"
+#include "GPU_state.h"
#include "UI_interface.h"
#include "UI_interface_icons.h"
@@ -92,8 +94,9 @@ static void outliner_height(SpaceOops *soops, ListBase *lb, int *h)
TreeElement *te = lb->first;
while (te) {
TreeStoreElem *tselem = TREESTORE(te);
- if (TSELEM_OPEN(tselem, soops))
+ if (TSELEM_OPEN(tselem, soops)) {
outliner_height(soops, &te->subtree, h);
+ }
(*h) += UI_UNIT_Y;
te = te->next;
}
@@ -105,7 +108,7 @@ static void outliner_width(SpaceOops *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)
@@ -132,12 +135,27 @@ static void outliner_rna_width(SpaceOops *soops, ListBase *lb, int *w, int start
if (startx + 100 > *w)
*w = startx + 100;
- if (TSELEM_OPEN(tselem, soops))
+ if (TSELEM_OPEN(tselem, soops)) {
outliner_rna_width(soops, &te->subtree, w, startx + UI_UNIT_X);
+ }
te = te->next;
}
}
+/**
+ * The active object is only needed for reference.
+ */
+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)
+ );
+}
+
/* ****************************************************** */
static void restrictbutton_recursive_ebone(bContext *C, EditBone *ebone_parent, int flag, bool set_flag)
@@ -145,7 +163,7 @@ static void restrictbutton_recursive_ebone(bContext *C, EditBone *ebone_parent,
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) {
@@ -183,7 +201,7 @@ static void restrictbutton_r_lay_cb(bContext *C, void *poin, void *UNUSED(poin2)
static void restrictbutton_modifier_cb(bContext *C, void *UNUSED(poin), void *poin2)
{
Object *ob = (Object *)poin2;
-
+
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
}
@@ -248,25 +266,12 @@ static void restrictbutton_gp_layer_flag_cb(bContext *C, void *UNUSED(poin), voi
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
-static void restrictbutton_collection_flag_cb(bContext *C, void *poin, void *UNUSED(poin2))
-{
- ID *id = (ID *)poin;
-
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(id, 0);
-
- if (GS(id->name) == ID_SCE) {
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, id);
- }
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, NULL);
-}
-
static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void *UNUSED(poin2))
{
ID *id = (ID *)poin;
-
+
BLI_assert(id != NULL);
-
+
if (id->flag & LIB_FAKEUSER) {
id_us_plus(id);
}
@@ -275,22 +280,58 @@ static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void
}
}
+static void hidebutton_base_flag_cb(bContext *C, void *poin, void *poin2)
+{
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = poin;
+ Base *base = poin2;
+ bool extend = (CTX_wm_window(C)->eventstate->ctrl == 0);
+
+ /* Undo button toggle, let function do it. */
+ base->flag ^= BASE_HIDDEN;
+
+ BKE_base_set_visible(scene, view_layer, base, extend);
+
+ if (!extend && (base->flag & BASE_VISIBLE)) {
+ /* Auto select solo-ed object. */
+ ED_object_base_select(base, BA_SELECT);
+ view_layer->basact = base;
+ }
+
+ DEG_id_tag_update(&scene->id, DEG_TAG_BASE_FLAGS_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+}
+
+static void hidebutton_layer_collection_flag_cb(bContext *C, void *poin, void *poin2)
+{
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = poin;
+ LayerCollection *lc = poin2;
+ bool extend = (CTX_wm_window(C)->eventstate->ctrl == 0);
+
+ /* Undo button toggle, let function do it. */
+ lc->runtime_flag ^= LAYER_COLLECTION_HAS_VISIBLE_OBJECTS;
+
+ BKE_layer_collection_set_visible(scene, view_layer, lc, extend);
+
+ DEG_id_tag_update(&scene->id, DEG_TAG_BASE_FLAGS_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+}
static void namebutton_cb(bContext *C, void *tsep, char *oldname)
{
+ Main *bmain = CTX_data_main(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(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(G.main, tselem->id->name);
-
+ 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;
@@ -308,10 +349,10 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
Library *lib = (Library *)tselem->id;
char expanded[FILE_MAX];
- BKE_library_filepath_set(lib, lib->name);
+ BKE_library_filepath_set(bmain, lib, lib->name);
BLI_strncpy(expanded, lib->name, sizeof(expanded));
- BLI_path_abs(expanded, G.main->name);
+ 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);
@@ -329,7 +370,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
defgroup_unique_name(te->directdata, (Object *)tselem->id); // id = object
break;
case TSE_NLA_ACTION:
- BLI_libblock_ensure_unique_name(G.main, tselem->id->name);
+ BLI_libblock_ensure_unique_name(bmain, tselem->id->name);
break;
case TSE_EBONE:
{
@@ -341,53 +382,55 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
/* restore bone name */
BLI_strncpy(newname, ebone->name, sizeof(ebone->name));
BLI_strncpy(ebone->name, oldname, sizeof(ebone->name));
- ED_armature_bone_rename(obedit->data, oldname, newname);
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, OBACT(view_layer));
+ 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;
- Object *ob;
char newname[sizeof(bone->name)];
-
+
/* always make current object active */
tree_element_active(C, scene, view_layer, soops, te, OL_SETSEL_NORMAL, true);
- ob = OBACT(view_layer);
-
+
/* restore bone name */
BLI_strncpy(newname, bone->name, sizeof(bone->name));
BLI_strncpy(bone->name, oldname, sizeof(bone->name));
- ED_armature_bone_rename(ob->data, oldname, newname);
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ 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;
- Object *ob;
char newname[sizeof(pchan->name)];
-
+
/* always make current pose-bone active */
tree_element_active(C, scene, view_layer, soops, te, OL_SETSEL_NORMAL, true);
- ob = OBACT(view_layer);
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(ob->data, oldname, newname);
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ 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);
@@ -397,7 +440,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
{
bGPdata *gpd = (bGPdata *)tselem->id; // id = GP Datablock
bGPDlayer *gpl = te->directdata;
-
+
// XXX: name needs translation stuff
BLI_uniquename(&gpd->layers, gpl, "GP Layer", '.',
offsetof(bGPDlayer, info), sizeof(gpl->info));
@@ -405,13 +448,24 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
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_SCENE_COLLECTION:
+ }
case TSE_LAYER_COLLECTION:
{
- SceneCollection *sc = outliner_scene_collection_from_tree_element(te);
- BKE_collection_rename(tselem->id, sc, te->name);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+ BLI_libblock_ensure_unique_name(bmain, tselem->id->name);
+ WM_event_add_notifier(C, NC_ID | NA_RENAME, NULL);
break;
}
}
@@ -420,185 +474,214 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
}
}
-static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops, ListBase *lb)
-{
+static void outliner_draw_restrictbuts(
+ uiBlock *block, Scene *scene, ViewLayer *view_layer, ARegion *ar, SpaceOops *soops, ListBase *lb)
+{
uiBut *bt;
- TreeElement *te;
- TreeStoreElem *tselem;
- Object *ob = NULL;
-#if 0
- PropertyRNA *object_prop_hide, *object_prop_hide_select, *object_prop_hide_render;
+ /* get RNA properties (once for speed) */
+ PropertyRNA *object_prop_hide_viewport, *object_prop_hide_select, *object_prop_hide_render;
+ PropertyRNA *collection_prop_hide_viewport, *collection_prop_hide_select, *collection_prop_hide_render;
- /* get RNA properties (once) */
- object_prop_hide = RNA_struct_type_find_property(&RNA_Object, "hide");
+ object_prop_hide_viewport = RNA_struct_type_find_property(&RNA_Object, "hide_viewport");
object_prop_hide_select = RNA_struct_type_find_property(&RNA_Object, "hide_select");
object_prop_hide_render = RNA_struct_type_find_property(&RNA_Object, "hide_render");
- BLI_assert(object_prop_hide && object_prop_hide_select && object_prop_hide_render);
-#endif
+ collection_prop_hide_select = RNA_struct_type_find_property(&RNA_Collection, "hide_select");
+ collection_prop_hide_viewport = RNA_struct_type_find_property(&RNA_Collection, "hide_viewport");
+ collection_prop_hide_render = RNA_struct_type_find_property(&RNA_Collection, "hide_render");
+ BLI_assert(object_prop_hide_viewport &&
+ object_prop_hide_select &&
+ object_prop_hide_render &&
+ collection_prop_hide_viewport &&
+ collection_prop_hide_select &&
+ collection_prop_hide_render);
- for (te = lb->first; te; te = te->next) {
- tselem = TREESTORE(te);
+ 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 *view_layer = te->directdata;
+ ViewLayer *layer = te->directdata;
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
-
- 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, &view_layer->flag, 0, 0, 0, 0, TIP_("Use view layer for rendering"));
+ 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_block_emboss_set(block, UI_EMBOSS);
+ }
+ else if (tselem->type == 0 && te->idcode == ID_OB) {
+ Object *ob = (Object *)tselem->id;
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+
+ if (base) {
+ bt = uiDefIconButBitS(
+ block, UI_BTYPE_ICON_TOGGLE, BASE_HIDDEN, 0, ICON_HIDE_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_HIDEX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &base->flag, 0, 0, 0, 0,
+ TIP_("Hide object in viewport (Ctrl to isolate)"));
+ UI_but_func_set(bt, hidebutton_base_flag_cb, view_layer, base);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
+
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)ob, &RNA_Object, ob, &ptr);
+
+ bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_VIEW_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y,
+ &ptr, object_prop_hide_viewport, -1, 0, 0, -1, -1,
+ TIP_("Restrict viewport visibility"));
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+
+ bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_SELECT_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, UI_UNIT_Y,
+ &ptr, object_prop_hide_select, -1, 0, 0, -1, -1,
+ TIP_("Restrict viewport selection"));
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+
+ bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_RENDER_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y,
+ &ptr, object_prop_hide_render, -1, 0, 0, -1, -1,
+ TIP_("Restrict render visibility"));
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+
}
else if (tselem->type == TSE_MODIFIER) {
ModifierData *md = (ModifierData *)te->directdata;
- ob = (Object *)tselem->id;
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE_N, eModifierMode_Realtime, 0, ICON_RESTRICT_VIEW_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &(md->mode), 0, 0, 0, 0,
- TIP_("Restrict/Allow visibility in the 3D View"));
+ Object *ob = (Object *)tselem->id;
+
+ bt = uiDefIconButBitI(
+ block, UI_BTYPE_ICON_TOGGLE_N, eModifierMode_Realtime, 0, ICON_RESTRICT_VIEW_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &(md->mode), 0, 0, 0, 0,
+ TIP_("Restrict/Allow visibility in the 3D View"));
UI_but_func_set(bt, restrictbutton_modifier_cb, scene, ob);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
-
- bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE_N, eModifierMode_Render, 0, ICON_RESTRICT_RENDER_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &(md->mode), 0, 0, 0, 0, TIP_("Restrict/Allow renderability"));
+
+ bt = uiDefIconButBitI(
+ block, UI_BTYPE_ICON_TOGGLE_N, eModifierMode_Render, 0, ICON_RESTRICT_RENDER_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &(md->mode), 0, 0, 0, 0, TIP_("Restrict/Allow renderability"));
UI_but_func_set(bt, restrictbutton_modifier_cb, scene, ob);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
-
- UI_block_emboss_set(block, UI_EMBOSS);
}
else if (tselem->type == TSE_POSE_CHANNEL) {
bPoseChannel *pchan = (bPoseChannel *)te->directdata;
Bone *bone = pchan->bone;
- ob = (Object *)tselem->id;
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE, BONE_HIDDEN_P, 0, ICON_RESTRICT_VIEW_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"));
+ 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);
-
- 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"));
+
+ 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_block_emboss_set(block, UI_EMBOSS);
}
else if (tselem->type == TSE_EBONE) {
EditBone *ebone = (EditBone *)te->directdata;
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- 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"));
+
+ 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);
-
- 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"));
+
+ 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_block_emboss_set(block, UI_EMBOSS);
}
else if (tselem->type == TSE_GP_LAYER) {
bGPDlayer *gpl = (bGPDlayer *)te->directdata;
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
-
- bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE, GP_LAYER_HIDE, 0, ICON_RESTRICT_VIEW_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"));
+
+ 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, NULL, gpl);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
-
- 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"));
+
+ 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, NULL, gpl);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
-
+
/* TODO: visibility in renders */
-
- UI_block_emboss_set(block, UI_EMBOSS);
}
- else if (tselem->type == TSE_LAYER_COLLECTION) {
- LayerCollection *collection = te->directdata;
+ 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);
- const bool is_enabled = (collection->flag & COLLECTION_DISABLED) == 0;
+ if ((!lc || !(lc->flag & LAYER_COLLECTION_EXCLUDE)) &&
+ !(collection->flag & COLLECTION_IS_MASTER))
+ {
+ if (lc && (lc->runtime_flag & LAYER_COLLECTION_HAS_ENABLED_OBJECTS)) {
+ bt = uiDefIconButBitS(
+ block, UI_BTYPE_ICON_TOGGLE_N, LAYER_COLLECTION_HAS_VISIBLE_OBJECTS, 0, ICON_HIDE_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_HIDEX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &lc->runtime_flag, 0, 0, 0, 0,
+ TIP_("Hide collection in viewport (Ctrl to isolate)"));
+ UI_but_func_set(bt, hidebutton_layer_collection_flag_cb, view_layer, lc);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ PointerRNA collection_ptr;
+ RNA_id_pointer_create(&collection->id, &collection_ptr);
- if (collection->scene_collection->type == COLLECTION_TYPE_NONE) {
- bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE_N, COLLECTION_SELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &collection->flag, 0, 0, 0, 0,
- TIP_("Restrict/Allow 3D View selection of objects in the collection"));
- UI_but_func_set(bt, restrictbutton_collection_flag_cb, scene, collection);
+ bt = uiDefIconButR_prop(
+ block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_VIEW_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &collection_ptr, collection_prop_hide_viewport, -1, 0, 0, 0, 0, NULL);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- }
- else if ((soops->outlinevis == SO_GROUPS) &&
- (collection->scene_collection->type == COLLECTION_TYPE_GROUP_INTERNAL))
- {
- bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE_N, COLLECTION_VIEWPORT, 0, ICON_RESTRICT_VIEW_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &collection->flag, 0, 0, 0, 0,
- TIP_("Restrict/Allow 3D View selection of objects in the collection"));
- UI_but_func_set(bt, restrictbutton_collection_flag_cb, tselem->id, collection);
+
+ bt = uiDefIconButR_prop(
+ block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_RENDER_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &collection_ptr, collection_prop_hide_render, -1, 0, 0, 0, 0, NULL);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE_N, COLLECTION_RENDER, 0, ICON_RESTRICT_RENDER_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &collection->flag, 0, 0, 0, 0,
- TIP_("Restrict/Allow 3D View selection of objects in the collection"));
- UI_but_func_set(bt, restrictbutton_collection_flag_cb, tselem->id, collection);
+ bt = uiDefIconButR_prop(
+ block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_SELECT_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &collection_ptr, collection_prop_hide_select, -1, 0, 0, 0, 0, NULL);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
}
-
- bt = uiDefIconButBitS(block, UI_BTYPE_BUT_TOGGLE, COLLECTION_DISABLED, 0,
- is_enabled ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &collection->flag, 0, 0, 0, 0,
- TIP_("Enable/Disable collection"));
- UI_but_func_set(bt, restrictbutton_collection_flag_cb, tselem->id, collection);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
-
- UI_block_emboss_set(block, UI_EMBOSS);
}
}
-
- if (TSELEM_OPEN(tselem, soops)) outliner_draw_restrictbuts(block, scene, ar, soops, &te->subtree);
+
+ 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, SpaceOops *soops, ListBase *lb)
{
- uiBut *bt;
- TreeElement *te;
- TreeStoreElem *tselem;
- for (te = lb->first; te; te = te->next) {
- tselem = TREESTORE(te);
+ 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;
@@ -608,8 +691,6 @@ static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOops *soops
if (ID_IS_LINKED(id))
but_flag |= UI_BUT_DISABLED;
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
-
if (id->flag & LIB_FAKEUSER) {
icon = ICON_FILE_TICK;
tip = TIP_("Data-block will be retained using a fake user");
@@ -618,34 +699,37 @@ static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOops *soops
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);
+ 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"));
+ 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"));
+
+
+ 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);
-
- UI_block_emboss_set(block, UI_EMBOSS);
}
}
-
- if (TSELEM_OPEN(tselem, soops)) outliner_draw_userbuts(block, ar, soops, &te->subtree);
+
+ if (TSELEM_OPEN(tselem, soops)) {
+ outliner_draw_userbuts(block, ar, soops, &te->subtree);
+ }
}
}
@@ -656,7 +740,7 @@ static void outliner_draw_rnacols(ARegion *ar, int sizex)
float miny = v2d->cur.ymin;
if (miny < v2d->tot.ymin) miny = v2d->tot.ymin;
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -677,13 +761,11 @@ static void outliner_draw_rnacols(ARegion *ar, int sizex)
static void outliner_draw_rnabuts(uiBlock *block, ARegion *ar, SpaceOops *soops, int sizex, ListBase *lb)
{
- TreeElement *te;
- TreeStoreElem *tselem;
PointerRNA *ptr;
PropertyRNA *prop;
- for (te = lb->first; te; te = te->next) {
- tselem = TREESTORE(te);
+ 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;
@@ -691,33 +773,37 @@ static void outliner_draw_rnabuts(uiBlock *block, ARegion *ar, SpaceOops *soops,
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);
+ 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);
+ 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);
+ 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);
+
+ 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);
- }
- UI_block_emboss_set(block, UI_EMBOSS);
+ 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)
@@ -741,8 +827,9 @@ static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, Tre
spx = te->xs + 1.8f * UI_UNIT_X;
dx = ar->v2d.cur.xmax - (spx + 3.2f * UI_UNIT_X);
- 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, "");
+ 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 */
@@ -769,15 +856,16 @@ static void tselem_draw_icon_uibut(struct DrawIconArg *arg, int icon)
{
/* restrict column clip... it has been coded by simply overdrawing, doesnt work for buttons */
if (arg->x >= arg->xmax) {
- glEnable(GL_BLEND);
+ GPU_blend(true);
UI_icon_draw_alpha(arg->x, arg->y, icon, arg->alpha);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
else {
- uiBut *but = uiDefIconBut(arg->block, UI_BTYPE_LABEL, 0, icon, arg->xb, arg->yb, UI_UNIT_X, UI_UNIT_Y, NULL,
- 0.0, 0.0, 1.0, arg->alpha,
- (arg->id && ID_IS_LINKED(arg->id)) ? arg->id->lib->name : "");
-
+ uiBut *but = uiDefIconBut(
+ arg->block, UI_BTYPE_LABEL, 0, icon, arg->xb, arg->yb, UI_UNIT_X, UI_UNIT_Y, NULL,
+ 0.0, 0.0, 1.0, arg->alpha,
+ (arg->id && ID_IS_LINKED(arg->id)) ? arg->id->lib->name : "");
+
if (arg->id)
UI_but_drag_set_id(but, arg->id);
}
@@ -801,28 +889,29 @@ static void UNUSED_FUNCTION(tselem_draw_gp_icon_uibut)(struct DrawIconArg *arg,
RNA_pointer_create(id, &RNA_GPencilLayer, gpl, &ptr);
UI_block_align_begin(arg->block);
-
+
UI_block_emboss_set(arg->block, is_stroke_visible ? UI_EMBOSS : UI_EMBOSS_NONE);
uiDefButR(arg->block, UI_BTYPE_COLOR, 1, "", arg->xb, arg->yb, w, h,
&ptr, "color", -1,
0, 0, 0, 0, NULL);
-
+
UI_block_emboss_set(arg->block, is_fill_visible ? UI_EMBOSS : UI_EMBOSS_NONE);
uiDefButR(arg->block, UI_BTYPE_COLOR, 1, "", arg->xb + w, arg->yb, w, h,
&ptr, "fill_color", -1,
0, 0, 0, 0, NULL);
-
+
UI_block_emboss_set(arg->block, UI_EMBOSS_NONE);
UI_block_align_end(arg->block);
}
}
-static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeStoreElem *tselem, TreeElement *te,
- float alpha)
+static void tselem_draw_icon(
+ uiBlock *block, int xmax, float x, float y, TreeStoreElem *tselem, TreeElement *te,
+ float alpha, const bool is_clickable)
{
struct DrawIconArg arg;
float aspect;
-
+
/* make function calls a bit compacter */
arg.block = block;
arg.id = tselem->id;
@@ -839,6 +928,7 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
arg.y = y;
#define ICON_DRAW(_icon) UI_icon_draw_alpha(x, y, _icon, alpha)
+#define ICON_CLICK_DRAW(_icon) if (!is_clickable) ICON_DRAW(_icon); else tselem_draw_icon_uibut(&arg, _icon)
if (tselem->type) {
switch (tselem->type) {
@@ -1090,8 +1180,9 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
}
break;
case TSE_LAYER_COLLECTION:
- case TSE_SCENE_COLLECTION:
- ICON_DRAW(ICON_COLLAPSEMENU);
+ case TSE_SCENE_COLLECTION_BASE:
+ case TSE_VIEW_COLLECTION_BASE:
+ ICON_DRAW(ICON_GROUP);
break;
/* Removed the icons from outliner. Need a better structure with Layers, Palettes and Colors */
#if 0
@@ -1109,29 +1200,35 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
Object *ob = (Object *)tselem->id;
switch (ob->type) {
case OB_LAMP:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LAMP); break;
+ ICON_CLICK_DRAW(ICON_OUTLINER_OB_LAMP); break;
case OB_MESH:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_MESH); break;
+ ICON_CLICK_DRAW(ICON_OUTLINER_OB_MESH); break;
case OB_CAMERA:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CAMERA); break;
+ ICON_CLICK_DRAW(ICON_OUTLINER_OB_CAMERA); break;
case OB_CURVE:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CURVE); break;
+ ICON_CLICK_DRAW(ICON_OUTLINER_OB_CURVE); break;
case OB_MBALL:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_META); break;
+ ICON_CLICK_DRAW(ICON_OUTLINER_OB_META); break;
case OB_LATTICE:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LATTICE); break;
+ ICON_CLICK_DRAW(ICON_OUTLINER_OB_LATTICE); break;
case OB_ARMATURE:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_ARMATURE); break;
+ ICON_CLICK_DRAW(ICON_OUTLINER_OB_ARMATURE); break;
case OB_FONT:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_FONT); break;
+ ICON_CLICK_DRAW(ICON_OUTLINER_OB_FONT); break;
case OB_SURF:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SURFACE); break;
+ ICON_CLICK_DRAW(ICON_OUTLINER_OB_SURFACE); break;
case OB_SPEAKER:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SPEAKER); break;
+ ICON_CLICK_DRAW(ICON_OUTLINER_OB_SPEAKER); break;
case OB_LIGHTPROBE:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LIGHTPROBE); break;
+ ICON_CLICK_DRAW(ICON_OUTLINER_OB_LIGHTPROBE); break;
case OB_EMPTY:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_EMPTY); break;
+ if (ob->dup_group) {
+ ICON_CLICK_DRAW(ICON_OUTLINER_OB_GROUP_INSTANCE);
+ }
+ else {
+ ICON_CLICK_DRAW(ICON_OUTLINER_OB_EMPTY);
+ }
+ break;
}
}
else {
@@ -1223,6 +1320,11 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
}
break;
}
+ case ID_BR:
+ tselem_draw_icon_uibut(&arg, ICON_BRUSH_DATA); break;
+ case ID_SCR:
+ case ID_WS:
+ tselem_draw_icon_uibut(&arg, ICON_SPLITSCREEN); break;
default:
break;
}
@@ -1232,30 +1334,152 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
#undef ICON_DRAW
}
+/**
+ * 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 eOLDrawState active,
+ const int num_elements)
+{
+ float color[4] = {0.4f, 0.4f, 0.4f, 0.9f};
+ copy_v3_fl(color, 0.2f);
+ if (active != OL_DRAWSEL_NONE) {
+ copy_v3_fl(color, 0.65f);
+ color[3] = 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)
+{
+ 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.4f};
+
+ 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.5f * 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, active, num_elements);
+ }
+ (*offsx) += UI_UNIT_X;
+}
+
+/**
+ * Return the index to use based on the TreeElement ID and object type
+ *
+ * We use a continuum of indeces until we get to the object datablocks
+ * and we then make room for the object types.
+ */
+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;
+ }
+}
+
static void outliner_draw_iconrow(
- bContext *C, uiBlock *block, Scene *scene, ViewLayer *view_layer, Object *obedit, SpaceOops *soops,
+ bContext *C, uiBlock *block, const uiFontStyle *fstyle, Scene *scene, ViewLayer *view_layer, SpaceOops *soops,
ListBase *lb, int level, int xmax, int *offsx, int ys, float alpha_fac)
{
- TreeElement *te;
- TreeStoreElem *tselem;
eOLDrawState active;
+ const Object *obact = OBACT(view_layer);
+
+ struct {
+ 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];
+ } data = {
+ .active = {0},
+ .num_elements = {0},
+ .tree_element = {NULL},
+ };
- for (te = lb->first; te; te = te->next) {
+ for (TreeElement *te = lb->first; te; te = te->next) {
/* exit drawing early */
if ((*offsx) - UI_UNIT_X > xmax)
break;
- tselem = TREESTORE(te);
-
+ 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 (obedit && obedit->data == tselem->id) {
+ else if (is_object_data_in_editmode(tselem->id, obact)) {
active = OL_DRAWSEL_NORMAL;
}
else {
@@ -1266,40 +1490,48 @@ static void outliner_draw_iconrow(
active = tree_element_type_active(C, scene, view_layer, soops, te, tselem, OL_SETSEL_NONE, false);
}
- if (active != OL_DRAWSEL_NONE) {
- float ufac = UI_UNIT_X / 20.0f;
- float color[4] = {1.0f, 1.0f, 1.0f, 0.4f};
-
- 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);
- glEnable(GL_BLEND); /* roundbox disables */
+ if (!ELEM(tselem->type, 0, TSE_LAYER_COLLECTION)) {
+ 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);
+ data.num_elements[index]++;
+ if ((data.tree_element[index] == NULL) ||
+ (active > data.active[index]))
+ {
+ data.tree_element[index] = te;
+ }
+ data.active[index] = MAX2(active, data.active[index]);
}
-
- tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.5f * alpha_fac);
- te->xs = *offsx;
- te->ys = ys;
- te->xend = (short)*offsx + UI_UNIT_X;
- te->flag |= TE_ICONROW; // for click
-
- (*offsx) += UI_UNIT_X;
}
-
+
/* this tree element always has same amount of branches, so don't draw */
- if (tselem->type != TSE_R_LAYER)
+ if (tselem->type != TSE_R_LAYER) {
outliner_draw_iconrow(
- C, block, scene, view_layer, obedit, soops,
+ C, block, fstyle, scene, view_layer, soops,
&te->subtree, level + 1, xmax, offsx, ys, alpha_fac);
+ }
+ }
+
+ 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 (data.num_elements[index] != 0) {
+ outliner_draw_iconrow_doit(block,
+ data.tree_element[index],
+ fstyle,
+ xmax, offsx, ys, alpha_fac,
+ data.active[index],
+ data.num_elements[index]);
+ }
+ }
}
-
}
/* closed tree element */
@@ -1321,7 +1553,7 @@ static void outliner_set_coord_tree_element(TreeElement *te, int startx, int sta
static void outliner_draw_tree_element(
- bContext *C, uiBlock *block, const uiFontStyle *fstyle, Scene *scene, ViewLayer *view_layer, Object *obedit,
+ bContext *C, uiBlock *block, const uiFontStyle *fstyle, Scene *scene, ViewLayer *view_layer,
ARegion *ar, SpaceOops *soops, TreeElement *te, bool draw_grayed_out,
int startx, int *starty, TreeElement **te_edit, TreeElement **te_floating)
{
@@ -1333,7 +1565,7 @@ static void outliner_draw_tree_element(
tselem = TREESTORE(te);
if (*starty + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && *starty <= ar->v2d.cur.ymax) {
- const float alpha_fac = draw_grayed_out ? 0.5f : 1.0f;
+ 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;
@@ -1347,11 +1579,12 @@ static void outliner_draw_tree_element(
/* 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;
-
- glEnable(GL_BLEND);
+
+ 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);
@@ -1363,18 +1596,18 @@ static void outliner_draw_tree_element(
Base *base = (Base *)te->directdata;
const bool is_selected = (base != NULL) && ((base->flag & BASE_SELECTED) != 0);
- if (ob == OBACT(view_layer) || is_selected) {
+ if (ob == obact || is_selected) {
char 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(view_layer)) {
+ if (ob == obact) {
if (is_selected) {
UI_GetThemeColorType4ubv(TH_ACTIVE, SPACE_VIEW3D, col);
col[3] = alpha;
}
-
+
active = OL_DRAWSEL_NORMAL;
}
else if (is_selected) {
@@ -1383,9 +1616,8 @@ static void outliner_draw_tree_element(
}
rgba_float_args_set(color, (float)col[0] / 255, (float)col[1] / 255, (float)col[2] / 255, alpha);
}
-
}
- else if (obedit && obedit->data == tselem->id) {
+ 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;
}
@@ -1400,7 +1632,7 @@ static void outliner_draw_tree_element(
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);
@@ -1411,59 +1643,67 @@ static void outliner_draw_tree_element(
(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);
- glEnable(GL_BLEND); /* roundbox disables it */
-
+ GPU_blend(true); /* roundbox disables it */
+
te->flag |= TE_ACTIVE; // for lookup in display hierarchies
}
-
- if ((soops->outlinevis == SO_COLLECTIONS) && (tselem->type == TSE_R_LAYER)) {
- /* View layer in collections can't expand/collapse. */
+
+ 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);
+ 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))) {
- tselem_draw_icon(block, xmax, (float)startx + offsx, (float)*starty, tselem, te, alpha_fac);
+
+ 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 + 2 * ufac;
}
else
offsx += 2 * ufac;
-
- if (tselem->type == 0 && ID_IS_LINKED(tselem->id)) {
+
+ 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);
+ 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);
+ 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);
+ UI_icon_draw_alpha(
+ (float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_DIRECT,
+ alpha_fac);
}
offsx += UI_UNIT_X + 2 * ufac;
}
- else if (tselem->type == 0 && 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);
+ 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 + 2 * ufac;
}
- glDisable(GL_BLEND);
-
+ GPU_blend(false);
+
/* name */
if ((tselem->flag & TSE_TEXTBUT) == 0) {
unsigned char text_col[4];
@@ -1482,9 +1722,9 @@ static void outliner_draw_tree_element(
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) {
@@ -1495,7 +1735,7 @@ static void outliner_draw_tree_element(
else if (tselem->type != TSE_R_LAYER) {
int tempx = startx + offsx;
- glEnable(GL_BLEND);
+ GPU_blend(true);
/* divider */
{
@@ -1516,10 +1756,10 @@ static void outliner_draw_tree_element(
}
outliner_draw_iconrow(
- C, block, scene, view_layer, obedit, soops, &te->subtree, 0, xmax, &tempx,
+ C, block, fstyle, scene, view_layer, soops, &te->subtree, 0, xmax, &tempx,
*starty, alpha_fac);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
}
}
@@ -1537,7 +1777,7 @@ static void outliner_draw_tree_element(
* childs of a grayed out parent (pass on draw_grayed_out to childs) */
bool draw_childs_grayed_out = draw_grayed_out || (ten->drag_data != NULL);
outliner_draw_tree_element(
- C, block, fstyle, scene, view_layer, obedit,
+ C, block, fstyle, scene, view_layer,
ar, soops, ten, draw_childs_grayed_out,
startx + UI_UNIT_X, starty, te_edit, te_floating);
}
@@ -1546,7 +1786,7 @@ static void outliner_draw_tree_element(
for (TreeElement *ten = te->subtree.first; ten; ten = ten->next) {
outliner_set_coord_tree_element(ten, startx, *starty);
}
-
+
*starty -= UI_UNIT_Y;
}
}
@@ -1569,14 +1809,14 @@ static void outliner_draw_tree_element_floating(
UI_GetThemeColorShade4fv(TH_BACK, -40, col);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- glEnable(GL_BLEND);
+ GPU_blend(true);
if (ELEM(te_floating->drag_data->insert_type, TE_INSERT_BEFORE, TE_INSERT_AFTER)) {
if (te_floating->drag_data->insert_type == TE_INSERT_BEFORE) {
coord_y += UI_UNIT_Y;
}
immUniformColor4fv(col);
- glLineWidth(line_width);
+ GPU_line_width(line_width);
immBegin(GWN_PRIM_LINE_STRIP, 2);
immVertex2f(pos, coord_x, coord_y);
@@ -1595,16 +1835,16 @@ static void outliner_draw_tree_element_floating(
immEnd();
}
- glDisable(GL_BLEND);
+ GPU_blend(false);
immUnbindProgram();
}
-static void outliner_draw_hierarchy_lines_recursive(unsigned pos, SpaceOops *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, SpaceOops *soops, ListBase *lb, int startx,
+ const unsigned char col[4], bool draw_grayed_out,
+ int *starty)
{
TreeElement *te, *te_vertical_line_last = NULL;
- TreeStoreElem *tselem;
int y1, y2;
if (BLI_listbase_is_empty(lb)) {
@@ -1617,7 +1857,7 @@ static void outliner_draw_hierarchy_lines_recursive(unsigned pos, SpaceOops *soo
y1 = y2 = *starty;
for (te = lb->first; te; te = te->next) {
bool draw_childs_grayed_out = draw_grayed_out || (te->drag_data != NULL);
- tselem = TREESTORE(te);
+ TreeStoreElem *tselem = TREESTORE(te);
if (draw_childs_grayed_out) {
immUniformColor3ubvAlpha(col, grayed_alpha);
@@ -1638,10 +1878,11 @@ static void outliner_draw_hierarchy_lines_recursive(unsigned pos, SpaceOops *soo
}
*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);
+ outliner_draw_hierarchy_lines_recursive(
+ pos, soops, &te->subtree, startx + UI_UNIT_X,
+ col, draw_childs_grayed_out, starty);
}
if (draw_grayed_out) {
@@ -1668,23 +1909,20 @@ static void outliner_draw_hierarchy_lines(SpaceOops *soops, ListBase *lb, int st
UI_GetThemeColorBlend3ubv(TH_BACK, TH_TEXT, 0.4f, col);
col[3] = 255;
- glEnable(GL_BLEND);
+ GPU_blend(true);
outliner_draw_hierarchy_lines_recursive(pos, soops, lb, startx, col, false, starty);
- glDisable(GL_BLEND);
+ GPU_blend(false);
immUnbindProgram();
}
static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *lb, int *starty)
{
- TreeElement *te;
- TreeStoreElem *tselem;
+ for (TreeElement *te = lb->first; te; te = te->next) {
+ TreeStoreElem *tselem = TREESTORE(te);
- for (te = lb->first; te; te = te->next) {
- tselem = TREESTORE(te);
-
/* selection status */
- if (TSELEM_OPEN(tselem, soops))
+ if (TSELEM_OPEN(tselem, soops)) {
if (tselem->type == TSE_RNA_STRUCT) {
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
@@ -1693,6 +1931,7 @@ static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *
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)) {
@@ -1719,10 +1958,10 @@ static void outliner_draw_highlights_recursive(
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_DATABLOCKS &&
- (soops->filter & SO_FILTER_SEARCH) &&
- soops->search_string[0] != 0);
+ 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);
@@ -1767,18 +2006,19 @@ static void outliner_draw_highlights(ARegion *ar, SpaceOops *soops, int startx,
UI_GetThemeColor4fv(TH_MATCH, col_searchmatch);
col_searchmatch[3] = 0.5f;
- glEnable(GL_BLEND);
+ GPU_blend(true);
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_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);
+ outliner_draw_highlights_recursive(
+ pos, ar, soops, &soops->tree, col_selection, col_highlight, col_searchmatch,
+ startx, starty);
immUnbindProgram();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
static void outliner_draw_tree(
- bContext *C, uiBlock *block, Scene *scene, ViewLayer *view_layer, Object *obedit,
+ bContext *C, uiBlock *block, Scene *scene, ViewLayer *view_layer,
ARegion *ar, SpaceOops *soops, const bool has_restrict_icons,
TreeElement **te_edit)
{
@@ -1786,9 +2026,9 @@ static void outliner_draw_tree(
TreeElement *te_floating = NULL;
int starty, startx;
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // only once
+ 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_DATABLOCKS) {
+ 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);
@@ -1800,17 +2040,17 @@ static void outliner_draw_tree(
outliner_draw_highlights(ar, soops, startx, &starty);
/* set scissor so tree elements or lines can't overlap restriction icons */
- GLfloat scissor[4] = {0};
+ 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);
- glGetFloatv(GL_SCISSOR_BOX, scissor);
- glScissor(0, 0, mask_x, ar->winy);
+ GPU_scissor_getf(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);
@@ -1820,7 +2060,7 @@ static void outliner_draw_tree(
startx = 0;
for (TreeElement *te = soops->tree.first; te; te = te->next) {
outliner_draw_tree_element(
- C, block, fstyle, scene, view_layer, obedit,
+ C, block, fstyle, scene, view_layer,
ar, soops, te, te->drag_data != NULL,
startx, &starty, te_edit, &te_floating);
}
@@ -1830,7 +2070,7 @@ static void outliner_draw_tree(
if (has_restrict_icons) {
/* reset scissor */
- glScissor(UNPACK4(scissor));
+ GPU_scissor(UNPACK4(scissor));
}
}
@@ -1838,7 +2078,7 @@ static void outliner_draw_tree(
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;
@@ -1872,12 +2112,15 @@ static void outliner_back(ARegion *ar)
static void outliner_draw_restrictcols(ARegion *ar)
{
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColorShadeAlpha(TH_BACK, -15, -200);
- immBegin(GWN_PRIM_LINES, 6);
+ immBegin(GWN_PRIM_LINES, 8);
+
+ immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_HIDEX), (int)ar->v2d.cur.ymax);
+ immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_HIDEX), (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);
@@ -1897,10 +2140,9 @@ static void outliner_draw_restrictcols(ARegion *ar)
void draw_outliner(const bContext *C)
{
- Main *mainvar = CTX_data_main(C);
+ Main *mainvar = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
ARegion *ar = CTX_wm_region(C);
View2D *v2d = &ar->v2d;
SpaceOops *soops = CTX_wm_space_outliner(C);
@@ -1910,11 +2152,11 @@ void draw_outliner(const bContext *C)
bool has_restrict_icons;
outliner_build_tree(mainvar, scene, view_layer, soops, ar); // always
-
+
/* get extents of data */
outliner_height(soops, &soops->tree, &sizey);
- if (soops->outlinevis == SO_DATABLOCKS) {
+ 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...
@@ -1922,11 +2164,11 @@ void draw_outliner(const bContext *C)
*
* (*) 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;
@@ -1936,7 +2178,7 @@ void draw_outliner(const bContext *C)
//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) {
@@ -1945,7 +2187,7 @@ void draw_outliner(const bContext *C)
has_restrict_icons = !(soops->flag & SO_HIDE_RESTRICTCOLS);
}
-
+
/* adds vertical offset */
sizey += OL_Y_OFFSET;
@@ -1961,13 +2203,19 @@ void draw_outliner(const bContext *C)
outliner_back(ar);
block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
outliner_draw_tree(
- (bContext *)C, block, scene, view_layer, obedit,
+ (bContext *)C, block, scene, view_layer,
ar, soops, has_restrict_icons, &te_edit);
- if (soops->outlinevis == SO_DATABLOCKS) {
+ /* 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 */
@@ -1977,9 +2225,12 @@ void draw_outliner(const bContext *C)
else if (has_restrict_icons) {
/* draw restriction columns */
outliner_draw_restrictcols(ar);
- outliner_draw_restrictbuts(block, scene, ar, soops, &soops->tree);
+
+ 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);
@@ -1987,7 +2238,4 @@ void draw_outliner(const bContext *C)
UI_block_end(C, block);
UI_block_draw(C, block);
-
- /* clear flag that allows quick redraws */
- soops->storeflag &= ~SO_TREESTORE_REDRAW;
-}
+}
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 9207ee5ae15..990d50ae42a 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -50,6 +50,7 @@
#include "BLT_translation.h"
#include "BKE_animsys.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_idcode.h"
#include "BKE_layer.h"
@@ -61,8 +62,8 @@
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_material.h"
-#include "BKE_group.h"
+#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "../blenloader/BLO_readfile.h"
@@ -98,19 +99,19 @@ static void outliner_open_reveal(SpaceOops *soops, ListBase *lb, TreeElement *te
{
TreeElement *te;
TreeStoreElem *tselem;
-
+
for (te = lb->first; te; te = te->next) {
/* check if this tree-element was the one we're seeking */
if (te == teFind) {
*found = 1;
return;
}
-
+
/* try to see if sub-tree contains it then */
outliner_open_reveal(soops, &te->subtree, teFind, found);
if (*found) {
tselem = TREESTORE(te);
- if (tselem->flag & TSE_CLOSED)
+ if (tselem->flag & TSE_CLOSED)
tselem->flag &= ~TSE_CLOSED;
return;
}
@@ -172,8 +173,7 @@ static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const
}
if (changed) {
- soops->storeflag |= SO_TREESTORE_REDRAW; /* only needs to redraw, no rebuild */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw_no_rebuild(ar);
}
return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
@@ -194,10 +194,10 @@ void OUTLINER_OT_highlight_update(wmOperatorType *ot)
static int do_outliner_item_openclose(bContext *C, SpaceOops *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);
-
+
/* all below close/open? */
if (all) {
tselem->flag &= ~TSE_CLOSED;
@@ -207,16 +207,16 @@ static int do_outliner_item_openclose(bContext *C, SpaceOops *soops, TreeElement
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))
+ if (do_outliner_item_openclose(C, soops, te, all, mval))
return 1;
}
return 0;
-
+
}
/* event can enterkey, then it opens/closes */
@@ -227,16 +227,16 @@ static int outliner_item_openclose(bContext *C, wmOperator *op, const wmEvent *e
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]);
-
+
for (te = soops->tree.first; te; te = te->next) {
- if (do_outliner_item_openclose(C, soops, te, all, fmval))
+ if (do_outliner_item_openclose(C, soops, te, all, fmval))
break;
}
ED_region_tag_redraw(ar);
-
+
return OPERATOR_FINISHED;
}
@@ -245,17 +245,66 @@ void OUTLINER_OT_item_openclose(wmOperatorType *ot)
ot->name = "Open/Close Item";
ot->idname = "OUTLINER_OT_item_openclose";
ot->description = "Toggle whether item under cursor is enabled or closed";
-
+
ot->invoke = outliner_item_openclose;
-
+
ot->poll = ED_operator_outliner_active;
-
+
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)
+{
+ 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 == 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);
+}
+
+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);
+}
+
+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);
+}
+
+/** \} */
+
/* Rename --------------------------------------------------- */
-static void do_item_rename(const Scene *scene, ARegion *ar, TreeElement *te, TreeStoreElem *tselem,
+static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem,
ReportList *reports)
{
bool add_textbut = false;
@@ -265,19 +314,18 @@ static void do_item_rename(const Scene *scene, ARegion *ar, TreeElement *te, Tre
/* 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_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 (ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
- SceneCollection *master = BKE_collection_master(&scene->id);
+ else if (outliner_is_collection_tree_element(te)) {
+ Collection *collection = outliner_collection_from_tree_element(te);
- if ((tselem->type == TSE_SCENE_COLLECTION && te->directdata == master) ||
- (((LayerCollection *)te->directdata)->scene_collection == master))
- {
+ if (collection->flag & COLLECTION_IS_MASTER) {
BKE_report(reports, RPT_WARNING, "Cannot edit name of master collection");
}
else {
@@ -301,29 +349,29 @@ static void do_item_rename(const Scene *scene, ARegion *ar, TreeElement *te, Tre
}
void item_rename_cb(
- bContext *C, ReportList *reports, Scene *scene, TreeElement *te,
+ 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(scene, ar, te, tselem, reports);
+ do_item_rename(ar, te, tselem, reports);
}
-static int do_outliner_item_rename(const Scene *scene, ReportList *reports, ARegion *ar, TreeElement *te,
+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);
-
+
/* click on name */
if (mval[0] > te->xs + UI_UNIT_X * 2 && mval[0] < te->xend) {
- do_item_rename(scene, ar, te, tselem, reports);
+ 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(scene, reports, ar, te, mval)) return 1;
+ if (do_outliner_item_rename(reports, ar, te, mval)) return 1;
}
return 0;
}
@@ -335,16 +383,16 @@ static int outliner_item_rename(bContext *C, wmOperator *op, const wmEvent *even
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]);
-
+
for (te = soops->tree.first; te; te = te->next) {
- if (do_outliner_item_rename(CTX_data_scene(C), op->reports, ar, te, fmval)) {
+ if (do_outliner_item_rename(op->reports, ar, te, fmval)) {
changed = true;
break;
}
}
-
+
return changed ? OPERATOR_FINISHED : OPERATOR_PASS_THROUGH;
}
@@ -354,9 +402,9 @@ void OUTLINER_OT_item_rename(wmOperatorType *ot)
ot->name = "Rename Item";
ot->idname = "OUTLINER_OT_item_rename";
ot->description = "Rename item under cursor";
-
+
ot->invoke = outliner_item_rename;
-
+
ot->poll = ED_operator_outliner_active;
}
@@ -494,7 +542,7 @@ static int outliner_id_remap_exec(bContext *C, wmOperator *op)
DEG_relations_tag_update(bmain);
/* free gpu materials, some materials depend on existing objects, such as lamps so freeing correctly refreshes */
- GPU_materials_free();
+ GPU_materials_free(bmain);
WM_event_add_notifier(C, NC_WINDOW, NULL);
@@ -777,9 +825,9 @@ static int outliner_count_levels(ListBase *lb, const int curlevel)
{
TreeElement *te;
int level = curlevel, lev;
-
+
for (te = lb->first; te; te = te->next) {
-
+
lev = outliner_count_levels(&te->subtree, curlevel + 1);
if (lev > level) level = lev;
}
@@ -791,11 +839,11 @@ int outliner_has_one_flag(ListBase *lb, short flag, const int curlevel)
TreeElement *te;
TreeStoreElem *tselem;
int level;
-
+
for (te = lb->first; te; te = te->next) {
tselem = TREESTORE(te);
if (tselem->flag & flag) return curlevel;
-
+
level = outliner_has_one_flag(&te->subtree, flag, curlevel + 1);
if (level) return level;
}
@@ -852,7 +900,7 @@ int common_restrict_check(bContext *C, Object *ob)
ob->restrictflag &= ~OB_RESTRICT_SELECT;
return 0;
}
-
+
return 1;
}
@@ -865,14 +913,14 @@ static int outliner_toggle_expanded_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceOops *soops = CTX_wm_space_outliner(C);
ARegion *ar = CTX_wm_region(C);
-
+
if (outliner_has_one_flag(&soops->tree, TSE_CLOSED, 1))
outliner_set_flag(&soops->tree, TSE_CLOSED, 0);
- else
+ else
outliner_set_flag(&soops->tree, TSE_CLOSED, 1);
-
+
ED_region_tag_redraw(ar);
-
+
return OPERATOR_FINISHED;
}
@@ -882,11 +930,11 @@ void OUTLINER_OT_expanded_toggle(wmOperatorType *ot)
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;
-
+
/* no undo or registry, UI option */
}
@@ -897,17 +945,16 @@ static int outliner_toggle_selected_exec(bContext *C, wmOperator *UNUSED(op))
SpaceOops *soops = CTX_wm_space_outliner(C);
ARegion *ar = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
-
+
if (outliner_has_one_flag(&soops->tree, TSE_SELECTED, 1))
outliner_set_flag(&soops->tree, TSE_SELECTED, 0);
- else
+ else
outliner_set_flag(&soops->tree, TSE_SELECTED, 1);
-
- soops->storeflag |= SO_TREESTORE_REDRAW;
-
+
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- ED_region_tag_redraw(ar);
-
+ ED_region_tag_redraw_no_rebuild(ar);
+
return OPERATOR_FINISHED;
}
@@ -917,11 +964,11 @@ void OUTLINER_OT_selected_toggle(wmOperatorType *ot)
ot->name = "Toggle Selected";
ot->idname = "OUTLINER_OT_selected_toggle";
ot->description = "Toggle the Outliner selection of items";
-
+
/* callbacks */
ot->exec = outliner_toggle_selected_exec;
ot->poll = ED_operator_outliner_active;
-
+
/* no undo or registry, UI option */
}
@@ -980,7 +1027,7 @@ static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op))
ViewLayer *view_layer = CTX_data_view_layer(C);
ARegion *ar = CTX_wm_region(C);
View2D *v2d = &ar->v2d;
-
+
TreeElement *te;
int xdelta, ytop;
@@ -1019,20 +1066,18 @@ static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op))
/* 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));
-
+
/* make te->xs ==> te->xend center of view */
xdelta = (int)(te->xs - v2d->cur.xmin);
v2d->cur.xmin += xdelta;
v2d->cur.xmax += xdelta;
-
- so->storeflag |= SO_TREESTORE_REDRAW;
}
-
- ED_region_tag_redraw(ar);
-
+
+ ED_region_tag_redraw_no_rebuild(ar);
+
return OPERATOR_FINISHED;
}
@@ -1042,7 +1087,7 @@ void OUTLINER_OT_show_active(wmOperatorType *ot)
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;
@@ -1055,16 +1100,16 @@ 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;
-
+
if (RNA_boolean_get(op->ptr, "up"))
up = 1;
if (up == 0) dy = -dy;
ar->v2d.cur.ymin += dy;
ar->v2d.cur.ymax += dy;
-
- ED_region_tag_redraw(ar);
-
+
+ ED_region_tag_redraw_no_rebuild(ar);
+
return OPERATOR_FINISHED;
}
@@ -1077,11 +1122,11 @@ void OUTLINER_OT_scroll_page(wmOperatorType *ot)
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;
-
+
/* properties */
prop = RNA_def_boolean(ot->srna, "up", 0, "Up", "Scroll up one page");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
@@ -1097,14 +1142,14 @@ static TreeElement *outliner_find_name(SpaceOops *soops, ListBase *lb, char *nam
TreeElement *prev, int *prevFound)
{
TreeElement *te, *tes;
-
+
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))
+ if ((te != prev) && (*prevFound))
return te;
if (te == prev) {
*prevFound = 1;
@@ -1113,7 +1158,7 @@ static TreeElement *outliner_find_name(SpaceOops *soops, ListBase *lb, char *nam
else
return te;
}
-
+
tes = outliner_find_name(soops, &te->subtree, name, flags, prev, prevFound);
if (tes) return tes;
}
@@ -1122,7 +1167,7 @@ static TreeElement *outliner_find_name(SpaceOops *soops, ListBase *lb, char *nam
return NULL;
}
-static void outliner_find_panel(Scene *UNUSED(scene), ARegion *ar, SpaceOops *soops, int again, int flags)
+static void outliner_find_panel(Scene *UNUSED(scene), ARegion *ar, SpaceOops *soops, int again, int flags)
{
ReportList *reports = NULL; // CTX_wm_reports(C);
TreeElement *te = NULL;
@@ -1130,16 +1175,16 @@ static void outliner_find_panel(Scene *UNUSED(scene), ARegion *ar, SpaceOops *so
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) {
@@ -1164,30 +1209,30 @@ static void outliner_find_panel(Scene *UNUSED(scene), ARegion *ar, SpaceOops *so
/* 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_set_flag(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 */
- soops->storeflag |= SO_TREESTORE_REDRAW;
+ ED_region_tag_redraw_no_rebuild(ar);
}
}
else {
@@ -1204,17 +1249,17 @@ static void outliner_openclose_level(ListBase *lb, int curlevel, int level, int
{
TreeElement *te;
TreeStoreElem *tselem;
-
+
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;
}
-
+
outliner_openclose_level(&te->subtree, curlevel + 1, level, open);
}
}
@@ -1225,7 +1270,7 @@ static int outliner_one_level_exec(bContext *C, wmOperator *op)
ARegion *ar = CTX_wm_region(C);
const bool add = RNA_boolean_get(op->ptr, "open");
int level;
-
+
level = outliner_has_one_flag(&soops->tree, TSE_CLOSED, 1);
if (add == 1) {
if (level) outliner_openclose_level(&soops->tree, 1, level, 1);
@@ -1234,9 +1279,9 @@ static int outliner_one_level_exec(bContext *C, wmOperator *op)
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);
-
+
return OPERATOR_FINISHED;
}
@@ -1248,13 +1293,13 @@ void OUTLINER_OT_show_one_level(wmOperatorType *ot)
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;
-
+
/* 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);
@@ -1267,7 +1312,7 @@ static int subtree_has_objects(ListBase *lb)
{
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;
@@ -1285,7 +1330,7 @@ static void tree_element_show_hierarchy(Scene *scene, SpaceOops *soops, ListBase
/* 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;
@@ -1312,12 +1357,12 @@ static int outliner_show_hierarchy_exec(bContext *C, wmOperator *UNUSED(op))
SpaceOops *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);
-
+
ED_region_tag_redraw(ar);
-
+
return OPERATOR_FINISHED;
}
@@ -1327,11 +1372,11 @@ void OUTLINER_OT_show_hierarchy(wmOperatorType *ot)
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...
-
+
/* no undo or registry, UI option */
}
@@ -1345,15 +1390,15 @@ static int ed_operator_outliner_datablocks_active(bContext *C)
ScrArea *sa = CTX_wm_area(C);
if ((sa) && (sa->spacetype == SPACE_OUTLINER)) {
SpaceOops *so = CTX_wm_space_outliner(C);
- return (so->outlinevis == SO_DATABLOCKS);
+ return (so->outlinevis == SO_DATA_API);
}
return 0;
}
-/* Helper func to extract an RNA path from selected tree element
+/* 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
+ * 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))
@@ -1365,29 +1410,29 @@ static void tree_element_to_path(TreeElement *te, TreeStoreElem *tselem,
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
+ * (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) {
@@ -1396,10 +1441,10 @@ static void tree_element_to_path(TreeElement *te, TreeStoreElem *tselem,
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
+ /* 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) {
@@ -1409,35 +1454,35 @@ static void tree_element_to_path(TreeElement *te, TreeStoreElem *tselem,
}
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;
@@ -1451,7 +1496,7 @@ static void tree_element_to_path(TreeElement *te, TreeStoreElem *tselem,
* 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);
@@ -1467,7 +1512,7 @@ static void tree_element_to_path(TreeElement *te, TreeStoreElem *tselem,
/* 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 */
@@ -1477,7 +1522,7 @@ static void tree_element_to_path(TreeElement *te, TreeStoreElem *tselem,
/* 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);
@@ -1499,17 +1544,17 @@ enum {
DRIVERS_EDITMODE_REMOVE,
} /*eDrivers_EditModes*/;
-/* Utilities ---------------------------------- */
+/* Utilities ---------------------------------- */
/* Recursively iterate over tree, finding and working on selected items */
static void do_outliner_drivers_editop(SpaceOops *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;
@@ -1517,7 +1562,7 @@ static void do_outliner_drivers_editop(SpaceOops *soops, ListBase *tree, ReportL
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))
@@ -1526,12 +1571,12 @@ static void do_outliner_drivers_editop(SpaceOops *soops, ListBase *tree, ReportL
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 */
@@ -1539,11 +1584,11 @@ static void do_outliner_drivers_editop(SpaceOops *soops, ListBase *tree, ReportL
}
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 */
@@ -1562,14 +1607,14 @@ static void do_outliner_drivers_editop(SpaceOops *soops, ListBase *tree, ReportL
}
}
}
-
+
/* 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);
@@ -1581,17 +1626,17 @@ static void do_outliner_drivers_editop(SpaceOops *soops, ListBase *tree, ReportL
static int outliner_drivers_addsel_exec(bContext *C, wmOperator *op)
{
SpaceOops *soutliner = CTX_wm_space_outliner(C);
-
+
/* 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);
-
+
/* send notifiers */
WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX
-
+
return OPERATOR_FINISHED;
}
@@ -1601,11 +1646,11 @@ void OUTLINER_OT_drivers_add_selected(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1616,17 +1661,17 @@ void OUTLINER_OT_drivers_add_selected(wmOperatorType *ot)
static int outliner_drivers_deletesel_exec(bContext *C, wmOperator *op)
{
SpaceOops *soutliner = CTX_wm_space_outliner(C);
-
+
/* 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);
-
+
/* send notifiers */
WM_event_add_notifier(C, ND_KEYS, NULL); // XXX
-
+
return OPERATOR_FINISHED;
}
@@ -1636,11 +1681,11 @@ void OUTLINER_OT_drivers_delete_selected(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1656,29 +1701,29 @@ enum {
KEYINGSET_EDITMODE_REMOVE,
} /*eKeyingSet_EditModes*/;
-/* Utilities ---------------------------------- */
-
+/* Utilities ---------------------------------- */
+
/* find the 'active' KeyingSet, and add if not found (if adding is allowed) */
// TODO: should this be an API func?
static KeyingSet *verify_active_keyingset(Scene *scene, short add)
{
KeyingSet *ks = 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);
-
+
/* 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;
}
@@ -1687,10 +1732,10 @@ static void do_outliner_keyingset_editop(SpaceOops *soops, KeyingSet *ks, ListBa
{
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;
@@ -1698,7 +1743,7 @@ static void do_outliner_keyingset_editop(SpaceOops *soops, KeyingSet *ks, ListBa
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))
@@ -1707,7 +1752,7 @@ static void do_outliner_keyingset_editop(SpaceOops *soops, KeyingSet *ks, ListBa
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 */
@@ -1725,7 +1770,7 @@ static void do_outliner_keyingset_editop(SpaceOops *soops, KeyingSet *ks, ListBa
{
/* 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);
@@ -1735,12 +1780,12 @@ static void do_outliner_keyingset_editop(SpaceOops *soops, KeyingSet *ks, ListBa
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);
@@ -1754,7 +1799,7 @@ static int outliner_keyingset_additems_exec(bContext *C, wmOperator *op)
SpaceOops *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");
@@ -1762,13 +1807,13 @@ static int outliner_keyingset_additems_exec(bContext *C, wmOperator *op)
}
if (soutliner == NULL)
return OPERATOR_CANCELLED;
-
+
/* 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);
-
+
return OPERATOR_FINISHED;
}
@@ -1778,11 +1823,11 @@ void OUTLINER_OT_keyingset_add_selected(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1795,17 +1840,17 @@ static int outliner_keyingset_removeitems_exec(bContext *C, wmOperator *UNUSED(o
SpaceOops *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;
-
+
/* 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);
-
+
return OPERATOR_FINISHED;
}
@@ -1815,11 +1860,11 @@ void OUTLINER_OT_keyingset_remove_selected(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1855,7 +1900,7 @@ static int outliner_orphans_purge_exec(bContext *C, wmOperator *UNUSED(op))
* are retained...
*/
WM_operator_name_call(C, "WM_OT_save_mainfile", WM_OP_EXEC_DEFAULT, NULL);
-
+
/* Now, reload the file to get rid of the orphans... */
WM_operator_name_call(C, "WM_OT_revert_mainfile", WM_OP_EXEC_DEFAULT, NULL);
return OPERATOR_FINISHED;
@@ -1868,12 +1913,12 @@ void OUTLINER_OT_orphans_purge(wmOperatorType *ot)
ot->name = "Purge All";
ot->description = "Clear all orphaned data-blocks without any users from the file "
"(cannot be undone, saves to current .blend file)";
-
+
/* 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;
}
@@ -1893,9 +1938,9 @@ static int parent_drop_exec(bContext *C, wmOperator *op)
partype = RNA_enum_get(op->ptr, "type");
RNA_string_get(op->ptr, "parent", parname);
- par = (Object *)BKE_libblock_find_name(ID_OB, parname);
+ par = (Object *)BKE_libblock_find_name(bmain, ID_OB, parname);
RNA_string_get(op->ptr, "child", childname);
- ob = (Object *)BKE_libblock_find_name(ID_OB, 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");
@@ -1920,7 +1965,6 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Main *bmain = CTX_data_main(C);
Scene *scene = NULL;
TreeElement *te = NULL;
- TreeStoreElem *tselem;
char childname[MAX_ID_NAME];
char parname[MAX_ID_NAME];
int partype = 0;
@@ -1930,28 +1974,15 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* Find object hovered over */
te = outliner_dropzone_find(soops, fmval, true);
- tselem = te ? TREESTORE(te) : NULL;
- if (tselem && ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
- SceneCollection *sc = outliner_scene_collection_from_tree_element(te);
-
- scene = BKE_scene_find_from_collection(bmain, sc);
- BLI_assert(scene);
- RNA_string_get(op->ptr, "child", childname);
- ob = (Object *)BKE_libblock_find_name(ID_OB, childname);
- BKE_collection_object_add(&scene->id, sc, ob);
-
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- }
- else if (te) {
+ if (te) {
RNA_string_set(op->ptr, "parent", te->name);
/* Identify parent and child */
RNA_string_get(op->ptr, "child", childname);
- ob = (Object *)BKE_libblock_find_name(ID_OB, childname);
+ ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, childname);
RNA_string_get(op->ptr, "parent", parname);
- par = (Object *)BKE_libblock_find_name(ID_OB, parname);
-
+ par = (Object *)BKE_libblock_find_name(bmain, ID_OB, parname);
+
if (ELEM(NULL, ob, par)) {
if (par == NULL) printf("par==NULL\n");
return OPERATOR_CANCELLED;
@@ -1963,7 +1994,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
BKE_report(op->reports, RPT_INFO, "Can't edit library linked object");
return OPERATOR_CANCELLED;
}
-
+
scene = (Scene *)outliner_search_back(soops, te, ID_SCE);
if (scene == NULL) {
@@ -1988,7 +2019,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
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);
@@ -2044,9 +2075,9 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_LATTICE);
}
-
+
UI_popup_menu_end(C, pup);
-
+
return OPERATOR_INTERFACE;
}
}
@@ -2087,9 +2118,10 @@ static int outliner_parenting_poll(bContext *C)
if (soops->outlinevis == SO_SCENES) {
return true;
}
-
- if (soops->outlinevis == SO_COLLECTIONS) {
- return (soops->filter & SO_FILTER_NO_COLLECTION);
+ else if ((soops->outlinevis == SO_VIEW_LAYER) &&
+ (soops->filter & SO_FILTER_NO_COLLECTION))
+ {
+ return true;
}
}
@@ -2104,7 +2136,7 @@ static int parent_clear_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
char obname[MAX_ID_NAME];
RNA_string_get(op->ptr, "dragged_obj", obname);
- ob = (Object *)BKE_libblock_find_name(ID_OB, obname);
+ ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, obname);
/* search forwards to find the object */
outliner_find_id(soops, &soops->tree, (ID *)ob);
@@ -2155,10 +2187,10 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if (te) {
RNA_string_set(op->ptr, "scene", te->name);
- scene = (Scene *)BKE_libblock_find_name(ID_SCE, te->name);
+ scene = (Scene *)BKE_libblock_find_name(bmain, ID_SCE, te->name);
RNA_string_get(op->ptr, "object", obname);
- ob = (Object *)BKE_libblock_find_name(ID_OB, obname);
+ ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, obname);
if (ELEM(NULL, ob, scene) || ID_IS_LINKED(scene)) {
return OPERATOR_CANCELLED;
@@ -2168,16 +2200,16 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
}
- SceneCollection *sc;
+ Collection *collection;
if (scene != CTX_data_scene(C)) {
/* when linking to an inactive scene link to the master collection */
- sc = BKE_collection_master(&scene->id);
+ collection = BKE_collection_master(scene);
}
else {
- sc = CTX_data_scene_collection(C);
+ collection = CTX_data_collection(C);
}
- BKE_collection_object_add(&scene->id, sc, ob);
+ 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);
@@ -2188,6 +2220,7 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
return OPERATOR_FINISHED;
@@ -2220,6 +2253,7 @@ static int material_drop_invoke(bContext *C, wmOperator *op, const wmEvent *even
{
Material *ma = NULL;
Object *ob = NULL;
+ Main *bmain = CTX_data_main(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
ARegion *ar = CTX_wm_region(C);
TreeElement *te = NULL;
@@ -2233,16 +2267,16 @@ static int material_drop_invoke(bContext *C, wmOperator *op, const wmEvent *even
if (te) {
RNA_string_set(op->ptr, "object", te->name);
- ob = (Object *)BKE_libblock_find_name(ID_OB, te->name);
+ ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, te->name);
RNA_string_get(op->ptr, "material", mat_name);
- ma = (Material *)BKE_libblock_find_name(ID_MA, mat_name);
+ ma = (Material *)BKE_libblock_find_name(bmain, ID_MA, mat_name);
if (ELEM(NULL, ob, ma)) {
return OPERATOR_CANCELLED;
}
- assign_material(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);
@@ -2273,58 +2307,82 @@ void OUTLINER_OT_material_drop(wmOperatorType *ot)
RNA_def_string(ot->srna, "material", "Material", MAX_ID_NAME, "Material", "Target Material");
}
-static int group_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+/* ******************** Collection Drop Operator *********************** */
+
+static int collection_drop_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
{
+ /* TODO: implement */
+#if 0
+ Object *par = NULL, *ob = NULL;
Main *bmain = CTX_data_main(C);
- Group *group = NULL;
- Object *ob = NULL;
+ Scene *scene = CTX_data_scene(C);
+ int partype = -1;
+ char parname[MAX_ID_NAME], childname[MAX_ID_NAME];
+
+ RNA_string_get(op->ptr, "parent", parname);
+ par = (Object *)BKE_libblock_find_name(ID_OB, parname);
+ RNA_string_get(op->ptr, "child", childname);
+ ob = (Object *)BKE_libblock_find_name(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);
+#endif
+
+ return OPERATOR_FINISHED;
+}
+
+static int collection_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
SpaceOops *soops = CTX_wm_space_outliner(C);
ARegion *ar = CTX_wm_region(C);
- TreeElement *te = NULL;
- char ob_name[MAX_ID_NAME - 2];
+ Main *bmain = CTX_data_main(C);
+ char childname[MAX_ID_NAME];
float fmval[2];
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
/* Find object hovered over */
- te = outliner_dropzone_find(soops, fmval, true);
+ TreeElement *te = outliner_dropzone_find(soops, fmval, true);
- if (te) {
- group = (Group *)BKE_libblock_find_name(ID_GR, te->name);
-
- RNA_string_get(op->ptr, "object", ob_name);
- ob = (Object *)BKE_libblock_find_name(ID_OB, ob_name);
-
- if (ELEM(NULL, group, ob)) {
- return OPERATOR_CANCELLED;
- }
- if (BKE_group_object_exists(group, ob)) {
- return OPERATOR_FINISHED;
- }
+ if (!te || !outliner_is_collection_tree_element(te)) {
+ return OPERATOR_CANCELLED;
+ }
- if (BKE_group_object_cyclic_check(bmain, ob, group)) {
- BKE_report(op->reports, RPT_ERROR, "Could not add the group because of dependency cycle detected");
- return OPERATOR_CANCELLED;
- }
+ Collection *collection = outliner_collection_from_tree_element(te);
- BKE_group_object_add(group, ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ // TODO: don't use scene, makes no sense anymore
+ // TODO: move rather than link, change hover text
+ Scene *scene = BKE_scene_find_from_collection(bmain, collection);
+ BLI_assert(scene);
+ RNA_string_get(op->ptr, "child", childname);
+ Object *ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, childname);
+ BKE_collection_object_add(bmain, collection, ob);
- return OPERATOR_FINISHED;
- }
+ DEG_id_tag_update(&collection->id, DEG_TAG_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- return OPERATOR_CANCELLED;
+ return OPERATOR_FINISHED;
}
-void OUTLINER_OT_group_link(wmOperatorType *ot)
+void OUTLINER_OT_collection_drop(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Link Object to Group";
- ot->description = "Link Object to Group in Outliner";
- ot->idname = "OUTLINER_OT_group_link";
+ ot->name = "Link to Collection"; // TODO: rename to move?
+ ot->description = "Drag to move to collection in Outliner";
+ ot->idname = "OUTLINER_OT_collection_drop";
/* api callbacks */
- ot->invoke = group_link_invoke;
+ ot->invoke = collection_drop_invoke;
+ ot->exec = collection_drop_exec;
ot->poll = ED_operator_outliner_active;
@@ -2332,5 +2390,6 @@ void OUTLINER_OT_group_link(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
/* properties */
- RNA_def_string(ot->srna, "object", "Object", MAX_ID_NAME, "Object", "Target Object");
+ RNA_def_string(ot->srna, "child", "Object", MAX_ID_NAME, "Child", "Child Object");
+ RNA_def_string(ot->srna, "parent", "Collection", MAX_ID_NAME, "Parent", "Parent Collection");
}
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index a0de3a06556..0ab22208841 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -71,6 +71,7 @@ typedef enum TreeTraversalAction {
* Callback type for reinserting elements at a different position, used to allow user customizable element order.
*/
typedef void (*TreeElementReinsertFunc)(struct Main *bmain,
+ struct Scene *scene,
struct SpaceOops *soops,
struct TreeElement *insert_element,
struct TreeElement *insert_handle,
@@ -114,7 +115,7 @@ typedef struct TreeElement {
#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) || \
- ELEM(GS((_id)->name), ID_SCR, ID_WM, ID_TXT, ID_VF, ID_SO, ID_CF, ID_PAL, ID_WS)) /* 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)) /* Only in 'blendfile' mode ... :/ */
/* TreeElement->flag */
enum {
@@ -124,6 +125,7 @@ enum {
TE_ICONROW = (1 << 1),
TE_LAZY_CLOSED = (1 << 2),
TE_FREE_NAME = (1 << 3),
+ TE_DISABLED = (1 << 4),
};
/* button events */
@@ -141,7 +143,7 @@ typedef enum {
OL_SETSEL_EXTEND = 2, /* select the item and extend (also toggles selection) */
} eOLSetState;
-/* get TreeStoreElem associated with a TreeElement
+/* get TreeStoreElem associated with a TreeElement
* < a: (TreeElement) tree element to find stored element for
*/
#define TREESTORE(a) ((a)->store_elem)
@@ -149,11 +151,12 @@ typedef enum {
/* size constants */
#define OL_Y_OFFSET 2
-#define OL_TOG_RESTRICT_VIEWX (UI_UNIT_X * 3.0f)
-#define OL_TOG_RESTRICT_SELECTX (UI_UNIT_X * 2.0f)
+#define OL_TOG_HIDEX (UI_UNIT_X * 4.0f)
+#define OL_TOG_RESTRICT_SELECTX (UI_UNIT_X * 3.0f)
+#define OL_TOG_RESTRICT_VIEWX (UI_UNIT_X * 2.0f)
#define OL_TOG_RESTRICT_RENDERX UI_UNIT_X
-#define OL_TOGW OL_TOG_RESTRICT_VIEWX
+#define OL_TOGW OL_TOG_HIDEX
#define OL_RNA_COLX (UI_UNIT_X * 15)
#define OL_RNA_COL_SIZEX (UI_UNIT_X * 7.5f)
@@ -161,25 +164,25 @@ typedef enum {
/* The outliner display modes that support the filter system.
* Note: keep it synced with space_outliner.py */
-#define SUPPORT_FILTER_OUTLINER(soops_) ((soops_)->outlinevis == SO_COLLECTIONS)
+#define SUPPORT_FILTER_OUTLINER(soops_) (ELEM((soops_)->outlinevis, SO_VIEW_LAYER))
/* Outliner Searching --
*
* Are we looking for something in the outliner?
* If so finding matches in child items makes it more useful
*
- * - We want to flag parents to act as being open to filter child matches
+ * - We want to flag parents to act as being open to filter child matches
* - and also flag matches so we can highlight them
* - Flags are stored in TreeStoreElem->flag
* - Flag options defined in DNA_outliner_types.h
* - SO_SEARCH_RECURSIVE defined in DNA_space_types.h
*
- * - NOT in datablocks view - searching all datablocks takes way too long
+ * - NOT in datablocks view - searching all datablocks takes way too long
* to be useful
* - not searching into RNA items helps but isn't the complete solution
*/
-#define SEARCHING_OUTLINER(sov) ((sov->search_flags & SO_SEARCH_RECURSIVE) && (sov->filter & SO_FILTER_SEARCH))
+#define SEARCHING_OUTLINER(sov) (sov->search_flags & SO_SEARCH_RECURSIVE)
/* is the currrent 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)) )
@@ -189,7 +192,6 @@ typedef enum {
void outliner_free_tree(ListBase *tree);
void outliner_cleanup_tree(struct SpaceOops *soops);
void outliner_free_tree_element(TreeElement *element, ListBase *parent_subtree);
-void outliner_remove_treestore_element(struct SpaceOops *soops, TreeStoreElem *tselem);
void outliner_build_tree(
struct Main *mainvar,
@@ -225,6 +227,10 @@ void outliner_item_select(
struct SpaceOops *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,
@@ -253,16 +259,6 @@ void object_toggle_renderability_cb(
TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
-void group_toggle_visibility_cb(
- struct bContext *C, struct ReportList *reports, struct Scene *scene,
- TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
-void group_toggle_selectability_cb(
- struct bContext *C, struct ReportList *reports, struct Scene *scene,
- TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
-void group_toggle_renderability_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);
@@ -280,6 +276,13 @@ 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);
+
TreeElement *outliner_dropzone_find(const struct SpaceOops *soops, const float fmval[2], const bool children);
void outliner_set_coordinates(struct ARegion *ar, struct SpaceOops *soops);
@@ -319,14 +322,13 @@ void OUTLINER_OT_parent_drop(struct wmOperatorType *ot);
void OUTLINER_OT_parent_clear(struct wmOperatorType *ot);
void OUTLINER_OT_scene_drop(struct wmOperatorType *ot);
void OUTLINER_OT_material_drop(struct wmOperatorType *ot);
-void OUTLINER_OT_group_link(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_drop(struct wmOperatorType *ot);
/* outliner_tools.c ---------------------------------------------- */
void OUTLINER_OT_operation(struct wmOperatorType *ot);
void OUTLINER_OT_scene_operation(struct wmOperatorType *ot);
void OUTLINER_OT_object_operation(struct wmOperatorType *ot);
-void OUTLINER_OT_group_operation(struct wmOperatorType *ot);
void OUTLINER_OT_lib_operation(struct wmOperatorType *ot);
void OUTLINER_OT_id_operation(struct wmOperatorType *ot);
void OUTLINER_OT_id_remap(struct wmOperatorType *ot);
@@ -335,7 +337,7 @@ void OUTLINER_OT_animdata_operation(struct wmOperatorType *ot);
void OUTLINER_OT_action_set(struct wmOperatorType *ot);
void OUTLINER_OT_constraint_operation(struct wmOperatorType *ot);
void OUTLINER_OT_modifier_operation(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_operation(struct wmOperatorType *ot);
+
/* ---------------------------------------------------------------- */
/* outliner_ops.c */
@@ -344,23 +346,18 @@ void outliner_keymap(struct wmKeyConfig *keyconf);
/* outliner_collections.c */
-struct SceneCollection *outliner_scene_collection_from_tree_element(TreeElement *te);
+bool outliner_is_collection_tree_element(const TreeElement *te);
+struct Collection *outliner_collection_from_tree_element(const TreeElement *te);
-void OUTLINER_OT_collections_delete(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_select(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_toggle(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_link(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_unlink(struct wmOperatorType *ot);
void OUTLINER_OT_collection_new(struct wmOperatorType *ot);
void OUTLINER_OT_collection_duplicate(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_objects_remove(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_delete(struct wmOperatorType *ot);
void OUTLINER_OT_collection_objects_select(struct wmOperatorType *ot);
-void OUTLINER_OT_object_add_to_new_collection(struct wmOperatorType *ot);
-void OUTLINER_OT_object_remove_from_collection(struct wmOperatorType *ot);
-
-void OUTLINER_OT_collection_objects_add(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_nested_new(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_delete_selected(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_objects_deselect(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_link(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_instance(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_exclude_set(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_include_set(struct wmOperatorType *ot);
/* outliner_utils.c ---------------------------------------------- */
@@ -368,6 +365,7 @@ TreeElement *outliner_find_item_at_y(const SpaceOops *soops, const ListBase *tre
TreeElement *outliner_find_item_at_x_in_row(const SpaceOops *soops, const TreeElement *parent_te, float view_co_x);
TreeElement *outliner_find_tse(struct SpaceOops *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_id(struct SpaceOops *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);
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index 2c4670d9ea3..b0478da55b5 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -33,12 +33,15 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
+#include "DNA_group_types.h"
+
#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_main.h"
#include "GPU_immediate.h"
+#include "GPU_state.h"
#include "RNA_access.h"
@@ -67,7 +70,7 @@ static int outliner_item_drag_drop_poll(bContext *C)
SpaceOops *soops = CTX_wm_space_outliner(C);
return ED_operator_outliner_active(C) &&
/* Only collection display modes supported for now. Others need more design work */
- ELEM(soops->outlinevis, SO_COLLECTIONS, SO_GROUPS);
+ ELEM(soops->outlinevis, SO_VIEW_LAYER, SO_LIBRARIES);
}
static TreeElement *outliner_item_drag_element_find(SpaceOops *soops, ARegion *ar, const wmEvent *event)
@@ -184,25 +187,19 @@ static void outliner_item_drag_handle(
*/
static bool is_empty_collection(TreeElement *te)
{
- if (!ELEM(TREESTORE(te)->type, TSE_SCENE_COLLECTION, TSE_LAYER_COLLECTION)) {
- return false;
- }
+ Collection *collection = outliner_collection_from_tree_element(te);
- SceneCollection *scene_collection;
- if (TREESTORE(te)->type == TSE_SCENE_COLLECTION) {
- scene_collection = (SceneCollection *)te->directdata;
- }
- else {
- BLI_assert(TREESTORE(te)->type == TSE_LAYER_COLLECTION);
- scene_collection = ((LayerCollection *)te->directdata)->scene_collection;
+ if (!collection) {
+ return false;
}
- return BLI_listbase_is_empty(&scene_collection->objects) &&
- BLI_listbase_is_empty(&scene_collection->scene_collections);
+ return BLI_listbase_is_empty(&collection->gobject) &&
+ BLI_listbase_is_empty(&collection->children);
}
static bool outliner_item_drag_drop_apply(
Main *bmain,
+ Scene *scene,
SpaceOops *soops,
OutlinerDragDropTooltip *data,
const wmEvent *event)
@@ -225,7 +222,7 @@ static bool outliner_item_drag_drop_apply(
* it is strange to have it closed and we not see the newly dragged elements. */
const bool should_open_collection = (insert_type == TE_INSERT_INTO) && is_empty_collection(insert_handle);
- dragged_te->reinsert(bmain, soops, dragged_te, insert_handle, insert_type, event);
+ dragged_te->reinsert(bmain, scene, soops, dragged_te, insert_handle, insert_type, event);
if (should_open_collection && !is_empty_collection(insert_handle)) {
TREESTORE(insert_handle)->flag &= ~TSE_CLOSED;
@@ -239,6 +236,7 @@ static bool outliner_item_drag_drop_apply(
static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
OutlinerDragDropTooltip *data = op->customdata;
@@ -250,7 +248,7 @@ static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEv
switch (event->type) {
case EVT_MODAL_MAP:
if (event->val == OUTLINER_ITEM_DRAG_CONFIRM) {
- if (outliner_item_drag_drop_apply(bmain, soops, data, event)) {
+ if (outliner_item_drag_drop_apply(bmain, scene, soops, data, event)) {
skip_rebuild = false;
}
retval = OPERATOR_FINISHED;
@@ -271,47 +269,32 @@ static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEv
break;
}
- if (skip_rebuild) {
- soops->storeflag |= SO_TREESTORE_REDRAW; /* only needs to redraw, no rebuild */
- }
if (redraw) {
- ED_region_tag_redraw(ar);
+ if (skip_rebuild) {
+ ED_region_tag_redraw_no_rebuild(ar);
+ }
+ else {
+ ED_region_tag_redraw(ar);
+ }
}
return retval;
}
-/**
- * Check if the given TreeElement is a collection
- *
- * This test is mainly used to see if next/prev TreeElement is a collection.
- * It will fail when there is no next/prev TreeElement, or when the
- * element is an Override or something else in the future.
- */
-static bool tree_element_is_collection_get(const TreeElement *te)
-{
- if (te == NULL) {
- return false;
- }
-
- TreeStoreElem *tselem = TREESTORE(te);
- return ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION);
-}
-
static const char *outliner_drag_drop_tooltip_get(
const TreeElement *te_float)
{
const char *name = NULL;
const TreeElement *te_insert = te_float->drag_data->insert_handle;
- if (tree_element_is_collection_get(te_float)) {
+ if (te_float && outliner_is_collection_tree_element(te_float)) {
if (te_insert == NULL) {
name = TIP_("Move collection");
}
else {
switch (te_float->drag_data->insert_type) {
case TE_INSERT_BEFORE:
- if (tree_element_is_collection_get(te_insert->prev)) {
+ if (te_insert->prev && outliner_is_collection_tree_element(te_insert->prev)) {
name = TIP_("Move between collections");
}
else {
@@ -319,7 +302,7 @@ static const char *outliner_drag_drop_tooltip_get(
}
break;
case TE_INSERT_AFTER:
- if (tree_element_is_collection_get(te_insert->next)) {
+ if (te_insert->next && outliner_is_collection_tree_element(te_insert->next)) {
name = TIP_("Move between collections");
}
else {
@@ -333,7 +316,7 @@ static const char *outliner_drag_drop_tooltip_get(
}
}
else if ((TREESTORE(te_float)->type == 0) && (te_float->idcode == ID_OB)) {
- name = TIP_("Move to collection (Ctrl to add)");
+ name = TIP_("Move to collection (Ctrl to link)");
}
return name;
@@ -364,9 +347,9 @@ static void outliner_drag_drop_tooltip_cb(const wmWindow *win, void *vdata)
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};
- glEnable(GL_BLEND);
+ GPU_blend(true);
UI_fontstyle_draw_simple_backdrop(fstyle, x, y, tooltip, col_fg, col_bg);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
static int outliner_item_drag_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
@@ -389,8 +372,7 @@ static int outliner_item_drag_drop_invoke(bContext *C, wmOperator *op, const wmE
/* unset highlighted tree element, dragged one will be highlighted instead */
outliner_set_flag(&soops->tree, TSE_HIGHLIGHTED, false);
- soops->storeflag |= SO_TREESTORE_REDRAW; /* only needs to redraw, no rebuild */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw_no_rebuild(ar);
WM_event_add_modal_handler(C, op);
@@ -433,7 +415,6 @@ void outliner_operatortypes(void)
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_group_operation);
WM_operatortype_append(OUTLINER_OT_lib_operation);
WM_operatortype_append(OUTLINER_OT_lib_relocate);
WM_operatortype_append(OUTLINER_OT_id_operation);
@@ -444,46 +425,39 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_action_set);
WM_operatortype_append(OUTLINER_OT_constraint_operation);
WM_operatortype_append(OUTLINER_OT_modifier_operation);
- WM_operatortype_append(OUTLINER_OT_collection_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_selected_toggle);
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_group_link);
+ WM_operatortype_append(OUTLINER_OT_collection_drop);
/* collections */
- WM_operatortype_append(OUTLINER_OT_collections_delete);
- WM_operatortype_append(OUTLINER_OT_collection_select);
- WM_operatortype_append(OUTLINER_OT_collection_toggle);
- WM_operatortype_append(OUTLINER_OT_collection_link);
- WM_operatortype_append(OUTLINER_OT_collection_unlink);
WM_operatortype_append(OUTLINER_OT_collection_new);
WM_operatortype_append(OUTLINER_OT_collection_duplicate);
-
- WM_operatortype_append(OUTLINER_OT_collection_nested_new);
- WM_operatortype_append(OUTLINER_OT_collection_delete_selected);
- WM_operatortype_append(OUTLINER_OT_collection_objects_add);
- WM_operatortype_append(OUTLINER_OT_collection_objects_remove);
+ WM_operatortype_append(OUTLINER_OT_collection_delete);
WM_operatortype_append(OUTLINER_OT_collection_objects_select);
- WM_operatortype_append(OUTLINER_OT_object_add_to_new_collection);
- WM_operatortype_append(OUTLINER_OT_object_remove_from_collection);
+ 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_include_set);
}
static wmKeyMap *outliner_item_drag_drop_modal_keymap(wmKeyConfig *keyconf)
@@ -543,47 +517,60 @@ void outliner_keymap(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "OUTLINER_OT_select_border", BKEY, KM_PRESS, 0, 0);
-
+
kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_openclose", RETKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "all", false);
kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_openclose", RETKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "all", true);
-
+
WM_keymap_add_item(keymap, "OUTLINER_OT_item_rename", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "OUTLINER_OT_operation", RIGHTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "OUTLINER_OT_item_drag_drop", EVT_TWEAK_L, KM_ANY, 0, 0);
WM_keymap_add_item(keymap, "OUTLINER_OT_show_hierarchy", HOMEKEY, KM_PRESS, 0, 0);
-
+
WM_keymap_add_item(keymap, "OUTLINER_OT_show_active", PERIODKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "OUTLINER_OT_show_active", PADPERIOD, KM_PRESS, 0, 0);
-
+
kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_scroll_page", PAGEDOWNKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "up", false);
kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_scroll_page", PAGEUPKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "up", true);
-
+
WM_keymap_add_item(keymap, "OUTLINER_OT_show_one_level", PADPLUSKEY, KM_PRESS, 0, 0); /* open */
kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_show_one_level", PADMINUS, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "open", false); /* close */
-
+
WM_keymap_verify_item(keymap, "OUTLINER_OT_selected_toggle", AKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "OUTLINER_OT_expanded_toggle", AKEY, KM_PRESS, KM_SHIFT, 0);
-
+
/* keying sets - only for databrowse */
WM_keymap_verify_item(keymap, "OUTLINER_OT_keyingset_add_selected", KKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "OUTLINER_OT_keyingset_remove_selected", KKEY, KM_PRESS, KM_ALT, 0);
-
+
WM_keymap_verify_item(keymap, "ANIM_OT_keyframe_insert", IKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "ANIM_OT_keyframe_delete", IKEY, KM_PRESS, KM_ALT, 0);
-
+
WM_keymap_verify_item(keymap, "OUTLINER_OT_drivers_add_selected", DKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "OUTLINER_OT_drivers_delete_selected", DKEY, KM_PRESS, KM_ALT, 0);
- WM_keymap_verify_item(keymap, "OUTLINER_OT_collection_nested_new", CKEY, KM_PRESS, 0, 0);
- WM_keymap_verify_item(keymap, "OUTLINER_OT_collection_delete_selected", XKEY, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "OUTLINER_OT_collection_new", CKEY, KM_PRESS, 0, 0);
+#ifdef USE_WM_KEYMAP_27X
+ WM_keymap_verify_item(keymap, "OUTLINER_OT_collection_delete", XKEY, KM_PRESS, 0, 0);
+#else
+ WM_keymap_verify_item(keymap, "OUTLINER_OT_collection_delete", DELKEY, KM_PRESS, 0, 0);
+#endif
+
+ WM_keymap_verify_item(keymap, "OBJECT_OT_move_to_collection", MKEY, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "OBJECT_OT_link_to_collection", MKEY, KM_PRESS, KM_SHIFT, 0);
+
+ kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_clear", HKEY, KM_PRESS, KM_ALT, 0);
+ RNA_boolean_set(kmi->ptr, "select", false);
+ kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "unselected", false);
+ kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "unselected", true);
outliner_item_drag_drop_modal_keymap(keyconf);
}
-
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index a3dbab1b3fd..6668ea1faeb 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -44,9 +44,10 @@
#include "BLI_listbase.h"
#include "BKE_armature.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_group.h"
#include "BKE_layer.h"
+#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_scene.h"
#include "BKE_sequencer.h"
@@ -72,6 +73,101 @@
#include "outliner_intern.h"
+static void do_outliner_activate_obdata(bContext *C, Scene *scene, ViewLayer *view_layer, Base *base)
+{
+ Main *bmain = CTX_data_main(C);
+ Object *obact = OBACT(view_layer);
+ bool use_all = false;
+
+ if (obact == NULL) {
+ ED_object_base_activate(C, base);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ obact = base->object;
+ use_all = true;
+ }
+ else if (obact->data == base->object->data) {
+ use_all = true;
+ }
+
+ if (use_all) {
+ WM_operator_name_call(C, "OBJECT_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
+ }
+ else {
+ Object *ob = base->object;
+ if (ob->type == obact->type) {
+ bool ok;
+ if (BKE_object_is_in_editmode(ob)) {
+ ok = ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA | EM_WAITCURSOR);
+ }
+ else {
+ ok = ED_object_editmode_enter_ex(CTX_data_main(C), scene, ob, EM_WAITCURSOR | 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, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ }
+ }
+ }
+}
+
+static void do_outliner_activate_pose(bContext *C, ViewLayer *view_layer, Base *base)
+{
+ Object *obact = OBACT(view_layer);
+ bool use_all = false;
+
+ if (obact == NULL) {
+ ED_object_base_activate(C, base);
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ obact = base->object;
+ use_all = true;
+ }
+ else if (obact->data == base->object->data) {
+ use_all = true;
+ }
+
+ if (use_all) {
+ WM_operator_name_call(C, "OBJECT_OT_posemode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
+ }
+ else {
+ Object *ob = base->object;
+ if (ob->type == obact->type) {
+ struct Main *bmain = CTX_data_main(C);
+ 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);
+
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ 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)
+{
+ Object *obact = OBACT(view_layer);
+ if (obact->mode & OB_MODE_EDIT) {
+ do_outliner_activate_obdata(C, scene, view_layer, base);
+ }
+ else if (obact->mode & OB_MODE_POSE) {
+ do_outliner_activate_pose(C, view_layer, base);
+ }
+}
/* ****************************************************** */
/* Outliner Element Selection/Activation on Click */
@@ -80,12 +176,12 @@ static eOLDrawState active_viewlayer(
bContext *C, Scene *UNUSED(scene), ViewLayer *UNUSED(sl), TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
{
Scene *sce;
-
+
/* paranoia check */
if (te->idcode != ID_SCE)
return OL_DRAWSEL_NONE;
sce = (Scene *)tselem->id;
-
+
WorkSpace *workspace = CTX_wm_workspace(C);
ViewLayer *view_layer = te->directdata;
@@ -110,7 +206,7 @@ static void do_outliner_object_select_recursive(ViewLayer *view_layer, Object *o
for (base = FIRSTBASE(view_layer); base; base = base->next) {
Object *ob = base->object;
- if ((((base->flag & BASE_VISIBLED) == 0) && BKE_object_is_child_recursive(ob_parent, ob))) {
+ if ((((base->flag & BASE_VISIBLE) == 0) && BKE_object_is_child_recursive(ob_parent, ob))) {
ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
}
}
@@ -149,7 +245,7 @@ static eOLDrawState tree_element_set_active_object(
Scene *sce;
Base *base;
Object *ob = NULL;
-
+
/* if id is not object, we search back */
if (te->idcode == ID_OB) {
ob = (Object *)tselem->id;
@@ -163,27 +259,50 @@ static eOLDrawState tree_element_set_active_object(
if (ob == NULL) {
return OL_DRAWSEL_NONE;
}
-
+
sce = (Scene *)outliner_search_back(soops, te, ID_SCE);
if (sce && scene != sce) {
WM_window_change_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
+ else
ED_object_base_select(base, BA_SELECT);
}
else {
/* deleselect all */
- BKE_view_layer_base_deselect_all(view_layer);
+
+ /* 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);
}
@@ -194,13 +313,14 @@ static eOLDrawState tree_element_set_active_object(
if (set != OL_SETSEL_NONE) {
ED_object_base_activate(C, base); /* adds notifier */
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
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 | EM_WAITCURSOR);
+ }
}
-
- if (ob != OBEDIT_FROM_VIEW_LAYER(view_layer))
- ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR | EM_DO_UNDO);
-
return OL_DRAWSEL_NORMAL;
}
@@ -210,14 +330,14 @@ static eOLDrawState tree_element_active_material(
{
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) {
@@ -262,21 +382,21 @@ static eOLDrawState tree_element_active_lamp(
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;
}
@@ -300,21 +420,21 @@ static eOLDrawState tree_element_active_world(
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_change_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);
@@ -330,7 +450,7 @@ 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) {
@@ -353,7 +473,7 @@ 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;
@@ -376,10 +496,10 @@ static eOLDrawState tree_element_active_posechannel(
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) {
bPoseChannel *pchannel;
/* single select forces all other bones to get unselected */
@@ -419,7 +539,7 @@ static eOLDrawState tree_element_active_bone(
{
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);
@@ -432,7 +552,7 @@ static eOLDrawState tree_element_active_bone(
}
}
}
-
+
if (set == OL_SETSEL_EXTEND && (bone->flag & BONE_SELECTED)) {
bone->flag &= ~BONE_SELECTED;
}
@@ -446,13 +566,13 @@ static eOLDrawState tree_element_active_bone(
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;
@@ -528,12 +648,12 @@ static eOLDrawState tree_element_active_modifier(
{
if (set != OL_SETSEL_NONE) {
Object *ob = (Object *)tselem->id;
-
+
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
// XXX extern_set_butspace(F9KEY, 0);
}
-
+
return OL_DRAWSEL_NONE;
}
@@ -542,12 +662,12 @@ static eOLDrawState tree_element_active_psys(
{
if (set != OL_SETSEL_NONE) {
Object *ob = (Object *)tselem->id;
-
+
WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
-
+
// XXX extern_set_butspace(F7KEY, 0);
}
-
+
return OL_DRAWSEL_NONE;
}
@@ -556,11 +676,11 @@ static int tree_element_active_constraint(
{
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);
}
-
+
return OL_DRAWSEL_NONE;
}
@@ -584,16 +704,7 @@ static eOLDrawState tree_element_active_pose(
}
if (set != OL_SETSEL_NONE) {
- if (OBEDIT_FROM_VIEW_LAYER(view_layer)) {
- ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR | EM_DO_UNDO);
- }
-
- if (ob->mode & OB_MODE_POSE) {
- ED_object_posemode_exit(C, ob);
- }
- else {
- ED_object_posemode_enter(C, ob);
- }
+ do_outliner_activate_pose(C, view_layer, base);
}
else {
if (ob->mode & OB_MODE_POSE) {
@@ -668,7 +779,7 @@ 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;
@@ -681,43 +792,42 @@ static eOLDrawState tree_element_active_keymap_item(
return OL_DRAWSEL_NONE;
}
-static eOLDrawState tree_element_active_collection(
- bContext *C, TreeElement *te, TreeStoreElem *tselem, 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);
- /* sometimes the renderlayer has no LayerCollection at all */
- if (active == NULL) {
- return OL_DRAWSEL_NONE;
- }
-
- if ((tselem->type == TSE_SCENE_COLLECTION && active->scene_collection == te->directdata) ||
- (tselem->type == TSE_LAYER_COLLECTION && active == te->directdata))
- {
+ if (active == view_layer->layer_collections.first) {
return OL_DRAWSEL_NORMAL;
}
}
- /* don't allow selecting a scene collection, it can have multiple layer collection
- * instances (which one would the user want to be selected then?) */
- else if (tselem->type == TSE_LAYER_COLLECTION) {
- LayerCollection *layer_collection = te->directdata;
+ 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);
+ }
- switch (layer_collection->scene_collection->type) {
- case COLLECTION_TYPE_NONE:
- case COLLECTION_TYPE_GROUP_INTERNAL:
- {
- ViewLayer *view_layer = BKE_view_layer_find_from_collection(tselem->id, layer_collection);
- const int collection_index = BKE_layer_collection_findindex(view_layer, layer_collection);
+ return OL_DRAWSEL_NONE;
+}
- if (collection_index > -1) {
- view_layer->active_collection = collection_index;
- }
- break;
- }
- default:
- BLI_assert(!"Collection type not fully implemented");
+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);
}
@@ -785,12 +895,7 @@ eOLDrawState tree_element_type_active(
case TSE_CONSTRAINT:
return tree_element_active_constraint(C, scene, view_layer, te, tselem, set);
case TSE_R_LAYER:
- if (soops->outlinevis == SO_SCENES) {
- return active_viewlayer(C, scene, view_layer, te, tselem, set);
- }
- else {
- return OL_DRAWSEL_NONE;
- }
+ return active_viewlayer(C, scene, view_layer, te, tselem, set);
case TSE_POSEGRP:
return tree_element_active_posegroup(C, scene, view_layer, te, tselem, set);
case TSE_SEQUENCE:
@@ -802,9 +907,10 @@ eOLDrawState tree_element_type_active(
case TSE_GP_LAYER:
//return tree_element_active_gplayer(C, scene, s, te, tselem, set);
break;
- case TSE_SCENE_COLLECTION:
+ case TSE_VIEW_COLLECTION_BASE:
+ return tree_element_active_master_collection(C, te, set);
case TSE_LAYER_COLLECTION:
- return tree_element_active_collection(C, te, tselem, set);
+ return tree_element_active_layer_collection(C, te, set);
}
return OL_DRAWSEL_NONE;
}
@@ -822,10 +928,18 @@ static void do_outliner_item_activate_tree_element(
TreeElement *te, TreeStoreElem *tselem,
const bool extend, const bool recursive)
{
- /* always makes active object, except for some specific types.
- * 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). */
- if (!ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP, TSE_EBONE, TSE_LAYER_COLLECTION)) {
+ /* 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,
@@ -840,29 +954,33 @@ static void do_outliner_item_activate_tree_element(
}
}
else if (te->idcode == ID_GR) {
- Group *gr = (Group *)tselem->id;
+ Collection *gr = (Collection *)tselem->id;
if (extend) {
int sel = BA_SELECT;
- FOREACH_GROUP_BASE_BEGIN(gr, base)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(gr, object)
{
- if (base->flag & BASE_SELECTED) {
+ Base *base = BKE_view_layer_base_find(view_layer, object);
+ if (base && (base->flag & BASE_SELECTED)) {
sel = BA_DESELECT;
break;
}
}
- FOREACH_GROUP_BASE_END
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- FOREACH_GROUP_OBJECT_BEGIN(gr, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(gr, object)
{
- ED_object_base_select(BKE_view_layer_base_find(view_layer, object), sel);
+ Base *base = BKE_view_layer_base_find(view_layer, object);
+ if (base) {
+ ED_object_base_select(base, sel);
+ }
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
else {
BKE_view_layer_base_deselect_all(view_layer);
- FOREACH_GROUP_OBJECT_BEGIN(gr, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(gr, object)
{
Base *base = BKE_view_layer_base_find(view_layer, object);
/* Object may not be in this scene */
@@ -872,13 +990,20 @@ static void do_outliner_item_activate_tree_element(
}
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
-
+
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
- else if (ELEM(te->idcode, ID_ME, ID_CU, ID_MB, ID_LT, ID_AR)) {
- WM_operator_name_call(C, "OBJECT_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
+ 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);
+ }
+ }
}
else { // rest of types
tree_element_active(C, scene, view_layer, soops, te, OL_SETSEL_NORMAL, false);
@@ -928,7 +1053,7 @@ static bool outliner_item_is_co_within_close_toggle(TreeElement *te, float view_
static bool outliner_is_co_within_restrict_columns(const SpaceOops *soops, const ARegion *ar, float view_co_x)
{
- return ((soops->outlinevis != SO_DATABLOCKS) &&
+ return ((soops->outlinevis != SO_DATA_API) &&
!(soops->flag & SO_HIDE_RESTRICTCOLS) &&
(view_co_x > ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX));
}
@@ -995,12 +1120,13 @@ int outliner_item_do_activate_from_cursor(
}
if (changed) {
- if (!rebuild_tree) {
- /* only needs to redraw, no rebuild */
- soops->storeflag |= SO_TREESTORE_REDRAW;
+ if (rebuild_tree) {
+ ED_region_tag_redraw(ar);
+ }
+ else {
+ ED_region_tag_redraw_no_rebuild(ar);
}
ED_undo_push(C, "Outliner selection change");
- ED_region_tag_redraw(ar);
}
return OPERATOR_FINISHED;
@@ -1016,14 +1142,14 @@ static int outliner_item_activate_invoke(bContext *C, wmOperator *op, const wmEv
void OUTLINER_OT_item_activate(wmOperatorType *ot)
{
- ot->name = "Activate Item";
+ ot->name = "Select";
ot->idname = "OUTLINER_OT_item_activate";
- ot->description = "Handle mouse clicks to activate/select items";
-
+ ot->description = "Handle mouse clicks to select and activate items";
+
ot->invoke = outliner_item_activate_invoke;
-
+
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");
}
@@ -1068,6 +1194,7 @@ static int outliner_border_select_exec(bContext *C, wmOperator *op)
outliner_item_border_select(scene, &rectf, te, select);
}
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
ED_region_tag_redraw(ar);
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index ab08d6a0025..b2ac4afc112 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -51,10 +51,10 @@
#include "BLI_utildefines.h"
#include "BKE_animsys.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_constraint.h"
#include "BKE_fcurve.h"
-#include "BKE_group.h"
#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_override.h"
@@ -101,11 +101,12 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb,
{
TreeElement *te;
TreeStoreElem *tselem;
-
+
for (te = lb->first; te; te = te->next) {
tselem = TREESTORE(te);
if (tselem->flag & TSE_SELECTED) {
- if (tselem->type) {
+ /* 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)
@@ -120,7 +121,7 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb,
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:
@@ -129,6 +130,9 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb,
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;
}
}
@@ -154,7 +158,7 @@ static void unlink_material_cb(
{
Material **matar = NULL;
int a, totcol = 0;
-
+
if (GS(tsep->id->name) == ID_OB) {
Object *ob = (Object *)tsep->id;
totcol = ob->totcol;
@@ -195,7 +199,7 @@ static void unlink_texture_cb(
{
MTex **mtex = NULL;
int a;
-
+
if (GS(tsep->id->name) == ID_LS) {
FreestyleLineStyle *ls = (FreestyleLineStyle *)tsep->id;
mtex = ls->mtex;
@@ -214,21 +218,59 @@ static void unlink_texture_cb(
}
}
-static void unlink_group_cb(
+static void unlink_collection_cb(
bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
TreeStoreElem *tsep, TreeStoreElem *tselem, void *UNUSED(user_data))
{
- Group *group = (Group *)tselem->id;
-
+ 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->dup_group = NULL;
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
+ 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, DEG_TAG_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, DEG_TAG_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
}
}
- else {
- Main *bmain = CTX_data_main(C);
- BKE_libblock_delete(bmain, group);
+}
+
+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, DEG_TAG_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, DEG_TAG_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+ }
}
}
@@ -238,7 +280,7 @@ static void unlink_world_cb(
{
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;
@@ -251,11 +293,11 @@ static void outliner_do_libdata_operation(
{
TreeElement *te;
TreeStoreElem *tselem;
-
+
for (te = lb->first; te; te = te->next) {
tselem = TREESTORE(te);
if (tselem->flag & TSE_SELECTED) {
- if (tselem->type == 0) {
+ 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);
}
@@ -359,7 +401,7 @@ static void object_select_cb(
Object *ob = (Object *)tselem->id;
Base *base = BKE_view_layer_base_find(view_layer, ob);
- if (base && ((base->flag & BASE_VISIBLED) != 0)) {
+ if (base && ((base->flag & BASE_VISIBLE) != 0)) {
base->flag |= BASE_SELECTED;
}
}
@@ -408,7 +450,7 @@ static void object_delete_cb(
// check also library later
if (ob == CTX_data_edit_object(C)) {
- ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR | EM_DO_UNDO);
+ ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR);
}
ED_object_base_free_and_unlink(CTX_data_main(C), scene, ob);
/* leave for ED_outliner_id_unref to handle */
@@ -461,7 +503,7 @@ static void id_fake_user_set_cb(
TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
{
ID *id = tselem->id;
-
+
id_fake_user_set(id);
}
@@ -470,7 +512,7 @@ static void id_fake_user_clear_cb(
TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
{
ID *id = tselem->id;
-
+
id_fake_user_clear(id);
}
@@ -488,15 +530,15 @@ static void singleuser_action_cb(
TreeStoreElem *tsep, TreeStoreElem *tselem, void *UNUSED(user_data))
{
ID *id = tselem->id;
-
+
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");
-
+
id_single_user(C, id, &ptr, prop);
}
}
@@ -506,54 +548,18 @@ static void singleuser_world_cb(
TreeStoreElem *tsep, TreeStoreElem *tselem, void *UNUSED(user_data))
{
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;
-
+
RNA_id_pointer_create(&parscene->id, &ptr);
prop = RNA_struct_find_property(&ptr, "world");
-
- id_single_user(C, id, &ptr, prop);
- }
-}
-static void group_linkobs2scene_cb(
- bContext *C, ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- SceneCollection *sc = CTX_data_scene_collection(C);
- Group *group = (Group *)tselem->id;
- Base *base;
-
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
- {
- base = BKE_view_layer_base_find(view_layer, object);
- if (!base) {
- /* link to scene */
- BKE_collection_object_add(&scene->id, sc, object);
- base = BKE_view_layer_base_find(view_layer, object);
- id_us_plus(&object->id);
- }
-
- base->flag |= BASE_SELECTED;
+ id_single_user(C, id, &ptr, prop);
}
- FOREACH_GROUP_OBJECT_END;
-}
-
-static void group_instance_cb(
- bContext *C, ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- Group *group = (Group *)tselem->id;
-
- Object *ob = ED_object_add_type(C, OB_EMPTY, group->id.name + 2, scene->cursor.location, NULL, false, scene->layact);
- ob->dup_group = group;
- ob->transflag |= OB_DUPLIGROUP;
- id_lib_extern(&group->id);
}
/**
@@ -564,7 +570,7 @@ void outliner_do_object_operation_ex(
outliner_operation_cb operation_cb, bool select_recurse)
{
TreeElement *te;
-
+
for (te = lb->first; te; te = te->next) {
TreeStoreElem *tselem = TREESTORE(te);
bool select_handled = false;
@@ -618,7 +624,7 @@ static void cleardrivers_animdata_cb(int UNUSED(event), TreeElement *UNUSED(te),
TreeStoreElem *tselem, void *UNUSED(arg))
{
IdAdtTemplate *iat = (IdAdtTemplate *)tselem->id;
-
+
/* just free drivers - stored as a list of F-Curves */
free_fcurves(&iat->adt->drivers);
}
@@ -628,11 +634,11 @@ static void refreshdrivers_animdata_cb(int UNUSED(event), TreeElement *UNUSED(te
{
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;
-
+
if (fcu->driver)
fcu->driver->flag &= ~DRIVER_FLAG_INVALID;
}
@@ -660,21 +666,10 @@ typedef enum eOutliner_PropModifierOps {
OL_MODIFIER_OP_DELETE
} eOutliner_PropModifierOps;
-typedef enum eOutliner_PropCollectionOps {
- OL_COLLECTION_OP_OBJECTS_ADD = 1,
- OL_COLLECTION_OP_OBJECTS_REMOVE,
- OL_COLLECTION_OP_OBJECTS_SELECT,
- OL_COLLECTION_OP_COLLECTION_NEW,
- OL_COLLECTION_OP_COLLECTION_COPY,
- OL_COLLECTION_OP_COLLECTION_DEL,
- OL_COLLECTION_OP_COLLECTION_UNLINK,
- OL_COLLECTION_OP_GROUP_CREATE,
-} eOutliner_PropCollectionOps;
-
static void pchan_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *UNUSED(arg))
{
bPoseChannel *pchan = (bPoseChannel *)te->directdata;
-
+
if (event == OL_DOP_SELECT)
pchan->bone->flag |= BONE_SELECTED;
else if (event == OL_DOP_DESELECT)
@@ -690,7 +685,7 @@ static void pchan_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem),
static void bone_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *UNUSED(arg))
{
Bone *bone = (Bone *)te->directdata;
-
+
if (event == OL_DOP_SELECT)
bone->flag |= BONE_SELECTED;
else if (event == OL_DOP_DESELECT)
@@ -706,7 +701,7 @@ static void bone_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), v
static void ebone_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *UNUSED(arg))
{
EditBone *ebone = (EditBone *)te->directdata;
-
+
if (event == OL_DOP_SELECT)
ebone->flag |= BONE_SELECTED;
else if (event == OL_DOP_DESELECT)
@@ -736,7 +731,7 @@ static void sequence_cb(int event, TreeElement *te, TreeStoreElem *tselem, void
static void gp_layer_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *UNUSED(arg))
{
bGPDlayer *gpl = (bGPDlayer *)te->directdata;
-
+
if (event == OL_DOP_SELECT)
gpl->flag |= GP_LAYER_SELECT;
else if (event == OL_DOP_DESELECT)
@@ -762,18 +757,19 @@ static void data_select_linked_cb(int event, TreeElement *te, TreeStoreElem *UNU
static void constraint_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *C_v)
{
bContext *C = C_v;
+ Main *bmain = CTX_data_main(C);
SpaceOops *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(ob);
+ 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(ob);
+ ED_object_constraint_update(bmain, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
}
else if (event == OL_CONSTRAINTOP_DELETE) {
@@ -789,7 +785,7 @@ static void constraint_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tsel
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);
- ED_object_constraint_update(ob); /* needed to set the flags on posebones correctly */
+ ED_object_constraint_update(bmain, ob); /* needed to set the flags on posebones correctly */
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
te->store_elem->flag &= ~TSE_SELECTED;
}
@@ -821,97 +817,13 @@ static void modifier_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem
}
}
-static void collection_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *Carg)
-{
- bContext *C = (bContext *)Carg;
- Scene *scene = CTX_data_scene(C);
- LayerCollection *lc = te->directdata;
- ID *id = te->store_elem->id;
- SceneCollection *sc = lc->scene_collection;
-
- if (event == OL_COLLECTION_OP_OBJECTS_ADD) {
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- BKE_collection_object_add(id, sc, ob);
- }
- CTX_DATA_END;
-
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- }
- else if (event == OL_COLLECTION_OP_OBJECTS_REMOVE) {
- Main *bmain = CTX_data_main(C);
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- BKE_collection_object_remove(bmain, id, sc, ob, true);
- }
- CTX_DATA_END;
-
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- te->store_elem->flag &= ~TSE_SELECTED;
- }
- else if (event == OL_COLLECTION_OP_OBJECTS_SELECT) {
- BKE_layer_collection_objects_select(lc);
- WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
- }
- else if (event == OL_COLLECTION_OP_COLLECTION_NEW) {
- if (GS(id->name) == ID_GR) {
- BKE_collection_add(id, sc, COLLECTION_TYPE_GROUP_INTERNAL, NULL);
- }
- else {
- BLI_assert(GS(id->name) == ID_SCE);
- BKE_collection_add(id, sc, COLLECTION_TYPE_NONE, NULL);
- }
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- }
- else if (event == OL_COLLECTION_OP_COLLECTION_COPY) {
- BKE_layer_collection_duplicate(id, lc);
- DEG_relations_tag_update(CTX_data_main(C));
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- }
- else if (event == OL_COLLECTION_OP_COLLECTION_UNLINK) {
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- if (BLI_findindex(&view_layer->layer_collections, lc) == -1) {
- /* we can't unlink if the layer collection wasn't directly linked */
- TODO_LAYER_OPERATORS; /* this shouldn't be in the menu in those cases */
- }
- else {
- BKE_collection_unlink(view_layer, lc);
- DEG_relations_tag_update(CTX_data_main(C));
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- }
- }
- else if (event == OL_COLLECTION_OP_COLLECTION_DEL) {
- if (BKE_collection_remove(id, sc)) {
- DEG_relations_tag_update(CTX_data_main(C));
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- }
- else {
- /* we can't remove the master collection */
- TODO_LAYER_OPERATORS; /* this shouldn't be in the menu in those cases */
- }
- }
- else if (event == OL_COLLECTION_OP_GROUP_CREATE) {
- Main *bmain = CTX_data_main(C);
- BKE_collection_group_create(bmain, scene, lc);
- DEG_relations_tag_update(bmain);
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(&scene->id, 0);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- }
- else {
- BLI_assert(!"Collection operation not fully implemented!");
- }
-}
-
static void outliner_do_data_operation(SpaceOops *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) {
@@ -977,7 +889,7 @@ static void object_delete_hierarchy_cb(
/* Check also library later. */
for (; obedit && (obedit != base->object); obedit = obedit->parent);
if (obedit == base->object) {
- ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR | EM_DO_UNDO);
+ ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR);
}
outline_delete_hierarchy(C, reports, scene, base);
@@ -988,6 +900,7 @@ static void object_delete_hierarchy_cb(
#endif
}
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
}
@@ -1005,6 +918,8 @@ enum {
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[] = {
@@ -1016,6 +931,8 @@ static const EnumPropertyItem prop_object_op_types[] = {
{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}
};
@@ -1027,11 +944,11 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
SpaceOops *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) {
@@ -1040,8 +957,9 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
if (scene != sce) {
WM_window_change_active_scene(bmain, C, win, sce);
}
-
+
str = "Select Objects";
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
else if (event == OL_OP_SELECT_HIERARCHY) {
@@ -1051,11 +969,13 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
WM_window_change_active_scene(bmain, C, win, sce);
}
str = "Select Object Hierarchy";
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
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, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
else if (event == OL_OP_DELETE) {
@@ -1070,6 +990,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
DEG_relations_tag_update(bmain);
str = "Delete Objects";
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
}
else if (event == OL_OP_DELETE_HIERARCHY) {
@@ -1080,6 +1001,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
DEG_relations_tag_update(bmain);
str = "Delete Object Hierarchy";
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
}
else if (event == OL_OP_REMAP) {
@@ -1094,13 +1016,21 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
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;
}
@@ -1111,12 +1041,12 @@ void OUTLINER_OT_object_operation(wmOperatorType *ot)
ot->name = "Outliner Object Operation";
ot->idname = "OUTLINER_OT_object_operation";
ot->description = "";
-
+
/* callbacks */
ot->invoke = WM_menu_invoke;
ot->exec = outliner_object_operation_exec;
ot->poll = ED_operator_outliner_active;
-
+
ot->flag = 0;
ot->prop = RNA_def_enum(ot->srna, "type", prop_object_op_types, 0, "Object Operation", "");
@@ -1124,116 +1054,16 @@ void OUTLINER_OT_object_operation(wmOperatorType *ot)
/* **************************************** */
-typedef enum eOutliner_PropGroupOps {
- OL_GROUPOP_UNLINK = 1,
- OL_GROUPOP_LOCAL,
- OL_GROUPOP_STATIC_OVERRIDE,
- OL_GROUPOP_LINK,
- OL_GROUPOP_DELETE,
- OL_GROUPOP_REMAP,
- OL_GROUPOP_INSTANCE,
- OL_GROUPOP_TOGVIS,
- OL_GROUPOP_TOGSEL,
- OL_GROUPOP_TOGREN,
- OL_GROUPOP_RENAME,
-} eOutliner_PropGroupOps;
-
-static const EnumPropertyItem prop_group_op_types[] = {
- {OL_GROUPOP_UNLINK, "UNLINK", 0, "Unlink Group", ""},
- {OL_GROUPOP_LOCAL, "LOCAL", 0, "Make Local Group", ""},
- {OL_GROUPOP_STATIC_OVERRIDE, "STATIC_OVERRIDE",
- 0, "Add Static Override", "Add a local static override of that group"},
- {OL_GROUPOP_LINK, "LINK", 0, "Link Group Objects to Scene", ""},
- {OL_GROUPOP_DELETE, "DELETE", 0, "Delete Group", ""},
- {OL_GROUPOP_REMAP, "REMAP", 0, "Remap Users",
- "Make all users of selected data-blocks to use instead current (clicked) one"},
- {OL_GROUPOP_INSTANCE, "INSTANCE", 0, "Instance Groups in Scene", ""},
- {OL_GROUPOP_TOGVIS, "TOGVIS", 0, "Toggle Visible Group", ""},
- {OL_GROUPOP_TOGSEL, "TOGSEL", 0, "Toggle Selectable", ""},
- {OL_GROUPOP_TOGREN, "TOGREN", 0, "Toggle Renderable", ""},
- {OL_GROUPOP_RENAME, "RENAME", 0, "Rename", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
-static int outliner_group_operation_exec(bContext *C, wmOperator *op)
-{
- Scene *scene = CTX_data_scene(C);
- SpaceOops *soops = CTX_wm_space_outliner(C);
- int event;
-
- /* check for invalid states */
- if (soops == NULL)
- return OPERATOR_CANCELLED;
-
- event = RNA_enum_get(op->ptr, "type");
-
- switch (event) {
- case OL_GROUPOP_UNLINK:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, unlink_group_cb, NULL);
- break;
- case OL_GROUPOP_LOCAL:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_local_cb, NULL);
- break;
- case OL_GROUPOP_STATIC_OVERRIDE:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_static_override_cb, NULL);
- break;
- case OL_GROUPOP_LINK:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_linkobs2scene_cb, NULL);
- break;
- case OL_GROUPOP_INSTANCE:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_instance_cb, NULL);
- /* works without this except if you try render right after, see: 22027 */
- DEG_relations_tag_update(CTX_data_main(C));
- break;
- case OL_GROUPOP_DELETE:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_delete_cb, NULL);
- break;
- case OL_GROUPOP_REMAP:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL);
- break;
- case OL_GROUPOP_RENAME:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb, NULL);
- break;
- default:
- BLI_assert(0);
- }
-
- ED_undo_push(C, prop_group_op_types[event - 1].name);
- WM_event_add_notifier(C, NC_GROUP, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-
-void OUTLINER_OT_group_operation(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Outliner Group Operation";
- ot->idname = "OUTLINER_OT_group_operation";
- ot->description = "";
-
- /* callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = outliner_group_operation_exec;
- ot->poll = ED_operator_outliner_active;
-
- ot->flag = 0;
-
- ot->prop = RNA_def_enum(ot->srna, "type", prop_group_op_types, 0, "Group Operation", "");
-}
-
-/* **************************************** */
-
typedef enum eOutlinerIdOpTypes {
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_FAKE_ADD,
OUTLINER_IDOP_FAKE_CLEAR,
OUTLINER_IDOP_RENAME,
@@ -1265,44 +1095,58 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
SpaceOops *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;
@@ -1329,18 +1173,18 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
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;
@@ -1367,7 +1211,7 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
{
/* 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;
@@ -1376,7 +1220,7 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
{
/* 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;
@@ -1385,7 +1229,7 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
{
/* 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;
@@ -1394,18 +1238,18 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
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
+
+ // 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;
}
@@ -1416,14 +1260,14 @@ void OUTLINER_OT_id_operation(wmOperatorType *ot)
ot->name = "Outliner ID data Operation";
ot->idname = "OUTLINER_OT_id_operation";
ot->description = "";
-
+
/* callbacks */
ot->invoke = WM_menu_invoke;
ot->exec = outliner_id_operation_exec;
ot->poll = ED_operator_outliner_active;
-
+
ot->flag = 0;
-
+
ot->prop = RNA_def_enum(ot->srna, "type", prop_id_op_types, 0, "ID data Operation", "");
}
@@ -1527,7 +1371,7 @@ static void outliner_do_id_set_operation(SpaceOops *soops, int type, ListBase *l
{
TreeElement *te;
TreeStoreElem *tselem;
-
+
for (te = lb->first; te; te = te->next) {
tselem = TREESTORE(te);
if (tselem->flag & TSE_SELECTED) {
@@ -1547,12 +1391,12 @@ static void outliner_do_id_set_operation(SpaceOops *soops, int type, ListBase *l
static void actionset_id_cb(TreeElement *UNUSED(te), TreeStoreElem *tselem, TreeStoreElem *tsep, ID *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,
+ /* 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)) {
@@ -1566,17 +1410,17 @@ static int outliner_action_set_exec(bContext *C, wmOperator *op)
{
SpaceOops *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)->action, RNA_enum_get(op->ptr, "action"));
-
+
if (act == NULL) {
BKE_report(op->reports, RPT_ERROR, "No valid action to add");
return OPERATOR_CANCELLED;
@@ -1589,7 +1433,7 @@ static int outliner_action_set_exec(bContext *C, wmOperator *op)
"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);
@@ -1597,11 +1441,11 @@ static int outliner_action_set_exec(bContext *C, wmOperator *op)
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;
}
@@ -1614,15 +1458,15 @@ void OUTLINER_OT_action_set(wmOperatorType *ot)
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;
-
+
/* 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", "");
@@ -1635,15 +1479,15 @@ void OUTLINER_OT_action_set(wmOperatorType *ot)
typedef enum eOutliner_AnimDataOps {
OUTLINER_ANIMOP_INVALID = 0,
-
+
OUTLINER_ANIMOP_CLEAR_ADT,
-
+
OUTLINER_ANIMOP_SET_ACT,
OUTLINER_ANIMOP_CLEAR_ACT,
-
+
OUTLINER_ANIMOP_REFRESH_DRV,
OUTLINER_ANIMOP_CLEAR_DRV
-
+
//OUTLINER_ANIMOP_COPY_DRIVERS,
//OUTLINER_ANIMOP_PASTE_DRIVERS
} eOutliner_AnimDataOps;
@@ -1665,66 +1509,66 @@ static int outliner_animdata_operation_exec(bContext *C, wmOperator *op)
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;
-
+
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;
-
+
/* 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;
-
+
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);
-
+
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);
-
+
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);
-
+
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, NULL);
ED_undo_push(C, "Clear Drivers");
updateDeps = 1;
break;
-
+
default: // invalid
break;
}
-
+
/* update dependencies */
if (updateDeps) {
/* rebuild depsgraph for the new deps */
DEG_relations_tag_update(CTX_data_main(C));
}
-
+
return OPERATOR_FINISHED;
}
@@ -1735,22 +1579,22 @@ void OUTLINER_OT_animdata_operation(wmOperatorType *ot)
ot->name = "Outliner Animation Data Operation";
ot->idname = "OUTLINER_OT_animdata_operation";
ot->description = "";
-
+
/* callbacks */
ot->invoke = WM_menu_invoke;
ot->exec = outliner_animdata_operation_exec;
ot->poll = ED_operator_outliner_active;
-
+
ot->flag = 0;
-
+
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_RESTRICT_VIEW_OFF, "Enable", ""},
- {OL_CONSTRAINTOP_DISABLE, "DISABLE", ICON_RESTRICT_VIEW_ON, "Disable", ""},
+ {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}
};
@@ -1840,84 +1684,6 @@ void OUTLINER_OT_modifier_operation(wmOperatorType *ot)
/* ******************** */
-static EnumPropertyItem prop_collection_op_types[] = {
- {OL_COLLECTION_OP_OBJECTS_ADD, "OBJECTS_ADD", ICON_ZOOMIN, "Add Selected", "Add selected objects to collection"},
- {OL_COLLECTION_OP_OBJECTS_REMOVE, "OBJECTS_REMOVE", ICON_X, "Remove Selected", "Remove selected objects from collection"},
- {OL_COLLECTION_OP_OBJECTS_SELECT, "OBJECTS_SELECT", ICON_RESTRICT_SELECT_OFF, "Select Objects", "Select collection objects"},
- {OL_COLLECTION_OP_COLLECTION_NEW, "COLLECTION_NEW", ICON_NEW, "New Collection", "Add a new nested collection"},
- {OL_COLLECTION_OP_COLLECTION_COPY, "COLLECTION_DUPLI", ICON_NONE, "Duplicate Collection", "Duplicate the collection"},
- {OL_COLLECTION_OP_COLLECTION_UNLINK, "COLLECTION_UNLINK", ICON_UNLINKED, "Unlink", "Unlink collection"},
- {OL_COLLECTION_OP_COLLECTION_DEL, "COLLECTION_DEL", ICON_X, "Delete Collection", "Delete the collection"},
- {OL_COLLECTION_OP_GROUP_CREATE, "GROUP_CREATE", ICON_GROUP, "Create Group", "Turn the collection into a group collection"},
- {0, NULL, 0, NULL, NULL}
-};
-
-static int outliner_collection_operation_exec(bContext *C, wmOperator *op)
-{
- SpaceOops *soops = CTX_wm_space_outliner(C);
- int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
- eOutliner_PropCollectionOps event;
-
- 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, collection_cb, C);
-
- outliner_cleanup_tree(soops);
-
- ED_undo_push(C, "Collection operation");
-
- return OPERATOR_FINISHED;
-}
-
-static int outliner_collection_operation_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
-{
- SpaceOops *soops = CTX_wm_space_outliner(C);
- wmOperatorType *ot = op->type;
- EnumPropertyItem *prop = &prop_collection_op_types[0];
-
- uiPopupMenu *pup = UI_popup_menu_begin(C, "Collection", ICON_NONE);
- uiLayout *layout = UI_popup_menu_layout(pup);
-
- for (int i = 0; i < (ARRAY_SIZE(prop_collection_op_types) - 1); i++, prop++) {
- if (soops->outlinevis != SO_GROUPS ||
- !ELEM(prop->value,
- OL_COLLECTION_OP_OBJECTS_SELECT,
- OL_COLLECTION_OP_COLLECTION_UNLINK,
- OL_COLLECTION_OP_GROUP_CREATE))
- {
- uiItemEnumO_ptr(layout, ot, NULL, prop->icon, "type", prop->value);
- }
- }
-
- UI_popup_menu_end(C, pup);
-
- return OPERATOR_INTERFACE;
-}
-
-void OUTLINER_OT_collection_operation(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Outliner Collection Operation";
- ot->idname = "OUTLINER_OT_collection_operation";
- ot->description = "";
-
- /* callbacks */
- ot->invoke = outliner_collection_operation_invoke;
- ot->exec = outliner_collection_operation_exec;
- ot->poll = ED_operator_outliner_active;
-
- ot->flag = 0;
-
- prop = RNA_def_enum(ot->srna, "type", prop_collection_op_types, OL_COLLECTION_OP_OBJECTS_ADD, "Collection Operation", "");
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
-}
-
-/* ******************** */
-
// XXX: select linked is for RNA structs only
static const EnumPropertyItem prop_data_op_types[] = {
{OL_DOP_SELECT, "SELECT", 0, "Select", ""},
@@ -1933,14 +1699,14 @@ static int outliner_data_operation_exec(bContext *C, wmOperator *op)
SpaceOops *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:
{
@@ -1992,7 +1758,7 @@ static int outliner_data_operation_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_WARNING, "Not yet implemented");
break;
}
-
+
return OPERATOR_FINISHED;
}
@@ -2003,14 +1769,14 @@ void OUTLINER_OT_data_operation(wmOperatorType *ot)
ot->name = "Outliner Data Operation";
ot->idname = "OUTLINER_OT_data_operation";
ot->description = "";
-
+
/* callbacks */
ot->invoke = WM_menu_invoke;
ot->exec = outliner_data_operation_exec;
ot->poll = ED_operator_outliner_active;
-
+
ot->flag = 0;
-
+
ot->prop = RNA_def_enum(ot->srna, "type", prop_data_op_types, 0, "Data Operation", "");
}
@@ -2022,25 +1788,26 @@ static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOops *soop
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_has_one_flag(&soops->tree, TSE_SELECTED, 1))
outliner_set_flag(&soops->tree, TSE_SELECTED, 0);
-
+
tselem->flag |= TSE_SELECTED;
- /* redraw, same as outliner_select function */
- soops->storeflag |= SO_TREESTORE_REDRAW;
- ED_region_tag_redraw(ar);
+
+ /* 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");
@@ -2050,7 +1817,7 @@ static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOops *soop
}
}
else if (objectlevel) {
- WM_menu_name_call(C, "OUTLINER_MT_context_object", WM_OP_INVOKE_REGION_WIN);
+ WM_menu_name_call(C, "OUTLINER_MT_object", WM_OP_INVOKE_REGION_WIN);
}
else if (idlevel) {
if (idlevel == -1 || datalevel) {
@@ -2059,7 +1826,7 @@ static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOops *soop
else {
switch (idlevel) {
case ID_GR:
- WM_operator_name_call(C, "OUTLINER_OT_group_operation", WM_OP_INVOKE_REGION_WIN, NULL);
+ WM_menu_name_call(C, "OUTLINER_MT_collection", WM_OP_INVOKE_REGION_WIN);
break;
case ID_LI:
WM_operator_name_call(C, "OUTLINER_OT_lib_operation", WM_OP_INVOKE_REGION_WIN, NULL);
@@ -2080,8 +1847,11 @@ static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOops *soop
else if (datalevel == TSE_DRIVER_BASE) {
/* do nothing... no special ops needed yet */
}
- else if (ELEM(datalevel, TSE_R_LAYER_BASE, TSE_R_LAYER)) {
- /*WM_operator_name_call(C, "OUTLINER_OT_renderdata_operation", WM_OP_INVOKE_REGION_WIN, NULL)*/
+ else if (datalevel == TSE_LAYER_COLLECTION) {
+ WM_menu_name_call(C, "OUTLINER_MT_collection", WM_OP_INVOKE_REGION_WIN);
+ }
+ 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);
}
else if (datalevel == TSE_ID_BASE) {
/* do nothing... there are no ops needed here yet */
@@ -2092,21 +1862,15 @@ static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOops *soop
else if (datalevel == TSE_MODIFIER) {
WM_operator_name_call(C, "OUTLINER_OT_modifier_operation", WM_OP_INVOKE_REGION_WIN, NULL);
}
- else if (datalevel == TSE_LAYER_COLLECTION) {
- WM_operator_name_call(C, "OUTLINER_OT_collection_operation", WM_OP_INVOKE_REGION_WIN, NULL);
- }
- else if (datalevel == TSE_SCENE_COLLECTION) {
- WM_menu_name_call(C, "OUTLINER_MT_context_scene_collection", WM_OP_INVOKE_REGION_WIN);
- }
else {
WM_operator_name_call(C, "OUTLINER_OT_data_operation", WM_OP_INVOKE_REGION_WIN, NULL);
}
}
}
-
+
return 1;
}
-
+
for (te = te->subtree.first; te; te = te->next) {
if (do_outliner_operation_event(C, ar, soops, te, mval))
return 1;
@@ -2122,31 +1886,40 @@ static int outliner_operation(bContext *C, wmOperator *UNUSED(op), const wmEvent
uiBut *but = UI_context_active_but_get(C);
TreeElement *te;
float fmval[2];
+ bool found = false;
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]);
-
+
for (te = soops->tree.first; te; te = te->next) {
if (do_outliner_operation_event(C, ar, soops, te, fmval)) {
+ found = true;
break;
}
}
-
+
+ if (!found) {
+ /* 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;
}
/* Menu only! Calls other operators */
void OUTLINER_OT_operation(wmOperatorType *ot)
{
- ot->name = "Execute Operation";
+ ot->name = "Context Menu";
ot->idname = "OUTLINER_OT_operation";
ot->description = "Context menu for item operations";
-
+
ot->invoke = outliner_operation;
-
+
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 d1195621138..9f6c944c914 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -28,7 +28,7 @@
/** \file blender/editors/space_outliner/outliner_tree.c
* \ingroup spoutliner
*/
-
+
#include <math.h>
#include <string.h>
@@ -91,14 +91,8 @@
#endif
/* prototypes */
-static void outliner_add_layer_collections_recursive(
- SpaceOops *soops, ListBase *tree, ID *id, ListBase *layer_collections, TreeElement *parent_ten,
- const bool show_objects);
-static TreeElement *outliner_add_scene_collection_recursive(
- SpaceOops *soops, ListBase *tree, Scene *scene, SceneCollection *scene_collection, TreeElement *parent_ten);
-static void outliner_add_view_layer(
- SpaceOops *soops, ListBase *tree, TreeElement *parent,
- Scene *scene, ViewLayer *layer, const bool show_objects);
+static TreeElement *outliner_add_collection_recursive(
+ SpaceOops *soops, Collection *collection, TreeElement *ten);
static void outliner_make_object_parent_hierarchy(ListBase *lb);
/* ********************************************************* */
@@ -107,11 +101,11 @@ static void outliner_make_object_parent_hierarchy(ListBase *lb);
static void outliner_storage_cleanup(SpaceOops *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;
@@ -119,7 +113,7 @@ static void outliner_storage_cleanup(SpaceOops *soops)
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) {
@@ -129,7 +123,7 @@ static void outliner_storage_cleanup(SpaceOops *soops)
while ((tselem = BLI_mempool_iterstep(&iter))) {
if (tselem->id == NULL) unused++;
}
-
+
if (unused) {
if (BLI_mempool_len(ts) == unused) {
BLI_mempool_destroy(ts);
@@ -159,17 +153,20 @@ static void outliner_storage_cleanup(SpaceOops *soops)
}
}
}
+ else if (soops->treehash) {
+ BKE_outliner_treehash_clear_used(soops->treehash);
+ }
}
}
static void check_persistent(SpaceOops *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);
@@ -235,7 +232,7 @@ void outliner_free_tree_element(TreeElement *element, ListBase *parent_subtree)
/* ********************************************************* */
/* Prototype, see functions below */
-static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *idv,
+static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *idv,
TreeElement *parent, short type, short index);
/* -------------------------------------------------------- */
@@ -245,11 +242,11 @@ static void outliner_add_bone(SpaceOops *soops, ListBase *lb, ID *id, Bone *curB
TreeElement *parent, int *a)
{
TreeElement *te = outliner_add_element(soops, lb, id, parent, TSE_BONE, *a);
-
+
(*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);
}
@@ -293,33 +290,35 @@ static void outliner_add_line_styles(SpaceOops *soops, ListBase *lb, Scene *sce,
static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *sce, TreeElement *te)
{
/* View layers */
- TreeElement *tenla = outliner_add_element(soops, lb, sce, te, TSE_R_LAYER_BASE, 0);
- tenla->name = IFACE_("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, &tenla->subtree, sce, te, TSE_R_LAYER, 0);
+ TreeElement *tenlay = outliner_add_element(soops, &ten->subtree, sce, te, TSE_R_LAYER, 0);
tenlay->name = view_layer->name;
tenlay->directdata = view_layer;
}
/* Collections */
- outliner_add_scene_collection_recursive(soops, lb, sce, sce->collection, NULL);
+ 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 */
- tenla = outliner_add_element(soops, lb, sce, te, TSE_SCENE_OBJECTS_BASE, 0);
- tenla->name = IFACE_("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, &tenla->subtree, ob, NULL, 0, 0);
+ outliner_add_element(soops, &ten->subtree, ob, NULL, 0, 0);
}
FOREACH_SCENE_OBJECT_END;
- outliner_make_object_parent_hierarchy(&tenla->subtree);
-
+ 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);
-
+
/* Grease Pencil */
outliner_add_element(soops, lb, sce->gpd, te, 0, 0);
}
@@ -329,7 +328,7 @@ TreeTraversalAction outliner_find_selected_objects(TreeElement *te, void *custom
struct ObjectsSelectedData *data = customdata;
TreeStoreElem *tselem = TREESTORE(te);
- if (ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
+ if (outliner_is_collection_tree_element(te)) {
return TRAVERSE_CONTINUE;
}
@@ -348,13 +347,14 @@ TreeTraversalAction outliner_find_selected_objects(TreeElement *te, void *custom
* Instead we move all the selected objects around.
*/
static void outliner_object_reorder(
- Main *bmain, SpaceOops *soops,
+ Main *bmain, Scene *scene,
+ SpaceOops *soops,
TreeElement *insert_element,
TreeElement *insert_handle, TreeElementInsertType action,
const wmEvent *event)
{
- SceneCollection *sc = outliner_scene_collection_from_tree_element(insert_handle);
- SceneCollection *sc_ob_parent = NULL;
+ Collection *collection = outliner_collection_from_tree_element(insert_handle);
+ Collection *collection_ob_parent = NULL;
ID *id = insert_handle->store_elem->id;
BLI_assert(action == TE_INSERT_INTO);
@@ -375,24 +375,24 @@ static void outliner_object_reorder(
Object *ob = (Object *)TREESTORE(ten_selected)->id;
if (is_append) {
- BKE_collection_object_add(id, sc, ob);
+ BKE_collection_object_add(bmain, collection, ob);
continue;
}
- /* Find parent scene-collection of object. */
+ /* Find parent collection of object. */
if (ten_selected->parent) {
for (TreeElement *te_ob_parent = ten_selected->parent; te_ob_parent; te_ob_parent = te_ob_parent->parent) {
- if (ELEM(TREESTORE(te_ob_parent)->type, TSE_SCENE_COLLECTION, TSE_LAYER_COLLECTION)) {
- sc_ob_parent = outliner_scene_collection_from_tree_element(te_ob_parent);
+ if (outliner_is_collection_tree_element(te_ob_parent)) {
+ collection_ob_parent = outliner_collection_from_tree_element(te_ob_parent);
break;
}
}
}
else {
- sc_ob_parent = BKE_collection_master(id);
+ collection_ob_parent = BKE_collection_master(scene);
}
- BKE_collection_object_move(id, sc, sc_ob_parent, ob);
+ BKE_collection_object_move(bmain, scene, collection, collection_ob_parent, ob);
}
BLI_freelistN(&data.objects_selected_array);
@@ -409,8 +409,7 @@ static bool outliner_object_reorder_poll(
const TreeElement *insert_element,
TreeElement **io_insert_handle, TreeElementInsertType *io_action)
{
- TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle);
- if (ELEM(tselem_handle->type, TSE_SCENE_COLLECTION, TSE_LAYER_COLLECTION) &&
+ if (outliner_is_collection_tree_element(*io_insert_handle) &&
(insert_element->parent != *io_insert_handle))
{
*io_action = TE_INSERT_INTO;
@@ -430,39 +429,39 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
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->gpd, te, 0, 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);
@@ -495,7 +494,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
ten = nten;
}
}
-
+
/* Pose Groups */
if (ob->pose->agroups.first) {
bActionGroup *agrp;
@@ -511,11 +510,11 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
}
}
}
-
+
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;
@@ -523,7 +522,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
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);
@@ -538,18 +537,18 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
/* 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);
}
@@ -565,21 +564,21 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
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);
@@ -587,7 +586,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
ten->directdata = defgroup;
}
}
-
+
/* duplicated group */
if (ob->dup_group)
outliner_add_element(soops, &te->subtree, ob->dup_group, te, 0, 0);
@@ -599,7 +598,7 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
{
/* 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:
@@ -621,10 +620,10 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
{
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);
@@ -636,10 +635,10 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
{
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;
@@ -648,10 +647,10 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
{
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;
@@ -659,7 +658,7 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
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;
@@ -667,17 +666,17 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
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;
@@ -695,7 +694,7 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
case ID_LA:
{
Lamp *la = (Lamp *)id;
-
+
if (outliner_animdata_test(la->adt))
outliner_add_element(soops, &te->subtree, la, te, TSE_ANIM_DATA, 0);
break;
@@ -719,7 +718,7 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
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;
@@ -727,7 +726,7 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
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;
@@ -742,14 +741,14 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
{
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;
@@ -789,7 +788,7 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
{
FreestyleLineStyle *linestyle = (FreestyleLineStyle *)id;
int a;
-
+
if (outliner_animdata_test(linestyle->adt))
outliner_add_element(soops, &te->subtree, linestyle, te, TSE_ANIM_DATA, 0);
@@ -804,10 +803,10 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
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.first; gpl; gpl = gpl->next) {
outliner_add_element(soops, &te->subtree, gpl, te, TSE_GP_LAYER, a);
@@ -815,6 +814,14 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
}
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;
}
@@ -828,7 +835,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
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;
@@ -857,11 +864,11 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
/* 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 arays
if (ELEM(type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) {
@@ -876,7 +883,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
else if (type == TSE_GP_LAYER) {
/* pass */
}
- else if (ELEM(type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
+ else if (ELEM(type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
/* pass */
}
else if (type == TSE_ID_BASE) {
@@ -890,41 +897,42 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
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)
+ 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(dvar)
+ DRIVER_TARGETS_USED_LOOPER(dvar)
{
if (lastadded != dtar->id) {
// XXX this lastadded check is rather lame, and also fails quite badly...
@@ -937,23 +945,23 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
}
}
}
-
+
/* 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;
@@ -963,7 +971,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
}
else if (type == TSE_GP_LAYER) {
bGPDlayer *gpl = (bGPDlayer *)idv;
-
+
te->name = gpl->info;
te->directdata = gpl;
}
@@ -1136,31 +1144,31 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
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");
}
@@ -1173,27 +1181,13 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
}
}
}
- else
+ else
te->flag |= TE_LAZY_CLOSED;
}
- if ((type != TSE_LAYER_COLLECTION) && (te->idcode == ID_GR)) {
- Group *group = (Group *)id;
- outliner_add_layer_collections_recursive(soops, &te->subtree, id, &group->view_layer->layer_collections, NULL, true);
- }
-
return te;
}
-/**
- * \note Really only removes \a tselem, not it's TreeElement instance or any children.
- */
-void outliner_remove_treestore_element(SpaceOops *soops, TreeStoreElem *tselem)
-{
- BKE_outliner_treehash_remove_element(soops->treehash, tselem);
- BLI_mempool_free(soops->treestore, tselem);
-}
-
/* ======================================================= */
/* Sequencer mode tree building */
@@ -1256,39 +1250,95 @@ static void outliner_add_seq_dup(SpaceOops *soops, Sequence *seq, TreeElement *t
/* ----------------------------------------------- */
+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";
+}
-static void outliner_add_library_contents(Main *mainvar, SpaceOops *soops, TreeElement *te, Library *lib)
+static bool outliner_library_id_show(Library *lib, ID *id, short filter_id_type)
{
- TreeElement *ten;
+ 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, SpaceOops *soops, ListBase *lb, Library *lib)
+{
+ TreeElement *ten, *tenlib = NULL;
ListBase *lbarray[MAX_LIBARRAY];
int a, tot;
-
- tot = set_listbasepointers(mainvar, lbarray);
+ 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]->first) {
+ 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) {
- ten = outliner_add_element(soops, &te->subtree, lbarray[a], NULL, TSE_ID_BASE, 0);
- ten->directdata = lbarray[a];
-
- ten->name = BKE_idcode_to_name_plural(GS(id->name));
- if (ten->name == NULL)
- ten->name = "UNKNOWN";
-
+ 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 (id->lib == lib)
+ 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, SpaceOops *soops)
@@ -1296,205 +1346,213 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops)
TreeElement *ten;
ListBase *lbarray[MAX_LIBARRAY];
int a, tot;
-
- tot = set_listbasepointers(mainvar, lbarray);
+ 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]->first) {
+ 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 */
- /* TODO's:
- * - Add a parameter to BKE_idcode_to_name_plural to get a sane "user-visible" name instead?
- * - Ensure that this uses nice icons for the datablock type involved instead of the dot?
- */
- ten = outliner_add_element(soops, &soops->tree, lbarray[a], NULL, TSE_ID_BASE, 0);
- ten->directdata = lbarray[a];
-
- ten->name = BKE_idcode_to_name_plural(GS(id->name));
- if (ten->name == NULL)
- ten->name = "UNKNOWN";
-
+ 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->subtree, id, ten, 0, 0);
+ outliner_add_element(soops, (ten) ? &ten->subtree : &soops->tree, id, ten, 0, 0);
}
}
}
}
}
-static void outliner_layer_collections_reorder(
+static void outliner_collections_reorder(
Main *bmain,
- SpaceOops *UNUSED(soops),
- TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action,
+ Scene *UNUSED(scene),
+ SpaceOops *soops,
+ TreeElement *insert_element,
+ TreeElement *insert_handle,
+ TreeElementInsertType action,
const wmEvent *UNUSED(event))
{
- LayerCollection *lc_insert = insert_element->directdata;
- LayerCollection *lc_handle = insert_handle->directdata;
- ID *id = insert_element->store_elem->id;
+ TreeElement *from_parent_te, *to_parent_te;
+ Collection *from_parent, *to_parent;
- if (action == TE_INSERT_BEFORE) {
- BKE_layer_collection_move_above(id, lc_handle, lc_insert);
- }
- else if (action == TE_INSERT_AFTER) {
- BKE_layer_collection_move_below(id, lc_handle, lc_insert);
+ Collection *collection = outliner_collection_from_tree_element(insert_element);
+ Collection *relative = NULL;
+ bool relative_after = false;
+
+ from_parent_te = outliner_find_parent_element(&soops->tree, NULL, insert_element);
+ from_parent = (from_parent_te) ? outliner_collection_from_tree_element(from_parent_te) : NULL;
+
+ if (ELEM(action, TE_INSERT_BEFORE, TE_INSERT_AFTER)) {
+ to_parent_te = outliner_find_parent_element(&soops->tree, NULL, insert_handle);
+ to_parent = (to_parent_te) ? outliner_collection_from_tree_element(to_parent_te) : NULL;
+
+ relative = outliner_collection_from_tree_element(insert_handle);
+ relative_after = (action == TE_INSERT_AFTER);
}
else if (action == TE_INSERT_INTO) {
- BKE_layer_collection_move_into(id, lc_handle, lc_insert);
+ to_parent = outliner_collection_from_tree_element(insert_handle);
}
else {
BLI_assert(0);
+ return;
+ }
+
+ if (!to_parent) {
+ return;
}
+ BKE_collection_move(bmain, to_parent, from_parent, relative, relative_after, collection);
+
DEG_relations_tag_update(bmain);
}
-static bool outliner_layer_collections_reorder_poll(
+
+static bool outliner_collections_reorder_poll(
const TreeElement *insert_element,
- TreeElement **io_insert_handle, TreeElementInsertType *UNUSED(io_action))
+ TreeElement **io_insert_handle,
+ TreeElementInsertType *io_action)
{
- const TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle);
+ /* Can't move master collection. */
+ Collection *collection = outliner_collection_from_tree_element(insert_element);
+ if (collection->flag & COLLECTION_IS_MASTER) {
+ return false;
+ }
- if (tselem_handle->id != insert_element->store_elem->id) {
- return false;
+ /* Can only move into collections. */
+ Collection *collection_handle = outliner_collection_from_tree_element(*io_insert_handle);
+ if (collection_handle == NULL) {
+ return false;
+ }
+
+ /* We can't insert/before after master collection. */
+ if (collection_handle->flag & COLLECTION_IS_MASTER) {
+ if (*io_action == TE_INSERT_BEFORE) {
+ /* can't go higher than master collection, insert into it */
+ *io_action = TE_INSERT_INTO;
+ }
+ else if (*io_action == TE_INSERT_AFTER) {
+ *io_insert_handle = (*io_insert_handle)->subtree.last;
+ }
}
- return ELEM(tselem_handle->type, TSE_LAYER_COLLECTION);
+ return true;
}
-static void outliner_add_layer_collections_recursive(
- SpaceOops *soops, ListBase *tree, ID *id, ListBase *layer_collections, TreeElement *parent_ten,
- const bool show_objects)
+static void outliner_add_layer_collection_objects(
+ SpaceOops *soops, ListBase *tree, ViewLayer *layer,
+ LayerCollection *lc, TreeElement *ten)
{
- for (LayerCollection *collection = layer_collections->first; collection; collection = collection->next) {
- TreeElement *ten = outliner_add_element(soops, tree, id, parent_ten, TSE_LAYER_COLLECTION, 0);
-
- ten->name = collection->scene_collection->name;
- ten->directdata = collection;
- ten->reinsert = outliner_layer_collections_reorder;
- ten->reinsert_poll = outliner_layer_collections_reorder_poll;
+ 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;
- outliner_add_layer_collections_recursive(soops, &ten->subtree, id, &collection->layer_collections, ten, show_objects);
- if (show_objects) {
- for (LinkData *link = collection->object_bases.first; link; link = link->next) {
- Base *base = (Base *)link->data;
- TreeElement *te_object = outliner_add_element(soops, &ten->subtree, base->object, ten, 0, 0);
- te_object->directdata = base;
- }
+ if (!(base->flag & BASE_VISIBLE)) {
+ te_object->flag |= TE_DISABLED;
}
}
}
-static void outliner_add_view_layer(SpaceOops *soops, ListBase *tree, TreeElement *parent,
- Scene *scene, ViewLayer *layer, const bool show_objects)
-{
- outliner_add_layer_collections_recursive(soops, tree, &scene->id, &layer->layer_collections, parent, show_objects);
-}
-
-static void outliner_scene_collections_reorder(
- Main *bmain,
- SpaceOops *UNUSED(soops),
- TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action,
- const wmEvent *UNUSED(event))
+static void outliner_add_layer_collections_recursive(
+ SpaceOops *soops, ListBase *tree, ViewLayer *layer,
+ ListBase *layer_collections, TreeElement *parent_ten,
+ const bool show_objects)
{
- SceneCollection *sc_insert = insert_element->directdata;
- SceneCollection *sc_handle = insert_handle->directdata;
- ID *id = insert_handle->store_elem->id;
- BLI_assert(id == insert_element->store_elem->id);
+ 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);
- BLI_assert((action == TE_INSERT_INTO) || (sc_handle != BKE_collection_master(id)));
- if (action == TE_INSERT_BEFORE) {
- BKE_collection_move_above(id, sc_handle, sc_insert);
- }
- else if (action == TE_INSERT_AFTER) {
- BKE_collection_move_below(id, sc_handle, sc_insert);
- }
- else if (action == TE_INSERT_INTO) {
- BKE_collection_move_into(id, sc_handle, sc_insert);
- }
- else {
- BLI_assert(0);
- }
+ ten->name = id->name + 2;
+ ten->directdata = lc;
+ ten->reinsert = outliner_collections_reorder;
+ ten->reinsert_poll = outliner_collections_reorder_poll;
- DEG_relations_tag_update(bmain);
-}
-static bool outliner_scene_collections_reorder_poll(
- const TreeElement *insert_element,
- TreeElement **io_insert_handle, TreeElementInsertType *io_action)
-{
- const TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle);
- ID *id = tselem_handle->id;
+ const bool exclude = (lc->flag & LAYER_COLLECTION_EXCLUDE) != 0;
+ if (exclude ||
+ ((layer->runtime_flag & VIEW_LAYER_HAS_HIDE) &&
+ !(lc->runtime_flag & LAYER_COLLECTION_HAS_VISIBLE_OBJECTS)))
+ {
+ ten->flag |= TE_DISABLED;
+ }
- if (id != insert_element->store_elem->id) {
- return false;
+ 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);
+ }
}
+}
- if (!ELEM(tselem_handle->type, TSE_SCENE_COLLECTION)) {
- return false;
+static void outliner_add_view_layer(SpaceOops *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;
}
- SceneCollection *sc_master = BKE_collection_master(id);
- SceneCollection *sc_handle = (*io_insert_handle)->directdata;
-
- if (sc_handle == sc_master) {
- /* exception: Can't insert before/after master selection, has to be one of its childs */
- TreeElement *te_master = *io_insert_handle;
- if (*io_action == TE_INSERT_BEFORE) {
- /* can't go higher than master collection, insert into it */
- *io_action = TE_INSERT_INTO;
- }
- else if (*io_action == TE_INSERT_AFTER) {
- *io_insert_handle = te_master->subtree.last;
- }
+ 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);
}
- return true;
}
-BLI_INLINE void outliner_add_scene_collection_init(TreeElement *te, Scene *scene, SceneCollection *collection)
+BLI_INLINE void outliner_add_collection_init(TreeElement *te, Collection *collection)
{
- if (collection == scene->collection) {
- // Don't display name of master collection
- te->name = IFACE_("Collections");
+ if (collection->flag & COLLECTION_IS_MASTER) {
+ te->name = IFACE_("Scene Collection");
}
else {
- te->name = collection->name;
+ te->name = collection->id.name + 2;
}
te->directdata = collection;
- te->reinsert = outliner_scene_collections_reorder;
- te->reinsert_poll = outliner_scene_collections_reorder_poll;
+ te->reinsert = outliner_collections_reorder;
+ te->reinsert_poll = outliner_collections_reorder_poll;
}
-BLI_INLINE void outliner_add_scene_collection_objects(
- SpaceOops *soops, ListBase *tree, SceneCollection *collection, TreeElement *parent)
+BLI_INLINE void outliner_add_collection_objects(
+ SpaceOops *soops, ListBase *tree, Collection *collection, TreeElement *parent)
{
- for (LinkData *link = collection->objects.first; link; link = link->next) {
- outliner_add_element(soops, tree, link->data, 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_scene_collection_recursive(
- SpaceOops *soops, ListBase *tree, Scene *scene, SceneCollection *scene_collection, TreeElement *parent_ten)
+static TreeElement *outliner_add_collection_recursive(
+ SpaceOops *soops, Collection *collection, TreeElement *ten)
{
- TreeElement *ten = outliner_add_element(soops, tree, &scene->id, parent_ten, TSE_SCENE_COLLECTION, 0);
- outliner_add_scene_collection_init(ten, scene, scene_collection);
+ outliner_add_collection_init(ten, collection);
- if (soops->outlinevis != SO_SCENES) {
- outliner_add_scene_collection_objects(soops, &ten->subtree, scene_collection, ten);
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ outliner_add_element(soops, &ten->subtree, &child->collection->id, ten, 0, 0);
}
- for (SceneCollection *scene_collection_nested = scene_collection->scene_collections.first;
- scene_collection_nested != NULL;
- scene_collection_nested = scene_collection_nested->next)
- {
- outliner_add_scene_collection_recursive(soops, &ten->subtree, scene, scene_collection_nested, ten);
+ if (soops->outlinevis != SO_SCENES) {
+ outliner_add_collection_objects(soops, &ten->subtree, collection, ten);
}
return ten;
@@ -1517,7 +1575,7 @@ static void outliner_make_object_parent_hierarchy(ListBase *lb)
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) {
@@ -1546,16 +1604,16 @@ 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;
@@ -1568,9 +1626,9 @@ 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;
@@ -1582,7 +1640,7 @@ static int treesort_alpha(const void *v1, const void *v2)
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;
@@ -1599,7 +1657,7 @@ static int treesort_obtype_alpha(const void *v1, const void *v2)
}
else {
int comp = strcmp(x1->name, x2->name);
-
+
if (comp > 0) return 1;
else if (comp < 0) return -1;
return 0;
@@ -1632,15 +1690,15 @@ static void outliner_sort(ListBase *lb)
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);
@@ -1649,11 +1707,11 @@ static void outliner_sort(ListBase *lb)
/* 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--) {
@@ -1663,7 +1721,7 @@ static void outliner_sort(ListBase *lb)
MEM_freeN(tear);
}
}
-
+
for (te = lb->first; te; te = te->next) {
outliner_sort(&te->subtree);
}
@@ -1705,15 +1763,12 @@ static void outliner_restore_scrolling_position(SpaceOops *soops, ARegion *ar, O
else {
return;
}
-
- soops->storeflag |= SO_TREESTORE_REDRAW;
}
}
static bool test_collection_callback(TreeElement *te)
{
- TreeStoreElem *tselem = TREESTORE(te);
- return ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION);
+ return outliner_is_collection_tree_element(te);
}
static bool test_object_callback(TreeElement *te)
@@ -1767,7 +1822,9 @@ static TreeElement *outliner_find_first_desired_element_at_y(
te = outliner_find_item_at_y(soops, &soops->tree, view_co);
bool (*callback_test)(TreeElement *);
- if (soops->filter & SO_FILTER_NO_COLLECTION) {
+ if ((soops->outlinevis == SO_VIEW_LAYER) &&
+ (soops->filter & SO_FILTER_NO_COLLECTION))
+ {
callback_test = test_object_callback;
}
else {
@@ -1835,10 +1892,11 @@ static int outliner_exclude_filter_get(SpaceOops *soops)
{
int exclude_filter = soops->filter & ~SO_FILTER_OB_STATE;
- if (soops->filter & SO_FILTER_SEARCH) {
- if (soops->search_string[0] == 0) {
- exclude_filter &= ~SO_FILTER_SEARCH;
- }
+ 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. */
@@ -1846,10 +1904,11 @@ static int outliner_exclude_filter_get(SpaceOops *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_NONE:
- exclude_filter |= SO_FILTER_OB_TYPE;
- break;
case SO_FILTER_OB_VISIBLE:
exclude_filter |= SO_FILTER_OB_STATE_VISIBLE;
break;
@@ -1925,7 +1984,7 @@ static bool outliner_element_visible_get(ViewLayer *view_layer, TreeElement *te,
}
if (exclude_filter & SO_FILTER_OB_STATE_VISIBLE) {
- if ((base->flag & BASE_VISIBLED) == 0) {
+ if ((base->flag & BASE_VISIBLE) == 0) {
return false;
}
}
@@ -2001,7 +2060,7 @@ static int outliner_filter_subtree(
/* 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)
{
@@ -2060,7 +2119,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
/* 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_DATABLOCKS)
+ if (soops->search_string[0] != 0 && soops->outlinevis != SO_DATA_API)
soops->search_flags |= SO_SEARCH_RECURSIVE;
else
soops->search_flags &= ~SO_SEARCH_RECURSIVE;
@@ -2070,34 +2129,33 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
BKE_outliner_treehash_rebuild_from_treestore(soops->treehash, soops->treestore);
}
- if (soops->tree.first && (soops->storeflag & SO_TREESTORE_REDRAW))
+ 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_element(soops, &soops->tree, mainvar, NULL, TSE_ID_BASE, 0);
- ten->name = IFACE_("Current File");
+ ten = outliner_add_library_contents(mainvar, soops, &soops->tree, NULL);
+ if (ten) {
+ tselem = TREESTORE(ten);
+ if (!tselem->used)
+ tselem->flag &= ~TSE_CLOSED;
+ }
- tselem = TREESTORE(ten);
- if (!tselem->used)
- tselem->flag &= ~TSE_CLOSED;
-
- outliner_add_library_contents(mainvar, soops, ten, NULL);
-
for (lib = mainvar->library.first; lib; lib = lib->id.next) {
- ten = outliner_add_element(soops, &soops->tree, lib, NULL, 0, 0);
- lib->id.newid = (ID *)ten;
-
- outliner_add_library_contents(mainvar, soops, ten, lib);
+ ten = outliner_add_library_contents(mainvar, soops, &soops->tree, lib);
+ if (ten) {
+ lib->id.newid = (ID *)ten;
+ }
}
/* make hierarchy */
@@ -2117,9 +2175,10 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
}
else {
/* Else, make a new copy of the libtree for our parent. */
- TreeElement *dupten = outliner_add_element(soops, &par->subtree, lib, NULL, 0, 0);
- outliner_add_library_contents(mainvar, soops, dupten, lib);
- dupten->parent = par;
+ TreeElement *dupten = outliner_add_library_contents(mainvar, soops, &par->subtree, lib);
+ if (dupten) {
+ dupten->parent = par;
+ }
}
}
ten = nten;
@@ -2127,7 +2186,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
/* restore newid pointers */
for (lib = mainvar->library.first; lib; lib = lib->id.next)
lib->id.newid = NULL;
-
+
}
else if (soops->outlinevis == SO_SCENES) {
Scene *sce;
@@ -2142,12 +2201,6 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
outliner_make_object_parent_hierarchy(&te->subtree);
}
}
- else if (soops->outlinevis == SO_GROUPS) {
- Group *group;
- for (group = mainvar->group.first; group; group = group->id.next) {
- te = outliner_add_element(soops, &soops->tree, group, NULL, 0, 0);
- }
- }
else if (soops->outlinevis == SO_SEQUENCE) {
Sequence *seq;
Editing *ed = BKE_sequencer_editing_get(scene, false);
@@ -2172,7 +2225,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
seq = seq->next;
}
}
- else if (soops->outlinevis == SO_DATABLOCKS) {
+ else if (soops->outlinevis == SO_DATA_API) {
PointerRNA mainptr;
RNA_main_pointer_create(mainvar, &mainptr);
@@ -2187,27 +2240,24 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
else if (soops->outlinevis == SO_ID_ORPHANS) {
outliner_add_orphaned_datablocks(mainvar, soops);
}
- else if (soops->outlinevis == SO_COLLECTIONS) {
- TreeElement *tenlay = outliner_add_element(soops, &soops->tree, scene, te, TSE_R_LAYER, 0);
- tenlay->name = view_layer->name;
- tenlay->directdata = view_layer;
- TREESTORE(tenlay)->flag &= ~TSE_CLOSED;
-
+ 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, &tenlay->subtree, base->object, NULL, 0, 0);
+ TreeElement *te_object = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
te_object->directdata = base;
}
- outliner_make_object_parent_hierarchy(&tenlay->subtree);
+
+ outliner_make_object_parent_hierarchy(&soops->tree);
}
else {
- outliner_add_view_layer(soops, &tenlay->subtree, NULL, scene, view_layer, true);
- }
- }
- else {
- if (BASACT(view_layer)) {
- ten = outliner_add_element(soops, &soops->tree, OBACT(view_layer), NULL, 0, 0);
- ten->directdata = BASACT(view_layer);
+ /* 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);
}
}
@@ -2220,5 +2270,3 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
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 d3f7fd7055e..6b7035dd326 100644
--- a/source/blender/editors/space_outliner/outliner_utils.c
+++ b/source/blender/editors/space_outliner/outliner_utils.c
@@ -101,6 +101,23 @@ TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store
return NULL;
}
+/* Find parent element of 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;
+}
+
/* tse is not in the treestore, we use its contents to find a match */
TreeElement *outliner_find_tse(SpaceOops *soops, const TreeStoreElem *tse)
{
@@ -125,15 +142,11 @@ TreeElement *outliner_find_id(SpaceOops *soops, ListBase *lb, const ID *id)
if (tselem->id == id) {
return te;
}
- /* only deeper on scene or object */
- if (ELEM(te->idcode, ID_OB, ID_SCE) ||
- ((soops->outlinevis == SO_GROUPS) && (te->idcode == ID_GR)))
- {
- TreeElement *tes = outliner_find_id(soops, &te->subtree, id);
- if (tes) {
- return tes;
- }
- }
+ }
+
+ TreeElement *tes = outliner_find_id(soops, &te->subtree, id);
+ if (tes) {
+ return tes;
}
}
return NULL;
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index 557a0723cb4..cfd658eea6c 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -63,12 +63,13 @@
#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 */
@@ -81,7 +82,7 @@ static void outliner_main_region_init(wmWindowManager *wm, ARegion *ar)
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_find(wm->defaultconf, "Outliner", SPACE_OUTLINER, 0);
/* don't pass on view2d mask, it's always set with scrollbar space, hide fails */
@@ -138,10 +139,6 @@ static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e
}
}
}
- else if (ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
- /* support adding object from different scene to collection */
- return 1;
- }
}
}
return 0;
@@ -163,7 +160,7 @@ static int outliner_parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
- if (!ELEM(soops->outlinevis, SO_SCENES, SO_GROUPS, SO_COLLECTIONS)) {
+ if (!ELEM(soops->outlinevis, SO_VIEW_LAYER)) {
return false;
}
@@ -250,7 +247,7 @@ static void outliner_material_drop_copy(wmDrag *drag, wmDropBox *drop)
RNA_string_set(drop->ptr, "material", id->name + 2);
}
-static int outliner_group_link_poll(bContext *C, wmDrag *drag, const wmEvent *event)
+static int outliner_collection_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
@@ -259,19 +256,19 @@ static int outliner_group_link_poll(bContext *C, wmDrag *drag, const wmEvent *ev
if (drag->type == WM_DRAG_ID) {
ID *id = drag->poin;
- if (GS(id->name) == ID_OB) {
+ if (ELEM(GS(id->name), ID_OB, ID_GR)) {
/* Ensure item under cursor is valid drop target */
TreeElement *te = outliner_dropzone_find(soops, fmval, true);
- return (te && te->idcode == ID_GR && TREESTORE(te)->type == 0);
+ return (te && outliner_is_collection_tree_element(te));
}
}
return 0;
}
-static void outliner_group_link_copy(wmDrag *drag, wmDropBox *drop)
+static void outliner_collection_drop_copy(wmDrag *drag, wmDropBox *drop)
{
ID *id = drag->poin;
- RNA_string_set(drop->ptr, "object", id->name + 2);
+ RNA_string_set(drop->ptr, "child", id->name + 2);
}
/* region dropbox definition */
@@ -283,23 +280,23 @@ static void outliner_dropboxes(void)
WM_dropbox_add(lb, "OUTLINER_OT_parent_clear", outliner_parent_clear_poll, outliner_parent_clear_copy);
WM_dropbox_add(lb, "OUTLINER_OT_scene_drop", outliner_scene_drop_poll, outliner_scene_drop_copy);
WM_dropbox_add(lb, "OUTLINER_OT_material_drop", outliner_material_drop_poll, outliner_material_drop_copy);
- WM_dropbox_add(lb, "OUTLINER_OT_group_link", outliner_group_link_poll, outliner_group_link_copy);
+ WM_dropbox_add(lb, "OUTLINER_OT_collection_drop", outliner_collection_drop_poll, outliner_collection_drop_copy);
}
static void outliner_main_region_draw(const bContext *C, ARegion *ar)
{
View2D *v2d = &ar->v2d;
View2DScrollers *scrollers;
-
+
/* clear */
UI_ThemeClearColor(TH_BACK);
- glClear(GL_COLOR_BUFFER_BIT);
-
+ GPU_clear(GPU_COLOR_BIT);
+
draw_outliner(C);
-
+
/* reset view matrix */
UI_view2d_view_restore(C);
-
+
/* scrollers */
scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
UI_view2d_scrollers_draw(C, v2d, scrollers);
@@ -309,7 +306,7 @@ static void outliner_main_region_draw(const bContext *C, ARegion *ar)
static void outliner_main_region_free(ARegion *UNUSED(ar))
{
-
+
}
static void outliner_main_region_listener(
@@ -422,7 +419,7 @@ static void outliner_main_region_listener(
}
break;
}
-
+
}
static void outliner_main_region_message_subscribe(
@@ -438,7 +435,7 @@ static void outliner_main_region_message_subscribe(
.notify = ED_region_do_msg_notify_tag_redraw,
};
- if (soops->outlinevis == SO_COLLECTIONS) {
+ 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);
}
}
@@ -487,20 +484,21 @@ static SpaceLink *outliner_new(const ScrArea *UNUSED(area), const Scene *UNUSED(
soutliner = MEM_callocN(sizeof(SpaceOops), "initoutliner");
soutliner->spacetype = SPACE_OUTLINER;
-
+ soutliner->filter_id_type = ID_GR;
+
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for outliner");
-
+
BLI_addtail(&soutliner->regionbase, ar);
ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = RGN_ALIGN_BOTTOM;
-
+ ar->alignment = RGN_ALIGN_TOP;
+
/* main region */
ar = MEM_callocN(sizeof(ARegion), "main region for outliner");
-
+
BLI_addtail(&soutliner->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
-
+
return (SpaceLink *)soutliner;
}
@@ -508,7 +506,7 @@ static SpaceLink *outliner_new(const ScrArea *UNUSED(area), const Scene *UNUSED(
static void outliner_free(SpaceLink *sl)
{
SpaceOops *soutliner = (SpaceOops *)sl;
-
+
outliner_free_tree(&soutliner->tree);
if (soutliner->treestore) {
BLI_mempool_destroy(soutliner->treestore);
@@ -521,7 +519,7 @@ static void outliner_free(SpaceLink *sl)
/* spacetype; init callback */
static void outliner_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
{
-
+
}
static SpaceLink *outliner_duplicate(SpaceLink *sl)
@@ -532,7 +530,7 @@ static SpaceLink *outliner_duplicate(SpaceLink *sl)
BLI_listbase_clear(&soutlinern->tree);
soutlinern->treestore = NULL;
soutlinern->treehash = NULL;
-
+
return (SpaceLink *)soutlinern;
}
@@ -574,10 +572,10 @@ 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;
@@ -591,26 +589,25 @@ void ED_spacetype_outliner(void)
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/script_intern.h b/source/blender/editors/space_script/script_intern.h
index cef6082aa1c..0e0936cf082 100644
--- a/source/blender/editors/space_script/script_intern.h
+++ b/source/blender/editors/space_script/script_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -43,4 +43,3 @@ void SCRIPT_OT_python_file_run(struct wmOperatorType *ot);
void SCRIPT_OT_autoexec_warn_clear(struct wmOperatorType *ot);
#endif /* __SCRIPT_INTERN_H__ */
-
diff --git a/source/blender/editors/space_script/space_script.c b/source/blender/editors/space_script/space_script.c
index 767db745c33..8b6100cd9e0 100644
--- a/source/blender/editors/space_script/space_script.c
+++ b/source/blender/editors/space_script/space_script.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -55,6 +55,7 @@
#endif
#include "script_intern.h" // own include
+#include "GPU_framebuffer.h"
//static script_run_python(char *funcname, )
@@ -66,33 +67,33 @@ static SpaceLink *script_new(const ScrArea *UNUSED(area), const Scene *UNUSED(sc
{
ARegion *ar;
SpaceScript *sscript;
-
+
sscript = MEM_callocN(sizeof(SpaceScript), "initscript");
sscript->spacetype = SPACE_SCRIPT;
-
-
+
+
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for script");
-
+
BLI_addtail(&sscript->regionbase, ar);
ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = RGN_ALIGN_BOTTOM;
-
+ ar->alignment = RGN_ALIGN_TOP;
+
/* main region */
ar = MEM_callocN(sizeof(ARegion), "main region for script");
-
+
BLI_addtail(&sscript->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
-
+
/* channel list region XXX */
-
+
return (SpaceLink *)sscript;
}
/* not spacelink itself */
static void script_free(SpaceLink *sl)
-{
+{
SpaceScript *sscript = (SpaceScript *) sl;
#ifdef WITH_PYTHON
@@ -116,9 +117,9 @@ static void script_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
static SpaceLink *script_duplicate(SpaceLink *sl)
{
SpaceScript *sscriptn = MEM_dupallocN(sl);
-
+
/* clear or remove stuff from old */
-
+
return (SpaceLink *)sscriptn;
}
@@ -128,9 +129,9 @@ static SpaceLink *script_duplicate(SpaceLink *sl)
static void script_main_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
-
+
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
-
+
/* own keymap */
keymap = WM_keymap_find(wm->defaultconf, "Script", SPACE_SCRIPT, 0);
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
@@ -144,13 +145,13 @@ static void script_main_region_draw(const bContext *C, ARegion *ar)
/* clear and setup matrix */
UI_ThemeClearColor(TH_BACK);
- glClear(GL_COLOR_BUFFER_BIT);
-
+ GPU_clear(GPU_COLOR_BIT);
+
UI_view2d_view_ortho(v2d);
-
+
/* 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);
@@ -158,10 +159,10 @@ static void script_main_region_draw(const bContext *C, ARegion *ar)
#else
(void)sscript;
#endif
-
+
/* reset view matrix */
UI_view2d_view_restore(C);
-
+
/* scrollers? */
}
@@ -190,17 +191,17 @@ 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;
@@ -210,19 +211,18 @@ void ED_spacetype_script(void)
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/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index caa3ba593fb..a8688b26280 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -95,12 +95,12 @@ static void sequencer_generic_props__internal(wmOperatorType *ot, int flag)
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)
RNA_def_int(ot->srna, "frame_end", 0, INT_MIN, INT_MAX, "End Frame", "End frame for the color strip", INT_MIN, INT_MAX); /* not usual since most strips have a fixed length */
-
+
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 */
@@ -114,9 +114,10 @@ static void sequencer_generic_invoke_path__internal(bContext *C, wmOperator *op,
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, G.main->name);
+ BLI_path_abs(path, BKE_main_blendfile_path(bmain));
RNA_string_set(op->ptr, identifier, path);
}
}
@@ -144,7 +145,7 @@ static int sequencer_generic_invoke_xy_guess_channel(bContext *C, int type)
proximity = cfra - seq->enddisp;
}
}
-
+
if (tgt) {
return tgt->machine;
}
@@ -154,16 +155,16 @@ static int sequencer_generic_invoke_xy_guess_channel(bContext *C, int type)
static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, int flag, int type)
{
Scene *scene = CTX_data_scene(C);
-
+
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));
}
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 arbitary but ok for now.
@@ -173,8 +174,10 @@ static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, i
}
}
-static void seq_load_operator_info(SeqLoadInfo *seq_load, wmOperator *op)
+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;
@@ -196,9 +199,9 @@ static void seq_load_operator_info(SeqLoadInfo *seq_load, wmOperator *op)
}
if ((is_file != -1) && relative)
- BLI_path_rel(seq_load->path, G.main->name);
+ 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);
}
@@ -214,7 +217,7 @@ static void seq_load_operator_info(SeqLoadInfo *seq_load, wmOperator *op)
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;
@@ -283,35 +286,35 @@ 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 *sce_seq;
Sequence *seq; /* generic strip vars */
Strip *strip;
-
+
int start_frame, channel; /* operator props */
-
+
start_frame = RNA_int_get(op->ptr, "frame_start");
channel = RNA_int_get(op->ptr, "channel");
-
+
sce_seq = BLI_findlink(&CTX_data_main(C)->scene, RNA_enum_get(op->ptr, "scene"));
-
+
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->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;
-
+
BLI_strncpy(seq->name + 2, sce_seq->id.name + 2, sizeof(seq->name) - 2);
BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
@@ -319,12 +322,12 @@ static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op)
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);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-
+
return OPERATOR_FINISHED;
}
@@ -344,7 +347,7 @@ static int sequencer_add_scene_strip_invoke(bContext *C, wmOperator *op, const w
void SEQUENCER_OT_scene_strip_add(struct wmOperatorType *ot)
{
PropertyRNA *prop;
-
+
/* identifiers */
ot->name = "Add Scene Strip";
ot->idname = "SEQUENCER_OT_scene_strip_add";
@@ -355,10 +358,10 @@ void SEQUENCER_OT_scene_strip_add(struct wmOperatorType *ot)
ot->exec = sequencer_add_scene_strip_exec;
ot->poll = ED_operator_sequencer_active_editable;
-
+
/* 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);
@@ -371,24 +374,24 @@ 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);
-
+
MovieClip *clip;
Sequence *seq; /* generic strip vars */
Strip *strip;
-
+
int start_frame, channel; /* operator props */
-
+
start_frame = RNA_int_get(op->ptr, "frame_start");
channel = RNA_int_get(op->ptr, "channel");
-
+
clip = BLI_findlink(&CTX_data_main(C)->movieclip, RNA_enum_get(op->ptr, "clip"));
-
+
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;
@@ -400,18 +403,18 @@ static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op)
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);
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);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-
+
return OPERATOR_FINISHED;
}
@@ -545,7 +548,7 @@ static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoad
SeqLoadInfo seq_load;
int tot_files;
- seq_load_operator_info(&seq_load, op);
+ seq_load_operator_info(&seq_load, C, op);
if (seq_load.flag & SEQ_LOAD_REPLACE_SEL)
ED_sequencer_deselect_all(scene);
@@ -666,7 +669,7 @@ static int sequencer_add_movie_strip_invoke(bContext *C, wmOperator *op, const w
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);
@@ -702,7 +705,7 @@ static void sequencer_add_draw(bContext *UNUSED(C), wmOperator *op)
void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot)
{
-
+
/* identifiers */
ot->name = "Add Movie Strip";
ot->idname = "SEQUENCER_OT_movie_strip_add";
@@ -718,7 +721,7 @@ void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot)
/* 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);
@@ -743,7 +746,7 @@ static int sequencer_add_sound_strip_invoke(bContext *C, wmOperator *op, const w
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);
WM_event_add_fileselect(C, op);
@@ -755,7 +758,7 @@ static int sequencer_add_sound_strip_invoke(bContext *C, wmOperator *op, const w
void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot)
{
-
+
/* identifiers */
ot->name = "Add Sound Strip";
ot->idname = "SEQUENCER_OT_sound_strip_add";
@@ -766,10 +769,10 @@ void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot)
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);
@@ -855,7 +858,7 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
StripElem *se;
const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
- seq_load_operator_info(&seq_load, op);
+ seq_load_operator_info(&seq_load, C, op);
/* images are unique in how they handle this - 1 per strip elem */
if (use_placeholders) {
@@ -925,7 +928,7 @@ static int sequencer_add_image_strip_invoke(bContext *C, wmOperator *op, const w
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_add_init(C, op);
@@ -941,7 +944,7 @@ static int sequencer_add_image_strip_invoke(bContext *C, wmOperator *op, const w
void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot)
{
-
+
/* identifiers */
ot->name = "Add Image Strip";
ot->idname = "SEQUENCER_OT_image_strip_add";
@@ -954,10 +957,10 @@ void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot)
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);
@@ -978,7 +981,7 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
struct SeqEffectHandle sh;
int start_frame, end_frame, channel, type; /* operator props */
-
+
Sequence *seq1, *seq2, *seq3;
const char *error_msg;
@@ -987,7 +990,7 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
channel = RNA_int_get(op->ptr, "channel");
type = RNA_enum_get(op->ptr, "type");
-
+
// XXX move to invoke
if (!seq_effect_find_selected(scene, NULL, type, &seq1, &seq2, &seq3, &error_msg)) {
BKE_report(op->reports, RPT_ERROR, error_msg);
@@ -1023,7 +1026,7 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE;
BKE_sequence_calc(scene, seq);
-
+
/* basic defaults */
seq->strip = strip = MEM_callocN(sizeof(Strip), "strip");
strip->us = 1;
@@ -1061,7 +1064,7 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
/* 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);
+ BKE_sequencer_sort(scene);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -1105,10 +1108,10 @@ void SEQUENCER_OT_effect_strip_add(struct wmOperatorType *ot)
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",
diff --git a/source/blender/editors/space_sequencer/sequencer_buttons.c b/source/blender/editors/space_sequencer/sequencer_buttons.c
index b33a26db728..5c8f8a0c4f1 100644
--- a/source/blender/editors/space_sequencer/sequencer_buttons.c
+++ b/source/blender/editors/space_sequencer/sequencer_buttons.c
@@ -65,7 +65,7 @@ void sequencer_buttons_register(ARegionType *UNUSED(art))
{
#if 0
PanelType *pt;
-
+
pt = MEM_callocN(sizeof(PanelType), "spacetype sequencer panel gpencil");
strcpy(pt->idname, "SEQUENCER_PT_gpencil");
strcpy(pt->label, N_("Grease Pencil"));
@@ -83,7 +83,7 @@ static int sequencer_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = sequencer_has_buttons_region(sa);
-
+
if (ar)
ED_region_toggle_hidden(C, ar);
@@ -95,11 +95,10 @@ void SEQUENCER_OT_properties(wmOperatorType *ot)
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;
-
+
/* 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 06ea3fceb2f..bf538611852 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -61,6 +61,8 @@
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
+#include "GPU_framebuffer.h"
#include "ED_anim_api.h"
#include "ED_gpencil.h"
@@ -125,12 +127,12 @@ void color3ubv_from_seq(Scene *curscene, Sequence *seq, unsigned char col[3])
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:
@@ -216,7 +218,7 @@ static void drawseqwave(View2D *v2d, const bContext *C, SpaceSeq *sseq, Scene *s
float startsample, endsample;
float value1, value2;
bSound *sound = seq->sound;
-
+
SoundWaveform *waveform;
if (length < 2) {
@@ -227,7 +229,7 @@ static void drawseqwave(View2D *v2d, const bContext *C, SpaceSeq *sseq, Scene *s
sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock");
BLI_spin_init(sound->spinlock);
}
-
+
BLI_spin_lock(sound->spinlock);
if (!sound->waveform) {
if (!(sound->flags & SOUND_FLAGS_WAVEFORM_LOADING)) {
@@ -242,7 +244,7 @@ static void drawseqwave(View2D *v2d, const bContext *C, SpaceSeq *sseq, Scene *s
return; /* nothing to draw */
}
BLI_spin_unlock(sound->spinlock);
-
+
waveform = sound->waveform;
if (waveform->length == 0) {
@@ -263,7 +265,7 @@ static void drawseqwave(View2D *v2d, const bContext *C, SpaceSeq *sseq, Scene *s
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
- glEnable(GL_BLEND);
+ GPU_blend(true);
immBegin(GWN_PRIM_TRI_STRIP, length * 2);
@@ -296,7 +298,7 @@ static void drawseqwave(View2D *v2d, const bContext *C, SpaceSeq *sseq, Scene *s
immEnd();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
}
static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1, float x2, float y2)
@@ -328,8 +330,8 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
offset = 0;
}
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
for (seq = seqbase->first; seq; seq = seq->next) {
chan_min = min_ii(chan_min, seq->machine);
@@ -365,7 +367,7 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
}
immUniformColor4ubv(col);
-
+
/* clamp within parent sequence strip bounds */
if (x1_chan < x1) x1_chan = x1;
if (x2_chan > x2) x2_chan = x2;
@@ -379,7 +381,7 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
immUnbindProgram();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
/* clamp handles to defined size in pixel space */
@@ -399,10 +401,10 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla
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;
@@ -410,32 +412,32 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla
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)
{
- glEnable(GL_BLEND);
-
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
+
if (seq->flag & whichsel) {
immUniformColor4ub(0, 0, 0, 80);
}
@@ -445,9 +447,9 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla
else {
immUniformColor4ub(0, 0, 0, 22);
}
-
+
immRectf(pos, rx1, y1, rx2, y2);
-
+
if (seq->flag & whichsel) {
immUniformColor4ub(255, 255, 255, 200);
}
@@ -461,9 +463,9 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla
immVertex2fv(pos, v3);
immEnd();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
-
+
if ((G.moving & G_TRANSFORM_SEQ) || (seq->flag & whichsel)) {
const char col[4] = {255, 255, 255, 255};
char numstr[32];
@@ -579,7 +581,7 @@ static void draw_seq_text(View2D *v2d, SpaceSeq *sseq, Sequence *seq, float x1,
str_len = BLI_snprintf(str, sizeof(str), "%s | %d",
name, seq->len);
}
-
+
if (seq->flag & SELECT) {
col[0] = col[1] = col[2] = 255;
}
@@ -604,23 +606,23 @@ static void draw_sequence_extensions(Scene *scene, ARegion *ar, Sequence *seq, u
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) {
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
+
color3ubv_from_seq(scene, seq, col);
if (seq->flag & SELECT) {
@@ -658,12 +660,12 @@ static void draw_sequence_extensions(Scene *scene, ARegion *ar, Sequence *seq, u
}
if (seq->startofs || seq->endofs) {
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
if (seq->startstill || seq->endstill) {
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
color3ubv_from_seq(scene, seq, col);
UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.5f, 60);
@@ -691,7 +693,7 @@ static void draw_sequence_extensions(Scene *scene, ARegion *ar, Sequence *seq, u
}
if (seq->startstill || seq->endstill) {
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
}
@@ -710,7 +712,7 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
/* 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;
@@ -728,8 +730,8 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
if (seq->flag & SEQ_MUTE) {
background_col[3] = 128;
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
}
else {
background_col[3] = 255;
@@ -751,7 +753,7 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
}
if (seq->flag & SEQ_MUTE) {
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
if (!is_single_image) {
@@ -765,7 +767,7 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
x1 = seq->startdisp;
x2 = seq->enddisp;
-
+
/* draw sound wave */
if (seq->type == SEQ_TYPE_SOUND_RAM) {
if (!(sseq->flag & SEQ_NO_WAVEFORMS)) {
@@ -777,7 +779,7 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
/* draw lock */
if (seq->flag & SEQ_LOCK) {
- glEnable(GL_BLEND);
+ GPU_blend(true);
pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_DIAG_STRIPES);
@@ -791,11 +793,11 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
immUnbindProgram();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
if (!BKE_sequence_is_valid_check(seq)) {
- glEnable(GL_BLEND);
+ GPU_blend(true);
pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_DIAG_STRIPES);
@@ -809,7 +811,7 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
immUnbindProgram();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
color3ubv_from_seq(scene, seq, col);
@@ -825,7 +827,7 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
}
else
UI_GetColorPtrShade3ubv(col, col, outline_tint);
-
+
if ((seq->type == SEQ_TYPE_META) ||
((seq->type == SEQ_TYPE_SCENE) && (seq->flag & SEQ_SCENE_STRIPS)))
{
@@ -840,8 +842,8 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
if (seq->flag & SEQ_MUTE) {
col[3] = 96;
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
immUniformColor4ubv(col);
}
@@ -894,7 +896,9 @@ void ED_sequencer_special_preview_clear(void)
sequencer_special_update_set(NULL);
}
-ImBuf *sequencer_ibuf_get(struct Main *bmain, 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;
@@ -919,7 +923,7 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int
recty = (render_size * (float)scene->r.ysch) / 100.0f + 0.5f;
BKE_sequencer_new_render_data(
- bmain, scene,
+ bmain, depsgraph, scene,
rectx, recty, proxy_size, false,
&context);
context.view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
@@ -976,7 +980,7 @@ static ImBuf *sequencer_make_scope(Scene *scene, ImBuf *ibuf, ImBuf *(*make_scop
{
ImBuf *display_ibuf = IMB_dupImBuf(ibuf);
ImBuf *scope;
-
+
IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings,
&scene->display_settings);
@@ -1033,7 +1037,7 @@ static void sequencer_draw_borders(const SpaceSeq *sseq, const View2D *v2d, cons
float x2 = v2d->tot.xmax;
float y2 = v2d->tot.ymax;
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
/* border */
const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -1041,7 +1045,7 @@ static void sequencer_draw_borders(const SpaceSeq *sseq, const View2D *v2d, cons
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
immUniformThemeColor(TH_BACK);
@@ -1091,6 +1095,7 @@ static void sequencer_draw_background(
void draw_image_seq(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 ImBuf *ibuf = NULL;
struct ImBuf *scope = NULL;
struct View2D *v2d = &ar->v2d;
@@ -1121,8 +1126,8 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
if ((!draw_overlay || sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) && !draw_backdrop) {
UI_GetThemeColor3fv(TH_SEQ_PREVIEW, col);
- glClearColor(col[0], col[1], col[2], 0.0);
- glClear(GL_COLOR_BUFFER_BIT);
+ GPU_clear_color(col[0], col[1], col[2], 0.0);
+ GPU_clear(GPU_COLOR_BIT);
}
/* only initialize the preview if a render is in progress */
@@ -1134,7 +1139,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
}
/* for now we only support Left/Right */
- ibuf = sequencer_ibuf_get(bmain, scene, sseq, cfra, frame_ofs, names[sseq->multiview_eye]);
+ ibuf = sequencer_ibuf_get(bmain, depsgraph, scene, sseq, cfra, frame_ofs, names[sseq->multiview_eye]);
if ((ibuf == NULL) ||
(ibuf->rect == NULL && ibuf->rect_float == NULL))
@@ -1218,8 +1223,8 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
}
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) {
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
}
/* Format needs to be created prior to any immBindProgram call.
@@ -1415,7 +1420,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
}
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) {
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
glDeleteTextures(1, &texid);
@@ -1482,7 +1487,7 @@ void drawprefetchseqspace(Scene *scene, ARegion *UNUSED(ar), SpaceSeq *sseq)
{
int rectx, recty;
int render_size = sseq->render_size;
- int proxy_size = 100.0;
+ int proxy_size = 100.0;
if (render_size == 0) {
render_size = scene->r.size;
}
@@ -1555,12 +1560,12 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
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;
int outline_tint = (j) ? 40 : -40; /* highlighting around strip edges indicating selection */
-
+
/* 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... */
@@ -1570,15 +1575,15 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
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);
@@ -1586,7 +1591,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
/* draw highlight when previewing a single strip */
if (special_seq_update) {
const Sequence *seq = special_seq_update;
- glEnable(GL_BLEND);
+ GPU_blend(true);
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -1596,7 +1601,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
immUnbindProgram();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
}
@@ -1606,12 +1611,12 @@ static void seq_draw_sfra_efra(Scene *scene, View2D *v2d)
const int frame_sta = PSFRA;
const int frame_end = PEFRA + 1;
- glEnable(GL_BLEND);
+ GPU_blend(true);
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- /* draw darkened area outside of active timeline
+ /* draw darkened area outside of active timeline
* frame range used is preview range or scene range */
immUniformThemeColorShadeAlpha(TH_BACK, -25, -100);
@@ -1657,7 +1662,7 @@ static void seq_draw_sfra_efra(Scene *scene, View2D *v2d)
immUnbindProgram();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
/* Draw Timeline/Strip Editor Mode for Sequencer */
@@ -1670,27 +1675,27 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
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)
- glClearColor(col[0], col[1], col[2] - 0.1f, 0.0f);
- else
- glClearColor(col[0], col[1], col[2], 0.0f);
- glClear(GL_COLOR_BUFFER_BIT);
+ 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
+
+
+ /* 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);
@@ -1699,29 +1704,29 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
draw_image_seq(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);
ED_markers_draw(C, DRAW_MARKERS_LINES | DRAW_MARKERS_MARGIN);
-
+
/* preview range */
UI_view2d_view_ortho(v2d);
ANIM_draw_previewrange(C, v2d, 1);
@@ -1754,12 +1759,10 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
scrollers = UI_view2d_scrollers_calc(C, v2d, 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 e200dffa308..98f63c791af 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -128,8 +128,9 @@ typedef struct TransSeq {
/* ***************** proxy job manager ********************** */
typedef struct ProxyBuildJob {
- Scene *scene;
struct Main *main;
+ struct Depsgraph *depsgraph;
+ Scene *scene;
ListBase queue;
int stop;
} ProxyJob;
@@ -153,7 +154,7 @@ static void proxy_startjob(void *pjv, short *stop, short *do_update, float *prog
struct SeqIndexBuildContext *context = link->data;
BKE_sequencer_proxy_rebuild(context, stop, do_update, progress);
-
+
if (*stop) {
pj->stop = 1;
fprintf(stderr, "Canceling proxy rebuild on users request...\n");
@@ -181,12 +182,13 @@ 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;
-
+
if (ed == NULL) {
return;
}
@@ -198,7 +200,8 @@ static void seq_proxy_build_job(const bContext *C)
if (!pj) {
pj = MEM_callocN(sizeof(ProxyJob), "proxy rebuild job");
-
+
+ pj->depsgraph = depsgraph;
pj->scene = scene;
pj->main = CTX_data_main(C);
@@ -211,13 +214,13 @@ static void seq_proxy_build_job(const bContext *C)
SEQP_BEGIN (ed, seq)
{
if ((seq->flag & SELECT)) {
- BKE_sequencer_proxy_rebuild_context(pj->main, pj->scene, seq, file_list, &pj->queue);
+ 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);
-
+
if (!WM_jobs_is_running(wm_job)) {
G.is_break = false;
WM_jobs_start(CTX_wm_manager(C), wm_job);
@@ -244,7 +247,7 @@ void boundbox_seq(Scene *scene, rctf *rect)
Editing *ed = BKE_sequencer_editing_get(scene, false);
float min[2], max[2];
-
+
if (ed == NULL) return;
min[0] = 0.0;
@@ -273,18 +276,18 @@ static int mouse_frame_side(View2D *v2d, short mouse_x, int frame)
{
int mval[2];
float mouseloc[2];
-
+
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]);
-
+
return mouseloc[0] > frame ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT;
}
-Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int sel)
+Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int sel)
{
/* sel - 0==unselected, 1==selected, -1==done care*/
Sequence *seq;
@@ -293,7 +296,7 @@ Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int se
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) &&
@@ -316,16 +319,16 @@ Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int se
return NULL;
}
-static Sequence *find_next_prev_sequence(Scene *scene, Sequence *test, int lr, int sel)
+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;
@@ -336,7 +339,7 @@ static Sequence *find_next_prev_sequence(Scene *scene, Sequence *test, int lr, i
((sel == -1) || (sel == (seq->flag & SELECT))))
{
dist = MAXFRAME * 2;
-
+
switch (lr) {
case SEQ_SIDE_LEFT:
if (seq->enddisp <= test->startdisp) {
@@ -349,7 +352,7 @@ static Sequence *find_next_prev_sequence(Scene *scene, Sequence *test, int lr, i
}
break;
}
-
+
if (dist == 0) {
best_seq = seq;
break;
@@ -375,15 +378,15 @@ Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[
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 */
@@ -391,23 +394,23 @@ Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[
((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);
-
+
if (displen / pixelx > 16) { /* don't even try to grab the handles of small strips */
/* 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)
@@ -445,7 +448,7 @@ void ED_sequencer_deselect_all(Scene *scene)
Sequence *seq;
Editing *ed = BKE_sequencer_editing_get(scene, false);
-
+
if (ed == NULL) return;
SEQP_BEGIN (ed, seq)
@@ -453,7 +456,7 @@ void ED_sequencer_deselect_all(Scene *scene)
seq->flag &= ~SEQ_ALLSEL;
}
SEQ_END
-
+
}
void recurs_sel_seq(Sequence *seqm)
@@ -518,7 +521,7 @@ int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequen
{
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq1 = NULL, *seq2 = NULL, *seq3 = NULL, *seq;
-
+
*error_str = NULL;
if (!activeseq)
@@ -549,7 +552,7 @@ int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequen
seq2 = seq3;
seq3 = tmp;
}
-
+
switch (BKE_sequence_effect_get_num_inputs(type)) {
case 0:
@@ -571,12 +574,12 @@ int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequen
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;
@@ -688,7 +691,7 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe)
/* 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 */
@@ -730,7 +733,7 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe)
skip_dup = true;
}
}
-
+
BKE_sequence_reload_new_file(scene, seq, false);
BKE_sequence_calc(scene, seq);
@@ -738,7 +741,7 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe)
/* Duplicate AFTER the first change */
seqn = BKE_sequence_dupli_recursive(scene, scene, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM);
}
-
+
if (seqn) {
seqn->flag |= SELECT;
@@ -840,14 +843,14 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe)
skip_dup = true;
}
}
-
+
BKE_sequence_calc(scene, seq);
if (!skip_dup) {
/* Duplicate AFTER the first change */
seqn = BKE_sequence_dupli_recursive(scene, scene, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM);
}
-
+
if (seqn) {
seqn->flag |= SELECT;
@@ -889,7 +892,7 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe)
/* like duplicate, but only duplicate and cut overlapping strips,
- * strips to the left of the cutframe are ignored and strips to the right
+ * strips to the left of the cutframe are ignored and strips to the right
* are moved to the end of slist
* we have to work on the same slist (not using a separate list), since
* otherwise dupli_seq can't check for duplicate names properly and
@@ -901,14 +904,14 @@ static bool cut_seq_list(Scene *scene, ListBase *slist, int cutframe,
{
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 &&
+ if (cutframe > seq->startdisp &&
cutframe < seq->enddisp)
{
Sequence *seqn = cut_seq(scene, seq, cutframe);
@@ -946,7 +949,7 @@ static bool sequence_offset_after_frame(Scene *scene, const int delta, const int
TimeMarker *marker;
/* all strips >= cfra are shifted */
-
+
if (ed == NULL) return 0;
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
@@ -974,7 +977,7 @@ static void set_filter_seq(Scene *scene)
Sequence *seq;
Editing *ed = BKE_sequencer_editing_get(scene, false);
-
+
if (ed == NULL) return;
if (okee("Set Deinterlace") == 0) return;
@@ -999,32 +1002,32 @@ 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;
-
+
BLI_strncpy(from, last_seq->strip->dir, sizeof(from));
// XXX if (0 == sbutton(from, 0, sizeof(from) - 1, "From: "))
// return;
-
+
BLI_strncpy(to, from, sizeof(to));
// XXX if (0 == sbutton(to, 0, sizeof(to) - 1, "To: "))
// return;
-
+
if (STREQ(to, from))
return;
-
+
SEQP_BEGIN (ed, seq)
{
if (seq->flag & SELECT) {
if (STREQLEN(seq->strip->dir, from, strlen(from))) {
printf("found %s\n", seq->strip->dir);
-
+
/* 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);
@@ -1032,7 +1035,7 @@ static void UNUSED_FUNCTION(seq_remap_paths) (Scene *scene)
}
}
SEQ_END
-
+
}
@@ -1048,7 +1051,7 @@ static int sequencer_gap_remove_exec(bContext *C, wmOperator *op)
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)) {
@@ -1073,7 +1076,7 @@ static int sequencer_gap_remove_exec(bContext *C, wmOperator *op)
}
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-
+
return OPERATOR_FINISHED;
}
@@ -1085,15 +1088,15 @@ void SEQUENCER_OT_gap_remove(struct wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
RNA_def_boolean(ot->srna, "all", 0, "All Gaps", "Do all gaps to right of current frame");
}
@@ -1101,13 +1104,13 @@ static int sequencer_gap_insert_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
int frames = RNA_int_get(op->ptr, "frames");
-
+
sequence_offset_after_frame(scene, frames, CFRA);
-
+
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-
+
return OPERATOR_FINISHED;
-
+
}
void SEQUENCER_OT_gap_insert(struct wmOperatorType *ot)
@@ -1116,15 +1119,15 @@ void SEQUENCER_OT_gap_insert(struct wmOperatorType *ot)
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;
-
+
/* 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);
}
@@ -1136,7 +1139,7 @@ static int seq_get_snaplimit(View2D *v2d)
* 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;
@@ -1189,7 +1192,7 @@ int sequencer_view_strips_poll(bContext *C)
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;
@@ -1231,31 +1234,31 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op)
}
}
else if (seq->type & SEQ_TYPE_EFFECT) {
- if (seq->seq1 && (seq->seq1->flag & SELECT))
+ if (seq->seq1 && (seq->seq1->flag & SELECT))
BKE_sequence_calc(scene, seq);
- else if (seq->seq2 && (seq->seq2->flag & SELECT))
+ else if (seq->seq2 && (seq->seq2->flag & SELECT))
BKE_sequence_calc(scene, seq);
- else if (seq->seq3 && (seq->seq3->flag & SELECT))
+ 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);
-
+
int snap_frame;
-
+
snap_frame = CFRA;
-
+
RNA_int_set(op->ptr, "frame", snap_frame);
return sequencer_snap_exec(C, op);
}
@@ -1266,15 +1269,15 @@ void SEQUENCER_OT_snap(struct wmOperatorType *ot)
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;
-
+
/* 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);
}
@@ -1531,7 +1534,7 @@ static void sequencer_slip_update_header(Scene *scene, ScrArea *sa, SlipData *da
}
}
- ED_area_headerprint(sa, msg);
+ ED_area_status_text(sa, msg);
}
static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *event)
@@ -1602,7 +1605,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
MEM_freeN(data);
op->customdata = NULL;
if (sa) {
- ED_area_headerprint(sa, NULL);
+ ED_area_status_text(sa, NULL);
}
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@@ -1635,7 +1638,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
if (sa) {
- ED_area_headerprint(sa, NULL);
+ ED_area_status_text(sa, NULL);
}
return OPERATOR_CANCELLED;
@@ -1705,7 +1708,7 @@ static int sequencer_mute_exec(bContext *C, wmOperator *op)
bool selected;
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 */
@@ -1722,10 +1725,10 @@ static int sequencer_mute_exec(bContext *C, wmOperator *op)
}
}
}
-
+
BKE_sequencer_update_muting(ed);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-
+
return OPERATOR_FINISHED;
}
@@ -1735,14 +1738,14 @@ void SEQUENCER_OT_mute(struct wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Mute unselected rather than selected strips");
}
@@ -1756,7 +1759,7 @@ static int sequencer_unmute_exec(bContext *C, wmOperator *op)
bool selected;
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 */
@@ -1773,10 +1776,10 @@ static int sequencer_unmute_exec(bContext *C, wmOperator *op)
}
}
}
-
+
BKE_sequencer_update_muting(ed);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-
+
return OPERATOR_FINISHED;
}
@@ -1786,14 +1789,14 @@ void SEQUENCER_OT_unmute(struct wmOperatorType *ot)
ot->name = "Un-Mute Strips";
ot->idname = "SEQUENCER_OT_unmute";
ot->description = "Unmute (un)selected strips";
-
+
/* api callbacks */
ot->exec = sequencer_unmute_exec;
ot->poll = sequencer_edit_poll;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Unmute unselected rather than selected strips");
}
@@ -1822,11 +1825,11 @@ void SEQUENCER_OT_lock(struct wmOperatorType *ot)
ot->name = "Lock Strips";
ot->idname = "SEQUENCER_OT_lock";
ot->description = "Lock the active strip so that it can't be transformed";
-
+
/* api callbacks */
ot->exec = sequencer_lock_exec;
ot->poll = sequencer_edit_poll;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1855,11 +1858,11 @@ void SEQUENCER_OT_unlock(struct wmOperatorType *ot)
ot->name = "UnLock Strips";
ot->idname = "SEQUENCER_OT_unlock";
ot->description = "Unlock the active strip so that it can't be transformed";
-
+
/* api callbacks */
ot->exec = sequencer_unlock_exec;
ot->poll = sequencer_edit_poll;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1897,11 +1900,11 @@ void SEQUENCER_OT_reload(struct wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER; /* no undo, the data changed is stored outside 'main' */
@@ -1937,7 +1940,7 @@ void SEQUENCER_OT_refresh_all(struct wmOperatorType *ot)
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;
@@ -2058,14 +2061,14 @@ static int sequencer_cut_exec(bContext *C, wmOperator *op)
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;
@@ -2118,7 +2121,7 @@ static int sequencer_cut_invoke(bContext *C, wmOperator *op, const wmEvent *even
if (ED_operator_sequencer_active(C) && v2d)
cut_side = mouse_frame_side(v2d, event->mval[0], cut_frame);
-
+
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 */
@@ -2133,15 +2136,15 @@ void SEQUENCER_OT_cut(struct wmOperatorType *ot)
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;
-
+
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");
RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_BOTH, "Side", "The side that remains selected after cutting");
@@ -2193,14 +2196,14 @@ void SEQUENCER_OT_duplicate(wmOperatorType *ot)
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;
-
+
/* 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", "");
}
@@ -2261,7 +2264,7 @@ static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op))
}
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-
+
return OPERATOR_FINISHED;
}
@@ -2287,12 +2290,12 @@ void SEQUENCER_OT_delete(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -2355,7 +2358,7 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
{
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;
@@ -2425,7 +2428,7 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
/* as last: */
BKE_sequencer_sort(scene);
-
+
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@@ -2438,12 +2441,12 @@ void SEQUENCER_OT_images_separate(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -2529,11 +2532,11 @@ void SEQUENCER_OT_meta_toggle(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -2544,7 +2547,7 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
{
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;
@@ -2576,7 +2579,7 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
seqm->strip = MEM_callocN(sizeof(Strip), "metastrip");
seqm->strip->us = 1;
-
+
BKE_sequencer_active_set(scene, seqm);
if (BKE_sequence_test_overlap(ed->seqbasep, seqm) ) BKE_sequence_base_shuffle(ed->seqbasep, seqm, scene);
@@ -2596,11 +2599,11 @@ void SEQUENCER_OT_meta_make(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -2669,11 +2672,11 @@ void SEQUENCER_OT_meta_separate(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -2695,11 +2698,11 @@ void SEQUENCER_OT_view_all(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER;
}
@@ -2708,7 +2711,7 @@ 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);
-
+
return OPERATOR_FINISHED;
}
@@ -2718,11 +2721,11 @@ void SEQUENCER_OT_view_frame(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -2742,7 +2745,7 @@ static int sequencer_view_all_preview_exec(bContext *C, wmOperator *UNUSED(op))
v2d->cur = v2d->tot;
UI_view2d_curRect_validate(v2d);
UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY);
-
+
#if 0
/* Like zooming on an image view */
float zoomX, zoomY;
@@ -2784,11 +2787,11 @@ void SEQUENCER_OT_view_all_preview(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER;
}
@@ -2859,11 +2862,11 @@ void SEQUENCER_OT_view_toggle(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER;
}
@@ -2904,7 +2907,7 @@ static int sequencer_view_selected_exec(bContext *C, wmOperator *op)
if (ymax != 0) {
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
-
+
xmax += xmargin;
xmin -= xmargin;
ymax += ymargin;
@@ -2933,7 +2936,7 @@ static int sequencer_view_selected_exec(bContext *C, wmOperator *op)
else {
return OPERATOR_CANCELLED;
}
-
+
}
void SEQUENCER_OT_view_selected(wmOperatorType *ot)
@@ -2942,11 +2945,11 @@ void SEQUENCER_OT_view_selected(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER;
}
@@ -2958,7 +2961,7 @@ static bool strip_jump_internal(Scene *scene,
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;
@@ -2989,7 +2992,7 @@ static int sequencer_strip_jump_exec(bContext *C, wmOperator *op)
}
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
-
+
return OPERATOR_FINISHED;
}
@@ -3006,7 +3009,7 @@ void SEQUENCER_OT_strip_jump(wmOperatorType *ot)
/* 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", "");
@@ -3058,9 +3061,9 @@ static int sequencer_swap_exec(bContext *C, wmOperator *op)
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;
@@ -3068,10 +3071,10 @@ static int sequencer_swap_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
switch (side) {
- case SEQ_SIDE_LEFT:
+ case SEQ_SIDE_LEFT:
swap_sequence(scene, seq, active_seq);
break;
- case SEQ_SIDE_RIGHT:
+ case SEQ_SIDE_RIGHT:
swap_sequence(scene, active_seq, seq);
break;
}
@@ -3111,14 +3114,14 @@ void SEQUENCER_OT_swap(wmOperatorType *ot)
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;
-
+
/* 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");
}
@@ -3170,14 +3173,14 @@ void SEQUENCER_OT_rendersize(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
}
@@ -3456,17 +3459,18 @@ static int sequencer_rebuild_proxy_invoke(bContext *C, wmOperator *UNUSED(op),
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;
-
+
if (ed == NULL) {
return OPERATOR_CANCELLED;
}
file_list = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "file list");
-
+
SEQP_BEGIN(ed, seq)
{
if ((seq->flag & SELECT)) {
@@ -3475,7 +3479,7 @@ static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
short stop = 0, do_update;
float progress;
- BKE_sequencer_proxy_rebuild_context(bmain, 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;
@@ -3488,7 +3492,7 @@ static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
SEQ_END
BLI_gset_free(file_list, MEM_freeN);
-
+
return OPERATOR_FINISHED;
}
@@ -3498,11 +3502,11 @@ void SEQUENCER_OT_rebuild_proxy(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER;
}
@@ -3539,27 +3543,27 @@ static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op)
if (proxy_25)
seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_25;
- else
+ 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
+ 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
+ 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
+ else
seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_100;
-
+
if (!overwrite)
seq->strip->proxy->build_flags |= SEQ_PROXY_SKIP_EXISTING;
- else
+ else
seq->strip->proxy->build_flags &= ~SEQ_PROXY_SKIP_EXISTING;
}
}
@@ -3567,7 +3571,7 @@ static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op)
SEQ_END
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-
+
return OPERATOR_FINISHED;
}
@@ -3577,14 +3581,14 @@ void SEQUENCER_OT_enable_proxies(wmOperatorType *ot)
ot->name = "Set Selected Strip Proxies";
ot->idname = "SEQUENCER_OT_enable_proxies";
ot->description = "Enable selected proxies on all selected Movie strips";
-
+
/* api callbacks */
ot->invoke = sequencer_enable_proxies_invoke;
ot->exec = sequencer_enable_proxies_exec;
-
+
/* 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%", "");
@@ -3749,7 +3753,7 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op)
/* 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, bmain->name);
+ BLI_path_rel(directory, BKE_main_blendfile_path(bmain));
}
BLI_strncpy(seq->strip->dir, directory, sizeof(seq->strip->dir));
@@ -3861,15 +3865,16 @@ void SEQUENCER_OT_change_path(struct wmOperatorType *ot)
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];
- if (G.main->name[0] == 0)
+ if (BKE_main_blendfile_path(bmain)[0] == '\0')
BLI_strncpy(filepath, "untitled", sizeof(filepath));
else
- BLI_strncpy(filepath, G.main->name, sizeof(filepath));
+ BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath));
- BLI_replace_extension(filepath, sizeof(filepath), ".srt");
+ BLI_path_extension_replace(filepath, sizeof(filepath), ".srt");
RNA_string_set(op->ptr, "filepath", filepath);
}
@@ -3894,7 +3899,7 @@ static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op)
}
RNA_string_get(op->ptr, "filepath", filepath);
- BLI_ensure_extension(filepath, sizeof(filepath), ".srt");
+ BLI_path_extension_ensure(filepath, sizeof(filepath), ".srt");
/* Avoid File write exceptions */
if (!BLI_exists(filepath)) {
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index de7c46cc02c..7c5bbbf52c6 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation, Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
@@ -63,7 +63,7 @@ void sequencer_special_update_set(Sequence *seq);
/* UNUSED */
// void seq_reset_imageofs(struct SpaceSeq *sseq);
-struct ImBuf *sequencer_ibuf_get(struct Main *bmain, 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;
@@ -174,7 +174,7 @@ enum {
SEQ_SELECT_LR_NONE = 0,
SEQ_SELECT_LR_MOUSE,
SEQ_SELECT_LR_LEFT,
- SEQ_SELECT_LR_RIGHT
+ SEQ_SELECT_LR_RIGHT
};
/* defines used internally */
@@ -212,4 +212,3 @@ int sequencer_image_seq_get_minmax_frame(struct wmOperator *op, int sfra, int *r
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 7ab9308f9a6..107169a48d8 100644
--- a/source/blender/editors/space_sequencer/sequencer_modifier.c
+++ b/source/blender/editors/space_sequencer/sequencer_modifier.c
@@ -281,4 +281,3 @@ void SEQUENCER_OT_strip_modifier_copy(wmOperatorType *ot)
/* 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 a3cfcae77b8..80d9cdcc0e7 100644
--- a/source/blender/editors/space_sequencer/sequencer_ops.c
+++ b/source/blender/editors/space_sequencer/sequencer_ops.c
@@ -68,7 +68,7 @@ void sequencer_operatortypes(void)
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);
@@ -135,7 +135,7 @@ void sequencer_keymap(wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
wmKeyMapItem *kmi;
-
+
/* Common items ------------------------------------------------------------------ */
keymap = WM_keymap_find(keyconf, "SequencerCommon", SPACE_SEQ, 0);
@@ -183,7 +183,9 @@ void sequencer_keymap(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "SEQUENCER_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "SEQUENCER_OT_delete", XKEY, KM_PRESS, 0, 0);
+#endif
WM_keymap_add_item(keymap, "SEQUENCER_OT_delete", DELKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "SEQUENCER_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
@@ -228,7 +230,7 @@ void sequencer_keymap(wmKeyConfig *keyconf)
RNA_boolean_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_gap_remove", BACKSPACEKEY, KM_PRESS, 0, 0)->ptr, "all", false);
RNA_boolean_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_gap_remove", BACKSPACEKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "all", true);
WM_keymap_add_item(keymap, "SEQUENCER_OT_gap_insert", EQUALKEY, KM_PRESS, KM_SHIFT, 0);
-
+
WM_keymap_add_item(keymap, "SEQUENCER_OT_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "SEQUENCER_OT_swap_inputs", SKEY, KM_PRESS, KM_ALT, 0);
diff --git a/source/blender/editors/space_sequencer/sequencer_preview.c b/source/blender/editors/space_sequencer/sequencer_preview.c
index 3f908dc7096..c58c05b67c0 100644
--- a/source/blender/editors/space_sequencer/sequencer_preview.c
+++ b/source/blender/editors/space_sequencer/sequencer_preview.c
@@ -80,11 +80,11 @@ static void preview_startjob(void *data, short *stop, short *do_update, float *p
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) {
@@ -98,12 +98,12 @@ static void preview_startjob(void *data, short *stop, short *do_update, float *p
BLI_spin_lock(sound->spinlock);
sound->flags &= ~SOUND_FLAGS_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;
@@ -111,12 +111,12 @@ static void preview_startjob(void *data, short *stop, short *do_update, float *p
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++;
+ pj->processed++;
*progress = (pj->total > 0) ? (float)pj->processed / (float)pj->total : 1.0f;
*do_update = true;
BLI_mutex_unlock(pj->mutex);
@@ -145,19 +145,19 @@ void sequencer_preview_add_sound(const bContext *C, Sequence *seq)
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++;
@@ -168,5 +168,5 @@ void sequencer_preview_add_sound(const bContext *C, Sequence *seq)
WM_jobs_start(CTX_wm_manager(C), wm_job);
}
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(sa);
}
diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c
index 8c57089f7ab..00811d68251 100644
--- a/source/blender/editors/space_sequencer/sequencer_scopes.c
+++ b/source/blender/editors/space_sequencer/sequencer_scopes.c
@@ -160,7 +160,7 @@ static ImBuf *make_waveform_view_from_ibuf_byte(ImBuf *ibuf)
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);
}
@@ -229,7 +229,7 @@ static ImBuf *make_waveform_view_from_ibuf_float(ImBuf *ibuf)
}
wform_put_border(tgt, w, h);
-
+
return rval;
}
@@ -285,7 +285,7 @@ static ImBuf *make_sep_waveform_view_from_ibuf_byte(ImBuf *ibuf)
}
wform_put_border(tgt, w, h);
-
+
return rval;
}
@@ -334,7 +334,7 @@ static ImBuf *make_sep_waveform_view_from_ibuf_float(ImBuf *ibuf)
}
wform_put_border(tgt, w, h);
-
+
return rval;
}
@@ -542,7 +542,7 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf)
}
wform_put_border((unsigned char *) rval->rect, rval->x, rval->y);
-
+
return rval;
}
@@ -610,7 +610,7 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf)
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);
@@ -622,11 +622,11 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf)
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;
}
@@ -653,7 +653,7 @@ static void vectorscope_put_cross(unsigned char r, unsigned char g, unsigned ch
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)));
@@ -698,12 +698,12 @@ static ImBuf *make_vectorscope_view_from_ibuf_byte(ImBuf *ibuf)
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);
@@ -744,7 +744,7 @@ static ImBuf *make_vectorscope_view_from_ibuf_float(ImBuf *ibuf)
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);
@@ -752,7 +752,7 @@ static ImBuf *make_vectorscope_view_from_ibuf_float(ImBuf *ibuf)
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);
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index 90a369760ac..1ec9ea53e33 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -59,11 +59,11 @@ static void *find_nearest_marker(int UNUSED(d1), int UNUSED(d2))
{
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
@@ -152,10 +152,10 @@ static void select_linked_time(ListBase *seqbase, Sequence *seq_link)
void select_surround_from_last(Scene *scene)
{
Sequence *seq = get_last_seq(scene);
-
+
if (seq == NULL)
return;
-
+
select_surrounding_handles(scene, seq);
}
#endif
@@ -163,7 +163,7 @@ void select_surround_from_last(Scene *scene)
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);
@@ -264,11 +264,11 @@ void SEQUENCER_OT_select_all(struct wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -294,7 +294,7 @@ static int sequencer_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
}
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
-
+
return OPERATOR_FINISHED;
}
@@ -304,11 +304,11 @@ void SEQUENCER_OT_select_inverse(struct wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -322,16 +322,16 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
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
@@ -353,13 +353,13 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
/* deselect_markers(0, 0); */ /* XXX, in 2.4x, seq selection used to deselect all, need to re-thnik this for 2.5 */
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]);
@@ -372,7 +372,7 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
x = CFRA;
break;
}
-
+
SEQP_BEGIN (ed, seq)
{
if (((x < CFRA) && (seq->enddisp <= CFRA)) ||
@@ -408,10 +408,10 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
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);
@@ -422,7 +422,7 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
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)) {
@@ -521,7 +521,7 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
}
}
}
-
+
/* marker transform */
#if 0 // XXX probably need to redo this differently for 2.5
if (marker) {
@@ -529,7 +529,7 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
// 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) {
@@ -539,7 +539,7 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
}
}
#endif
-
+
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
/* allowing tweaks */
@@ -555,19 +555,19 @@ void SEQUENCER_OT_select(wmOperatorType *ot)
{SEQ_SELECT_LR_RIGHT, "RIGHT", 0, "Right", "Select right"},
{0, NULL, 0, NULL, NULL}
};
-
+
/* identifiers */
- ot->name = "Activate/Select";
+ 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");
@@ -584,10 +584,10 @@ static bool select_more_less_seq__internal(Scene *scene, bool sel, const bool li
Sequence *seq, *neighbor;
bool changed = false;
int isel;
-
+
if (ed == NULL)
return changed;
-
+
if (sel) {
sel = SELECT;
isel = 0;
@@ -596,14 +596,14 @@ static bool select_more_less_seq__internal(Scene *scene, bool sel, const bool li
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)) {
@@ -639,7 +639,7 @@ static bool select_more_less_seq__internal(Scene *scene, bool sel, const bool li
}
}
}
-
+
return changed;
}
@@ -649,12 +649,12 @@ static bool select_more_less_seq__internal(Scene *scene, bool sel, const bool li
static int sequencer_select_more_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
-
+
if (!select_more_less_seq__internal(scene, true, false))
return OPERATOR_CANCELLED;
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
-
+
return OPERATOR_FINISHED;
}
@@ -664,14 +664,14 @@ void SEQUENCER_OT_select_more(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
}
@@ -680,12 +680,12 @@ void SEQUENCER_OT_select_more(wmOperatorType *ot)
static int sequencer_select_less_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
-
+
if (!select_more_less_seq__internal(scene, false, false))
return OPERATOR_CANCELLED;
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
-
+
return OPERATOR_FINISHED;
}
@@ -695,14 +695,14 @@ void SEQUENCER_OT_select_less(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
}
@@ -712,9 +712,9 @@ static int sequencer_select_linked_pick_invoke(bContext *C, wmOperator *op, cons
{
Scene *scene = CTX_data_scene(C);
View2D *v2d = UI_view2d_fromcontext(C);
-
+
bool extend = RNA_boolean_get(op->ptr, "extend");
-
+
Sequence *mouse_seq;
int selected, hand;
@@ -722,20 +722,20 @@ static int sequencer_select_linked_pick_invoke(bContext *C, wmOperator *op, cons
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);
-
+
mouse_seq->flag |= SELECT;
recurs_sel_seq(mouse_seq);
-
+
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);
-
+
return OPERATOR_FINISHED;
}
@@ -745,14 +745,14 @@ void SEQUENCER_OT_select_linked_pick(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
}
@@ -780,14 +780,14 @@ void SEQUENCER_OT_select_linked(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
}
@@ -830,14 +830,14 @@ void SEQUENCER_OT_select_handles(wmOperatorType *ot)
ot->name = "Select Handles";
ot->idname = "SEQUENCER_OT_select_handles";
ot->description = "Select manipulator 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");
}
@@ -867,7 +867,7 @@ void SEQUENCER_OT_select_active_side(wmOperatorType *ot)
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;
@@ -886,7 +886,7 @@ static int sequencer_borderselect_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Editing *ed = BKE_sequencer_editing_get(scene, false);
View2D *v2d = UI_view2d_fromcontext(C);
-
+
Sequence *seq;
rctf rectf, rq;
const bool select = !RNA_boolean_get(op->ptr, "deselect");
@@ -900,7 +900,7 @@ static int sequencer_borderselect_exec(bContext *C, wmOperator *op)
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
seq_rectf(seq, &rq);
-
+
if (BLI_rctf_isect(&rq, &rectf, NULL)) {
if (select) seq->flag |= SELECT;
else seq->flag &= ~SEQ_ALLSEL;
@@ -915,7 +915,7 @@ static int sequencer_borderselect_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
return OPERATOR_FINISHED;
-}
+}
/* ****** Border Select ****** */
@@ -925,18 +925,18 @@ void SEQUENCER_OT_select_border(wmOperatorType *ot)
ot->name = "Border Select";
ot->idname = "SEQUENCER_OT_select_border";
ot->description = "Select strips using border selection";
-
+
/* api callbacks */
ot->invoke = WM_gesture_border_invoke;
ot->exec = sequencer_borderselect_exec;
ot->modal = WM_gesture_border_modal;
ot->cancel = WM_gesture_border_cancel;
-
+
ot->poll = ED_operator_sequencer_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* rna */
WM_operator_properties_gesture_border_select(ot);
}
@@ -1267,19 +1267,18 @@ void SEQUENCER_OT_select_grouped(wmOperatorType *ot)
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 4d6ea865b40..88dcc3a8821 100644
--- a/source/blender/editors/space_sequencer/sequencer_view.c
+++ b/source/blender/editors/space_sequencer/sequencer_view.c
@@ -91,13 +91,14 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info)
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, scene, sseq, CFRA, 0, NULL);
+ 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;
@@ -121,7 +122,7 @@ static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event)
info->colp = NULL;
info->colfp = NULL;
-
+
if (ibuf->rect) {
cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x);
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 4e78e056093..756d8de927a 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -82,28 +82,28 @@ ARegion *sequencer_has_buttons_region(ScrArea *sa)
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);
/* is error! */
if (ar == NULL) return NULL;
-
+
arnew = MEM_callocN(sizeof(ARegion), "buttons for sequencer");
-
+
BLI_insertlinkafter(&sa->regionbase, ar, arnew);
arnew->regiontype = RGN_TYPE_UI;
arnew->alignment = RGN_ALIGN_RIGHT;
-
+
arnew->flag = RGN_FLAG_HIDDEN;
-
+
return arnew;
}
static ARegion *sequencer_find_region(ScrArea *sa, short type)
{
ARegion *ar = NULL;
-
+
for (ar = sa->regionbase.first; ar; ar = ar->next)
if (ar->regiontype == type)
return ar;
@@ -117,7 +117,7 @@ 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;
@@ -127,19 +127,19 @@ static SpaceLink *sequencer_new(const ScrArea *UNUSED(sa), const Scene *scene)
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for sequencer");
-
+
BLI_addtail(&sseq->regionbase, ar);
ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = RGN_ALIGN_BOTTOM;
-
+ ar->alignment = 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");
@@ -166,26 +166,26 @@ static SpaceLink *sequencer_new(const ScrArea *UNUSED(sa), const Scene *scene)
/* 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;
@@ -200,7 +200,7 @@ static SpaceLink *sequencer_new(const ScrArea *UNUSED(sa), const Scene *scene)
/* not spacelink itself */
static void sequencer_free(SpaceLink *sl)
-{
+{
SpaceSeq *sseq = (SpaceSeq *) sl;
SequencerScopes *scopes = &sseq->scopes;
@@ -226,7 +226,7 @@ static void sequencer_free(SpaceLink *sl)
/* spacetype; init callback */
static void sequencer_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
{
-
+
}
static void sequencer_refresh(const bContext *C, ScrArea *sa)
@@ -330,7 +330,7 @@ static void sequencer_refresh(const bContext *C, ScrArea *sa)
static SpaceLink *sequencer_duplicate(SpaceLink *sl)
{
SpaceSeq *sseqn = MEM_dupallocN(sl);
-
+
/* clear or remove stuff from old */
// XXX sseq->gpd = gpencil_data_duplicate(sseq->gpd, false);
@@ -418,7 +418,7 @@ static void sequencer_drop_copy(wmDrag *drag, wmDropBox *drop)
char dir[FILE_MAX], file[FILE_MAX];
BLI_split_dirfile(drag->path, dir, file, sizeof(dir), sizeof(file));
-
+
RNA_string_set(drop->ptr, "directory", dir);
RNA_collection_clear(drop->ptr, "files");
@@ -529,7 +529,7 @@ static void sequencer_main_region_listener(
ED_region_tag_redraw(ar);
break;
case NC_SCREEN:
- if (ELEM(wmn->data, ND_SCREENCAST, ND_ANIMPLAY))
+ if (ELEM(wmn->data, ND_ANIMPLAY))
ED_region_tag_redraw(ar);
break;
}
@@ -708,7 +708,7 @@ static void sequencer_buttons_region_init(wmWindowManager *wm, ARegion *ar)
static void sequencer_buttons_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
static void sequencer_buttons_region_listener(
diff --git a/source/blender/editors/space_statusbar/CMakeLists.txt b/source/blender/editors/space_statusbar/CMakeLists.txt
new file mode 100644
index 00000000000..31439942397
--- /dev/null
+++ b/source/blender/editors/space_statusbar/CMakeLists.txt
@@ -0,0 +1,45 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# Contributor(s): Jacques Beaurain.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blenloader
+ ../../blentranslation
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
+)
+
+set(INC_SYS
+ ${GLEW_INCLUDE_PATH}
+)
+
+set(SRC
+ space_statusbar.c
+)
+
+add_definitions(${GL_DEFINITIONS})
+
+blender_add_lib(bf_editor_space_statusbar "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/space_statusbar/space_statusbar.c b/source/blender/editors/space_statusbar/space_statusbar.c
new file mode 100644
index 00000000000..5ff32b98f90
--- /dev/null
+++ b/source/blender/editors/space_statusbar/space_statusbar.c
@@ -0,0 +1,187 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_statusbar/space_statusbar.c
+ * \ingroup spstatusbar
+ */
+
+
+#include <string.h>
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "ED_screen.h"
+#include "ED_space_api.h"
+
+#include "RNA_access.h"
+
+#include "UI_interface.h"
+#include "UI_view2d.h"
+
+#include "WM_api.h"
+#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;
+
+ 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;
+
+ 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);
+
+ /* clear or remove stuff from old */
+
+ 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);
+}
+
+static void statusbar_operatortypes(void)
+{
+
+}
+
+static void statusbar_keymap(struct wmKeyConfig *UNUSED(keyconf))
+{
+
+}
+
+static void statusbar_header_region_listener(
+ bScreen *UNUSED(sc), 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;
+ }
+}
+
+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);
+}
+
+/* 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);
+}
diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c
index c0324908b60..8a83f25f093 100644
--- a/source/blender/editors/space_text/space_text.c
+++ b/source/blender/editors/space_text/space_text.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -59,6 +59,7 @@
#include "text_format.h"
#include "text_intern.h" /* own include */
+#include "GPU_framebuffer.h"
/* ******************** default callbacks for text space ***************** */
@@ -66,20 +67,20 @@ static SpaceLink *text_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scen
{
ARegion *ar;
SpaceText *stext;
-
+
stext = MEM_callocN(sizeof(SpaceText), "inittext");
stext->spacetype = SPACE_TEXT;
stext->lheight = 12;
stext->tabnumber = 4;
stext->margin_column = 80;
-
+
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for text");
-
+
BLI_addtail(&stext->regionbase, ar);
ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = RGN_ALIGN_BOTTOM;
+ ar->alignment = RGN_ALIGN_TOP;
/* properties region */
ar = MEM_callocN(sizeof(ARegion), "properties region for text");
@@ -91,18 +92,18 @@ static SpaceLink *text_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scen
/* main region */
ar = MEM_callocN(sizeof(ARegion), "main region for text");
-
+
BLI_addtail(&stext->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
-
+
return (SpaceLink *)stext;
}
/* not spacelink itself */
static void text_free(SpaceLink *sl)
-{
+{
SpaceText *stext = (SpaceText *) sl;
-
+
stext->text = NULL;
text_free_caches(stext);
}
@@ -205,7 +206,7 @@ static void text_operatortypes(void)
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);
@@ -231,7 +232,7 @@ static void text_operatortypes(void)
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);
@@ -243,7 +244,7 @@ static void text_keymap(struct wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
wmKeyMapItem *kmi;
-
+
keymap = WM_keymap_find(keyconf, "Text Generic", SPACE_TEXT, 0);
WM_keymap_add_item(keymap, "TEXT_OT_start_find", FKEY, KM_PRESS, KM_CTRL, 0);
#ifdef __APPLE__
@@ -255,7 +256,7 @@ static void text_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "TEXT_OT_properties", TKEY, KM_PRESS, KM_CTRL, 0);
keymap = WM_keymap_find(keyconf, "Text", SPACE_TEXT, 0);
-
+
#ifdef __APPLE__
RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", LEFTARROWKEY, KM_PRESS, KM_OSKEY, 0)->ptr, "type", LINE_BEGIN);
RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", RIGHTARROWKEY, KM_PRESS, KM_OSKEY, 0)->ptr, "type", LINE_END);
@@ -263,30 +264,30 @@ static void text_keymap(struct wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", RIGHTARROWKEY, KM_PRESS, KM_ALT, 0)->ptr, "type", NEXT_WORD);
RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", UPARROWKEY, KM_PRESS, KM_OSKEY, 0)->ptr, "type", FILE_TOP);
RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", DOWNARROWKEY, KM_PRESS, KM_OSKEY, 0)->ptr, "type", FILE_BOTTOM);
-
+
RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", LEFTARROWKEY, KM_PRESS, KM_SHIFT | KM_OSKEY, 0)->ptr, "type", LINE_BEGIN);
RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", RIGHTARROWKEY, KM_PRESS, KM_SHIFT | KM_OSKEY, 0)->ptr, "type", LINE_END);
RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", LEFTARROWKEY, KM_PRESS, KM_SHIFT | KM_ALT, 0)->ptr, "type", PREV_WORD);
RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", RIGHTARROWKEY, KM_PRESS, KM_SHIFT | KM_ALT, 0)->ptr, "type", NEXT_WORD);
RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", UPARROWKEY, KM_PRESS, KM_SHIFT | KM_OSKEY, 0)->ptr, "type", FILE_TOP);
RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", DOWNARROWKEY, KM_PRESS, KM_SHIFT | KM_OSKEY, 0)->ptr, "type", FILE_BOTTOM);
-
+
RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_delete", BACKSPACEKEY, KM_PRESS, KM_ALT, 0)->ptr, "type", DEL_PREV_WORD);
-
+
WM_keymap_add_item(keymap, "TEXT_OT_save", SKEY, KM_PRESS, KM_ALT | KM_OSKEY, 0);
WM_keymap_add_item(keymap, "TEXT_OT_save_as", SKEY, KM_PRESS, KM_ALT | KM_SHIFT | KM_OSKEY, 0);
WM_keymap_add_item(keymap, "TEXT_OT_cut", XKEY, KM_PRESS, KM_OSKEY, 0);
- WM_keymap_add_item(keymap, "TEXT_OT_copy", CKEY, KM_PRESS, KM_OSKEY, 0);
+ WM_keymap_add_item(keymap, "TEXT_OT_copy", CKEY, KM_PRESS, KM_OSKEY, 0);
WM_keymap_add_item(keymap, "TEXT_OT_paste", VKEY, KM_PRESS, KM_OSKEY, 0);
WM_keymap_add_item(keymap, "TEXT_OT_find_set_selected", EKEY, KM_PRESS, KM_OSKEY, 0);
WM_keymap_add_item(keymap, "TEXT_OT_select_all", AKEY, KM_PRESS, KM_OSKEY, 0);
WM_keymap_add_item(keymap, "TEXT_OT_select_line", AKEY, KM_PRESS, KM_SHIFT | KM_OSKEY, 0);
#endif
-
+
kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", WHEELUPMOUSE, KM_PRESS, KM_CTRL, 0);
RNA_string_set(kmi->ptr, "data_path", "space_data.font_size");
RNA_boolean_set(kmi->ptr, "reverse", false);
-
+
kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL, 0);
RNA_string_set(kmi->ptr, "data_path", "space_data.font_size");
RNA_boolean_set(kmi->ptr, "reverse", true);
@@ -294,19 +295,23 @@ static void text_keymap(struct wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
RNA_string_set(kmi->ptr, "data_path", "space_data.font_size");
RNA_boolean_set(kmi->ptr, "reverse", false);
-
+
kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", PADMINUS, KM_PRESS, KM_CTRL, 0);
RNA_string_set(kmi->ptr, "data_path", "space_data.font_size");
RNA_boolean_set(kmi->ptr, "reverse", true);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "TEXT_OT_new", NKEY, KM_PRESS, KM_CTRL, 0);
+#else
+ WM_keymap_add_item(keymap, "TEXT_OT_new", NKEY, KM_PRESS, KM_ALT, 0);
+#endif
WM_keymap_add_item(keymap, "TEXT_OT_open", OKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "TEXT_OT_reload", RKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "TEXT_OT_save", SKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "TEXT_OT_save_as", SKEY, KM_PRESS, KM_ALT | KM_SHIFT | KM_CTRL, 0);
WM_keymap_add_item(keymap, "TEXT_OT_run_script", PKEY, KM_PRESS, KM_ALT, 0);
-
+
WM_keymap_add_item(keymap, "TEXT_OT_cut", XKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "TEXT_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "TEXT_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0);
@@ -314,7 +319,7 @@ static void text_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "TEXT_OT_cut", DELKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "TEXT_OT_copy", INSERTKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "TEXT_OT_paste", INSERTKEY, KM_PRESS, KM_SHIFT, 0);
-
+
WM_keymap_add_item(keymap, "TEXT_OT_duplicate_line", DKEY, KM_PRESS, KM_CTRL, 0);
if (U.uiflag & USER_MMB_PASTE) { // XXX not dynamic
@@ -328,14 +333,14 @@ static void text_keymap(struct wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_lines", UPARROWKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0)->ptr, "direction", TXT_MOVE_LINE_UP);
RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_lines", DOWNARROWKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0)->ptr, "direction", TXT_MOVE_LINE_DOWN);
-
+
WM_keymap_add_item(keymap, "TEXT_OT_indent", TABKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "TEXT_OT_unindent", TABKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "TEXT_OT_uncomment", DKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", HOMEKEY, KM_PRESS, 0, 0)->ptr, "type", LINE_BEGIN);
RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", ENDKEY, KM_PRESS, 0, 0)->ptr, "type", LINE_END);
-
+
RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", EKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", LINE_END);
RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", EKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0)->ptr, "type", LINE_END);
RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", LEFTARROWKEY, KM_PRESS, 0, 0)->ptr, "type", PREV_CHAR);
@@ -367,7 +372,7 @@ static void text_keymap(struct wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_delete", BACKSPACEKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", DEL_PREV_CHAR); /* same as above [#26623] */
RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_delete", DELKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", DEL_NEXT_WORD);
RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_delete", BACKSPACEKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", DEL_PREV_WORD);
-
+
WM_keymap_add_item(keymap, "TEXT_OT_overwrite_toggle", INSERTKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "TEXT_OT_scroll_bar", LEFTMOUSE, KM_PRESS, 0, 0);
@@ -388,7 +393,7 @@ static void text_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_menu(keymap, "TEXT_MT_toolbox", RIGHTMOUSE, KM_PRESS, KM_ANY, 0);
WM_keymap_add_item(keymap, "TEXT_OT_autocomplete", SPACEKEY, KM_PRESS, KM_CTRL, 0);
-
+
WM_keymap_add_item(keymap, "TEXT_OT_line_number", KM_TEXTINPUT, KM_ANY, KM_ANY, 0);
WM_keymap_add_item(keymap, "TEXT_OT_insert", KM_TEXTINPUT, KM_ANY, KM_ANY, 0); // last!
}
@@ -418,18 +423,18 @@ static void text_main_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
ListBase *lb;
-
+
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
-
+
/* own keymap */
keymap = WM_keymap_find(wm->defaultconf, "Text Generic", SPACE_TEXT, 0);
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
keymap = WM_keymap_find(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);
-
+
WM_event_add_dropbox_handler(&ar->handlers, lb);
}
@@ -438,19 +443,19 @@ 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;
-
+
/* clear and setup matrix */
UI_ThemeClearColor(TH_BACK);
- glClear(GL_COLOR_BUFFER_BIT);
-
+ GPU_clear(GPU_COLOR_BIT);
+
// UI_view2d_view_ortho(v2d);
-
+
/* data... */
draw_text_main(st, ar);
-
+
/* reset view matrix */
// UI_view2d_view_restore(C);
-
+
/* scrollers? */
}
@@ -510,7 +515,7 @@ static void text_drop_paste(wmDrag *drag, wmDropBox *drop)
static void text_dropboxes(void)
{
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);
}
@@ -550,9 +555,9 @@ static void text_properties_region_init(wmWindowManager *wm, ARegion *ar)
static void text_properties_region_draw(const bContext *C, ARegion *ar)
{
SpaceText *st = CTX_wm_space_text(C);
-
- ED_region_panels(C, ar, NULL, -1, true);
-
+
+ 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")) {
@@ -585,10 +590,10 @@ 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;
@@ -609,13 +614,13 @@ void ED_spacetype_text(void)
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);
@@ -625,7 +630,7 @@ void ED_spacetype_text(void)
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;
@@ -640,4 +645,3 @@ void ED_spacetype_text(void)
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 9163831c333..4f6a3bc82ba 100644
--- a/source/blender/editors/space_text/text_autocomplete.c
+++ b/source/blender/editors/space_text/text_autocomplete.c
@@ -40,7 +40,10 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_text.h"
+#include "ED_undo.h"
#include "ED_screen.h"
+
#include "UI_interface.h"
#include "text_format.h"
@@ -284,10 +287,11 @@ static int text_autocomplete_invoke(bContext *C, wmOperator *op, const wmEvent *
ED_area_tag_redraw(CTX_wm_area(C));
if (texttool_suggest_first() == texttool_suggest_last()) {
- TextUndoBuf *utxt = NULL; // FIXME
+ 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 {
@@ -315,8 +319,6 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
(void)text;
- TextUndoBuf *utxt = NULL; // FIXME
-
if (st->doplugins && texttool_text_is_active(st->text)) {
if (texttool_suggest_first()) tools |= TOOL_SUGG_LIST;
if (texttool_docs_get()) tools |= TOOL_DOCUMENT;
@@ -343,8 +345,10 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
case MIDDLEMOUSE:
if (event->val == KM_PRESS) {
if (text_do_suggest_select(st, ar)) {
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
confirm_suggestion(st->text, utxt);
text_update_line_edited(st->text->curl);
+ ED_undo_push(C, op->type->name);
swallow = 1;
}
else {
@@ -378,8 +382,10 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
case PADENTER:
if (event->val == KM_PRESS) {
if (tools & TOOL_SUGG_LIST) {
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
confirm_suggestion(st->text, utxt);
text_update_line_edited(st->text->curl);
+ ED_undo_push(C, op->type->name);
swallow = 1;
draw = 1;
}
@@ -591,5 +597,6 @@ void TEXT_OT_autocomplete(wmOperatorType *ot)
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 3949aa928c9..99305b143c6 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -50,6 +50,7 @@
#include "BIF_glutil.h"
#include "GPU_immediate.h"
+#include "GPU_state.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -113,7 +114,7 @@ static int text_font_draw_character_utf8(const TextDrawContext *tdc, int x, int
#if 0
/* Formats every line of the current text */
-static void txt_format_text(SpaceText *st)
+static void txt_format_text(SpaceText *st)
{
TextLine *linep;
@@ -170,7 +171,7 @@ static void format_draw_color(const TextDrawContext *tdc, char formatchar)
* view_width The maximum number of characters displayable in the region
* This equals region_width/font_width for the region
* wrap_chars Characters that allow wrapping. This equals [' ', '\t', '-']
- *
+ *
* def wrap(line, view_width, wrap_chars):
* draw_start = 0
* draw_end = view_width
@@ -184,14 +185,14 @@ static void format_draw_color(const TextDrawContext *tdc, char formatchar)
* draw_end = pos+1
* pos += 1
* print line[draw_start:]
- *
+ *
*/
int wrap_width(const SpaceText *st, ARegion *ar)
{
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;
@@ -358,7 +359,7 @@ void wrap_offset_in_line(const SpaceText *st, ARegion *ar, TextLine *linein, int
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;
@@ -407,11 +408,11 @@ static int text_draw_wrapped(
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) {
@@ -659,7 +660,7 @@ 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;
@@ -808,17 +809,17 @@ static void calc_text_rcts(SpaceText *st, ARegion *ar, rcti *scroll, rcti *back)
back->xmax = ar->winx;
back->ymin = 0;
back->ymax = ar->winy;
-
+
scroll->xmin = ar->winx - V2D_SCROLL_WIDTH;
scroll->xmax = ar->winx - 5;
scroll->ymin = 4;
scroll->ymax = 4 + 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;
@@ -895,7 +896,7 @@ static void calc_text_rcts(SpaceText *st, ARegion *ar, rcti *scroll, rcti *back)
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;
@@ -937,10 +938,10 @@ static void draw_documentation(const SpaceText *st, ARegion *ar)
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;
@@ -950,7 +951,7 @@ static void draw_documentation(const SpaceText *st, ARegion *ar)
/* 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;
}
@@ -1031,7 +1032,7 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc
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;
@@ -1058,7 +1059,7 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc
boxw = SUGG_LIST_WIDTH * st->cwidth + 20;
boxh = SUGG_LIST_SIZE * lheight + 8;
-
+
if (x + boxw > ar->winx)
x = MAX2(0, ar->winx - boxw);
@@ -1086,7 +1087,7 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc
BLI_strncpy(str, item->name, len + 1);
w = st->cwidth * text_get_char_pos(st, str, len);
-
+
if (item == sel) {
unsigned int posi = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -1207,10 +1208,10 @@ static void draw_text_decoration(SpaceText *st, ARegion *ar)
immUniformColor4ub(255, 255, 255, 32);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
+ 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);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
}
@@ -1247,7 +1248,7 @@ static void draw_brackets(const SpaceText *st, const TextDrawContext *tdc, ARegi
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
@@ -1266,7 +1267,7 @@ static void draw_brackets(const SpaceText *st, const TextDrawContext *tdc, ARegi
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;
@@ -1391,7 +1392,7 @@ void draw_text_main(SpaceText *st, ARegion *ar)
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);
@@ -1399,7 +1400,7 @@ void draw_text_main(SpaceText *st, ARegion *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 */
@@ -1454,7 +1455,7 @@ void draw_text_main(SpaceText *st, ARegion *ar)
}
y = ar->winy - st->lheight_dpi;
winx = ar->winx - TXT_SCROLL_WIDTH;
-
+
/* draw cursor, margin, selection and highlight */
draw_text_decoration(st, ar);
@@ -1493,20 +1494,20 @@ void draw_text_main(SpaceText *st, ARegion *ar)
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 = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
immUniform1i("num_colors", 0); /* "simple" mode */
@@ -1527,7 +1528,7 @@ void draw_text_main(SpaceText *st, ARegion *ar)
draw_textscroll(st, &scroll, &back);
/* draw_documentation(st, ar); - No longer supported */
draw_suggestion_list(st, &tdc, ar);
-
+
text_font_end(&tdc);
}
@@ -1578,7 +1579,7 @@ void text_scroll_to_cursor(SpaceText *st, ARegion *ar, const bool center)
st->top = i;
}
}
-
+
if (st->wordwrap) {
st->left = 0;
}
diff --git a/source/blender/editors/space_text/text_format.c b/source/blender/editors/space_text/text_format.c
index 0133122c5a3..b64eefe969b 100644
--- a/source/blender/editors/space_text/text_format.c
+++ b/source/blender/editors/space_text/text_format.c
@@ -216,7 +216,7 @@ TextFormatType *ED_text_format_get(Text *text)
}
}
- /* If we make it here we never found an extension that worked - return
+ /* If we make it here we never found an extension that worked - 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 d7cf31d0b41..5912dc2402c 100644
--- a/source/blender/editors/space_text/text_format.h
+++ b/source/blender/editors/space_text/text_format.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
diff --git a/source/blender/editors/space_text/text_format_lua.c b/source/blender/editors/space_text/text_format_lua.c
index 1e842729ab3..8b6ec2d804b 100644
--- a/source/blender/editors/space_text/text_format_lua.c
+++ b/source/blender/editors/space_text/text_format_lua.c
@@ -34,8 +34,8 @@
/* *** Lua Keywords (for format_line) *** */
-/* Checks the specified source string for a Lua keyword (minus boolean & 'nil').
- * This name must start at the beginning of the source string and must be
+/* Checks the specified source string for a Lua keyword (minus boolean & 'nil').
+ * This name must start at the beginning of the source string and must be
* followed by a non-identifier (see text_check_identifier(char)) or null char.
*
* If a keyword is found, the length of the matching word is returned.
@@ -75,13 +75,13 @@ static int txtfmt_lua_find_keyword(const char *string)
return i;
}
-/* Checks the specified source string for a Lua special name/function. This
- * name must start at the beginning of the source string and must be followed
+/* Checks the specified source string for a Lua special name/function. This
+ * name must start at the beginning of the source string and must be followed
* by a non-identifier (see text_check_identifier(char)) or null character.
*
* If a special name is found, the length of the matching name is returned.
- * Otherwise, -1 is returned.
- *
+ * Otherwise, -1 is returned.
+ *
* See:
* http://www.lua.org/manual/5.1/manual.html#5.1
*/
diff --git a/source/blender/editors/space_text/text_format_osl.c b/source/blender/editors/space_text/text_format_osl.c
index 97dc1be3b9a..2daaaa348e6 100644
--- a/source/blender/editors/space_text/text_format_osl.c
+++ b/source/blender/editors/space_text/text_format_osl.c
@@ -132,7 +132,7 @@ static int txtfmt_osl_find_reserved(const char *string)
static int txtfmt_osl_find_specialvar(const char *string)
{
int i, len;
-
+
/* OSL shader types */
if (STR_LITERAL_STARTSWITH(string, "shader", len)) i = len;
else if (STR_LITERAL_STARTSWITH(string, "surface", len)) i = len;
diff --git a/source/blender/editors/space_text/text_header.c b/source/blender/editors/space_text/text_header.c
index e06a5b5474e..3229d164f27 100644
--- a/source/blender/editors/space_text/text_header.c
+++ b/source/blender/editors/space_text/text_header.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -54,21 +54,21 @@ static ARegion *text_has_properties_region(ScrArea *sa)
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);
/* is error! */
if (ar == NULL) return NULL;
-
+
arnew = MEM_callocN(sizeof(ARegion), "properties region");
-
+
BLI_insertlinkafter(&sa->regionbase, ar, arnew);
arnew->regiontype = RGN_TYPE_UI;
arnew->alignment = RGN_ALIGN_LEFT;
-
+
arnew->flag = RGN_FLAG_HIDDEN;
-
+
return arnew;
}
@@ -81,7 +81,7 @@ static int text_properties_exec(bContext *C, wmOperator *UNUSED(op))
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = text_has_properties_region(sa);
-
+
if (ar)
ED_region_toggle_hidden(C, ar);
@@ -91,10 +91,10 @@ static int text_properties_exec(bContext *C, wmOperator *UNUSED(op))
void TEXT_OT_properties(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Properties";
+ 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;
@@ -105,15 +105,15 @@ 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);
-
+
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;
-
+
ED_region_tag_redraw(ar);
}
return OPERATOR_FINISHED;
@@ -126,7 +126,7 @@ void TEXT_OT_start_find(wmOperatorType *ot)
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;
@@ -212,4 +212,3 @@ void TEXT_OT_start_find(wmOperatorType *ot)
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 3129c1bfc85..56ce62d0b14 100644
--- a/source/blender/editors/space_text/text_intern.h
+++ b/source/blender/editors/space_text/text_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -151,4 +151,3 @@ void TEXT_OT_autocomplete(struct wmOperatorType *ot);
extern const char *text_context_dir[]; /* doc access */
#endif /* __TEXT_INTERN_H__ */
-
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 2ce699aa6e2..e34edc8908f 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -124,7 +124,7 @@ static int text_region_edit_poll(bContext *C)
if (!st || !text)
return 0;
-
+
if (!ar || ar->regiontype != RGN_TYPE_WINDOW)
return 0;
@@ -198,11 +198,11 @@ void TEXT_OT_new(wmOperatorType *ot)
ot->name = "Create Text Block";
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;
-
+
/* flags */
ot->flag = OPTYPE_UNDO;
}
@@ -234,7 +234,7 @@ static int text_open_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "filepath", str);
- text = BKE_text_load_ex(bmain, str, G.main->name, internal);
+ text = BKE_text_load_ex(bmain, str, BKE_main_blendfile_path(bmain), internal);
if (!text) {
if (op->customdata) MEM_freeN(op->customdata);
@@ -247,15 +247,15 @@ static int text_open_exec(bContext *C, wmOperator *op)
/* hook into UI */
pprop = op->customdata;
+ id_us_ensure_real(&text->id);
+
if (pprop->prop) {
- id_us_ensure_real(&text->id);
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;
- id_us_ensure_real(&text->id);
st->left = 0;
st->top = 0;
st->scroll_accum[0] = 0.0f;
@@ -272,15 +272,16 @@ static int text_open_exec(bContext *C, wmOperator *op)
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 : G.main->name;
+ 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);
-
+
text_open_init(C, op);
RNA_string_set(op->ptr, "filepath", path);
- WM_event_add_fileselect(C, op);
+ WM_event_add_fileselect(C, op);
return OPERATOR_RUNNING_MODAL;
}
@@ -300,7 +301,7 @@ void TEXT_OT_open(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_UNDO;
-
+
/* properties */
WM_operator_properties_filesel(
ot, FILE_TYPE_FOLDER | FILE_TYPE_TEXT | FILE_TYPE_PYSCRIPT, FILE_SPECIAL, FILE_OPENFILE,
@@ -351,7 +352,7 @@ void TEXT_OT_reload(wmOperatorType *ot)
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;
@@ -400,12 +401,12 @@ void TEXT_OT_unlink(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_UNDO;
}
@@ -439,7 +440,7 @@ void TEXT_OT_make_internal(wmOperatorType *ot)
/* api callbacks */
ot->exec = text_make_internal_exec;
ot->poll = text_edit_poll;
-
+
/* flags */
ot->flag = OPTYPE_UNDO;
}
@@ -452,20 +453,20 @@ static int text_save_poll(bContext *C)
if (!text_edit_poll(C))
return 0;
-
+
return (text->name != NULL && !(text->flags & TXT_ISMEM));
}
-static void txt_write_file(Text *text, ReportList *reports)
+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, G.main->name);
-
+ 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",
@@ -479,7 +480,7 @@ static void txt_write_file(Text *text, ReportList *reports)
fputc('\n', fp);
}
}
-
+
fclose(fp);
if (BLI_stat(filepath, &st) == 0) {
@@ -493,15 +494,16 @@ static void txt_write_file(Text *text, ReportList *reports)
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);
- txt_write_file(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);
@@ -525,6 +527,7 @@ void TEXT_OT_save(wmOperatorType *ot)
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];
@@ -537,7 +540,7 @@ static int text_save_as_exec(bContext *C, wmOperator *op)
text->name = BLI_strdup(str);
text->flags &= ~TXT_ISMEM;
- txt_write_file(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);
@@ -547,6 +550,7 @@ static int text_save_as_exec(bContext *C, wmOperator *op)
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;
@@ -558,10 +562,10 @@ static int text_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
else if (text->flags & TXT_ISMEM)
str = text->id.name + 2;
else
- str = G.main->name;
-
+ str = BKE_main_blendfile_path(bmain);
+
RNA_string_set(op->ptr, "filepath", str);
- WM_event_add_fileselect(C, op);
+ WM_event_add_fileselect(C, op);
return OPERATOR_RUNNING_MODAL;
}
@@ -572,7 +576,7 @@ void TEXT_OT_save_as(wmOperatorType *ot)
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;
@@ -649,7 +653,7 @@ void TEXT_OT_run_script(wmOperatorType *ot)
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;
@@ -668,7 +672,7 @@ static int text_refresh_pyconstraints_exec(bContext *UNUSED(C), wmOperator *UNUS
Object *ob;
bConstraint *con;
short update;
-
+
/* check all pyconstraints */
for (ob = CTX_data_main(C)->object.first; ob; ob = ob->id.next) {
update = 0;
@@ -680,7 +684,7 @@ static int text_refresh_pyconstraints_exec(bContext *UNUSED(C), wmOperator *UNUS
bPythonConstraint *data = con->data;
if (data->text == text) BPY_pyconstraint_update(ob, con);
update = 1;
-
+
}
}
}
@@ -692,7 +696,7 @@ static int text_refresh_pyconstraints_exec(bContext *UNUSED(C), wmOperator *UNUS
update = 1;
}
}
-
+
if (update) {
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
@@ -709,7 +713,7 @@ void TEXT_OT_refresh_pyconstraints(wmOperatorType *ot)
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;
@@ -753,7 +757,7 @@ void TEXT_OT_paste(wmOperatorType *ot)
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;
@@ -867,7 +871,7 @@ void TEXT_OT_cut(wmOperatorType *ot)
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;
@@ -908,7 +912,7 @@ void TEXT_OT_indent(wmOperatorType *ot)
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;
@@ -944,7 +948,7 @@ void TEXT_OT_unindent(wmOperatorType *ot)
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;
@@ -1073,7 +1077,7 @@ void TEXT_OT_uncomment(wmOperatorType *ot)
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;
@@ -1113,7 +1117,7 @@ static int text_convert_whitespace_exec(bContext *C, wmOperator *op)
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);
@@ -1122,7 +1126,7 @@ static int text_convert_whitespace_exec(bContext *C, wmOperator *op)
max_len = tmp->len;
}
}
-
+
if (type == TO_TABS) {
char *tmp_line = MEM_mallocN(sizeof(*tmp_line) * (max_len + 1), __func__);
@@ -1208,7 +1212,7 @@ void TEXT_OT_convert_whitespace(wmOperatorType *ot)
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;
@@ -1240,7 +1244,7 @@ void TEXT_OT_select_all(wmOperatorType *ot)
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;
@@ -1266,7 +1270,7 @@ void TEXT_OT_select_line(wmOperatorType *ot)
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;
@@ -1311,14 +1315,14 @@ static int move_lines_exec(bContext *C, wmOperator *op)
TextUndoBuf *utxt = ED_text_undo_push_init(C);
txt_move_lines(text, utxt, direction);
-
+
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);
-
+
return OPERATOR_FINISHED;
}
@@ -1334,7 +1338,7 @@ void TEXT_OT_move_lines(wmOperatorType *ot)
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;
@@ -1753,7 +1757,7 @@ static void cursor_skip(SpaceText *st, ARegion *ar, Text *text, int lines, const
{
TextLine **linep;
int *charp;
-
+
if (sel) { linep = &text->sell; charp = &text->selc; }
else { linep = &text->curl; charp = &text->curc; }
@@ -1798,7 +1802,7 @@ static int text_move_cursor(bContext *C, int type, bool select)
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);
@@ -1810,7 +1814,7 @@ static int text_move_cursor(bContext *C, int type, bool select)
case FILE_TOP:
txt_move_bof(text, select);
break;
-
+
case FILE_BOTTOM:
txt_move_eof(text, select);
break;
@@ -1853,7 +1857,7 @@ static int text_move_cursor(bContext *C, int type, bool select)
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);
@@ -1889,7 +1893,7 @@ void TEXT_OT_move(wmOperatorType *ot)
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;
@@ -1913,7 +1917,7 @@ void TEXT_OT_move_select(wmOperatorType *ot)
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;
@@ -1957,7 +1961,7 @@ void TEXT_OT_jump(wmOperatorType *ot)
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;
@@ -2048,7 +2052,7 @@ static int text_delete_exec(bContext *C, wmOperator *op)
/* run the script while editing, evil but useful */
if (st->live_edit)
text_run_script(C, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -2058,7 +2062,7 @@ void TEXT_OT_delete(wmOperatorType *ot)
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;
@@ -2067,7 +2071,9 @@ void TEXT_OT_delete(wmOperatorType *ot)
ot->flag = OPTYPE_UNDO;
/* properties */
- RNA_def_enum(ot->srna, "type", delete_type_items, DEL_NEXT_CHAR, "Type", "Which part of the text to delete");
+ 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 **********************/
@@ -2089,7 +2095,7 @@ void TEXT_OT_overwrite_toggle(wmOperatorType *ot)
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;
@@ -2239,13 +2245,15 @@ static int text_scroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
case LEFTMOUSE:
case RIGHTMOUSE:
case MIDDLEMOUSE:
- if (ELEM(tsc->zone, SCROLLHANDLE_MIN_OUTSIDE, SCROLLHANDLE_MAX_OUTSIDE)) {
- txt_screen_skip(st, ar, st->viewlines * (tsc->zone == SCROLLHANDLE_MIN_OUTSIDE ? 1 : -1));
+ 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));
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+ scroll_exit(C, op);
+ return OPERATOR_FINISHED;
}
- scroll_exit(C, op);
- return OPERATOR_FINISHED;
}
return OPERATOR_RUNNING_MODAL;
@@ -2260,20 +2268,20 @@ static int text_scroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceText *st = CTX_wm_space_text(C);
TextScroll *tsc;
-
+
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;
-
+
st->flags |= ST_SCROLL_SELECT;
-
+
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 */
@@ -2287,7 +2295,7 @@ static int text_scroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
WM_event_add_modal_handler(C, op);
-
+
return OPERATOR_RUNNING_MODAL;
}
@@ -2296,11 +2304,11 @@ 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
+ * scroll_bar. Both do basically the same thing (aside
* from keymaps).*/
ot->idname = "TEXT_OT_scroll";
ot->description = "";
-
+
/* api callbacks */
ot->exec = text_scroll_exec;
ot->invoke = text_scroll_invoke;
@@ -2326,10 +2334,10 @@ static int text_region_scroll_poll(bContext *C)
if (!st || !text)
return 0;
-
+
if (!ar || ar->regiontype != RGN_TYPE_WINDOW)
return 0;
-
+
return 1;
}
@@ -2343,7 +2351,7 @@ static int text_scroll_bar_invoke(bContext *C, wmOperator *op, const wmEvent *ev
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) {
@@ -2388,11 +2396,11 @@ 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
+ * scroll. Both do basically the same thing (aside
* from keymaps).*/
ot->idname = "TEXT_OT_scroll_bar";
ot->description = "";
-
+
/* api callbacks */
ot->invoke = text_scroll_bar_invoke;
ot->modal = text_scroll_modal;
@@ -2427,7 +2435,7 @@ static int flatten_width(SpaceText *st, const char *str)
total += BLI_str_utf8_char_width_safe(str + i);
}
}
-
+
return total;
}
@@ -2440,14 +2448,14 @@ static int flatten_column_to_offset(SpaceText *st, const char *str, int index)
col = st->tabnumber - i % st->tabnumber;
else
col = BLI_str_utf8_char_width_safe(str + j);
-
+
if (i + col > index)
break;
-
+
i += col;
j += BLI_str_utf8_size_safe(str + j);
}
-
+
return j;
}
@@ -2478,7 +2486,7 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in
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);
@@ -2491,7 +2499,7 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in
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;
@@ -2500,7 +2508,7 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in
else {
chars = 1;
}
-
+
while (chars--) {
/* Gone too far, go back to last wrap point */
if (y < 0) {
@@ -2522,22 +2530,22 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in
}
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;
@@ -2549,7 +2557,7 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in
if (found) {
break;
}
-
+
if (y == 0 && i + columns - start > x) {
charp = curs;
found = true;
@@ -2564,7 +2572,7 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in
}
BLI_assert(y == 0);
-
+
if (!found) {
/* On correct line but didn't meet cursor, must be at end */
charp = linep->len;
@@ -2602,7 +2610,7 @@ static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, con
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);
}
@@ -2610,12 +2618,12 @@ static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, con
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;
@@ -2627,7 +2635,7 @@ static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, con
}
}
-
+
w = flatten_width(st, (*linep)->line);
if (x < w) *charp = flatten_column_to_offset(st, (*linep)->line, x);
else *charp = (*linep)->len;
@@ -2675,7 +2683,7 @@ static void text_cursor_set_apply(bContext *C, wmOperator *op, const wmEvent *ev
}
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);
@@ -2872,7 +2880,7 @@ void TEXT_OT_line_number(wmOperatorType *ot)
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;
@@ -2909,7 +2917,7 @@ static int text_insert_exec(bContext *C, wmOperator *op)
}
MEM_freeN(str);
-
+
if (!done)
return OPERATOR_CANCELLED;
@@ -2937,7 +2945,7 @@ static int text_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event)
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);
@@ -2952,7 +2960,7 @@ static int text_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
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);
@@ -2968,7 +2976,7 @@ void TEXT_OT_insert(wmOperatorType *ot)
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;
@@ -3060,7 +3068,7 @@ void TEXT_OT_find(wmOperatorType *ot)
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;
@@ -3112,7 +3120,7 @@ void TEXT_OT_find_set_selected(wmOperatorType *ot)
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;
@@ -3139,7 +3147,7 @@ void TEXT_OT_replace_set_selected(wmOperatorType *ot)
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;
@@ -3255,11 +3263,11 @@ void TEXT_OT_to_3d_object(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/space_topbar/space_topbar.c b/source/blender/editors/space_topbar/space_topbar.c
index 8cf27d86cfe..c7ef6591c0d 100644
--- a/source/blender/editors/space_topbar/space_topbar.c
+++ b/source/blender/editors/space_topbar/space_topbar.c
@@ -57,9 +57,6 @@
#include "WM_types.h"
#include "WM_message.h"
-
-void topbar_panels_register(ARegionType *art);
-
/* ******************** default callbacks for topbar space ***************** */
static SpaceLink *topbar_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
@@ -201,9 +198,10 @@ static void topbar_header_region_message_subscribe(
.user_data = ar,
.notify = ED_region_do_msg_notify_tag_redraw,
};
+
WM_msg_subscribe_rna_prop(
mbus, &workspace->id, workspace,
- WorkSpace, tool_keymap, &msg_sub_value_region_tag_redraw);
+ WorkSpace, tools, &msg_sub_value_region_tag_redraw);
}
static void recent_files_menu_draw(const bContext *UNUSED(C), Menu *menu)
@@ -276,64 +274,9 @@ void ED_spacetype_topbar(void)
art->layout = ED_region_header_layout;
art->draw = ED_region_header_draw;
- /* For popovers. */
- topbar_panels_register(art);
-
BLI_addhead(&st->regiontypes, art);
recent_files_menu_register();
BKE_spacetype_register(st);
}
-
-
-/* -------------------------------------------------------------------- */
-/** \name Redo Panel
- * \{ */
-
-static int topbar_panel_operator_redo_poll(const bContext *C, PanelType *UNUSED(pt))
-{
- wmOperator *op = WM_operator_last_redo(C);
- if (op == NULL) {
- return false;
- }
-
- bool success = false;
- if (!WM_operator_check_ui_empty(op->type)) {
- const OperatorRepeatContextHandle *context_info;
- context_info = ED_operator_repeat_prepare_context((bContext *)C, op);
- success = WM_operator_poll((bContext *)C, op->type);
- ED_operator_repeat_reset_context((bContext *)C, context_info);
- }
- return success;
-}
-
-static void topbar_panel_operator_redo(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);
-}
-
-void topbar_panels_register(ARegionType *art)
-{
- PanelType *pt;
-
- pt = MEM_callocN(sizeof(PanelType), __func__);
- strcpy(pt->idname, "TOPBAR_PT_redo");
- strcpy(pt->label, N_("Redo"));
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = topbar_panel_operator_redo;
- pt->poll = topbar_panel_operator_redo_poll;
- pt->space_type = SPACE_TOPBAR;
- pt->region_type = RGN_TYPE_HEADER;
- BLI_addtail(&art->paneltypes, pt);
-}
-
-/** \} */
diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c
index 8e569c3b16e..fc5182fcb4f 100644
--- a/source/blender/editors/space_userpref/space_userpref.c
+++ b/source/blender/editors/space_userpref/space_userpref.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -77,9 +77,9 @@ static SpaceLink *userpref_new(const ScrArea *UNUSED(area), const Scene *UNUSED(
/* not spacelink itself */
static void userpref_free(SpaceLink *UNUSED(sl))
-{
+{
// SpaceUserPref *spref = (SpaceUserPref *)sl;
-
+
}
@@ -105,7 +105,7 @@ 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; */
-
+
ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
ED_region_panels_init(wm, ar);
@@ -113,7 +113,7 @@ static void userpref_main_region_init(wmWindowManager *wm, ARegion *ar)
static void userpref_main_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
static void userpref_operatortypes(void)
@@ -122,7 +122,7 @@ 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 */
@@ -196,4 +196,3 @@ void ED_spacetype_userpref(void)
BKE_spacetype_register(st);
}
-
diff --git a/source/blender/editors/space_userpref/userpref_intern.h b/source/blender/editors/space_userpref/userpref_intern.h
index 03074290d13..720b4da0f71 100644
--- a/source/blender/editors/space_userpref/userpref_intern.h
+++ b/source/blender/editors/space_userpref/userpref_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -34,4 +34,3 @@
/* internal exports only */
#endif /* __USERPREF_INTERN_H__ */
-
diff --git a/source/blender/editors/space_userpref/userpref_ops.c b/source/blender/editors/space_userpref/userpref_ops.c
index 0783eacc65c..6666a6cfc16 100644
--- a/source/blender/editors/space_userpref/userpref_ops.c
+++ b/source/blender/editors/space_userpref/userpref_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -31,5 +31,3 @@
#include <string.h>
#include <stdio.h>
-
-
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 8e04a2e17b8..bca5faa314a 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -67,6 +67,7 @@
#include "BKE_lattice.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
#include "BKE_material.h"
#include "BKE_mball.h"
#include "BKE_modifier.h"
@@ -99,6 +100,8 @@
#include "GPU_immediate_util.h"
#include "GPU_batch.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
+#include "GPU_framebuffer.h"
#include "ED_mesh.h"
#include "ED_particle.h"
@@ -288,7 +291,7 @@ static void bbs_obmode_mesh_verts(Object *ob, DerivedMesh *dm, int offset)
immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32);
- glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
+ GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE));
immBeginAtMost(GWN_PRIM_POINTS, imm_len);
dm->foreachMappedVert(dm, bbs_obmode_mesh_verts__mapFunc, &data, DM_FOREACH_NOP);
@@ -331,7 +334,7 @@ static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *dm, int offset)
immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32);
- glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
+ GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE));
immBeginAtMost(GWN_PRIM_POINTS, em->bm->totvert);
dm->foreachMappedVert(dm, bbs_mesh_verts__mapFunc, &data, DM_FOREACH_NOP);
@@ -342,7 +345,7 @@ static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *dm, int offset)
#else
static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *UNUSED(dm), int offset)
{
- glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
+ GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE));
Mesh *me = em->ob->data;
Gwn_Batch *batch = DRW_mesh_batch_cache_get_verts_with_select_id(me, offset);
@@ -383,7 +386,7 @@ static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *dm, int offset)
immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32);
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
immBeginAtMost(GWN_PRIM_LINES, imm_len);
dm->foreachMappedEdge(dm, bbs_mesh_wire__mapFunc, &data);
@@ -394,7 +397,7 @@ static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *dm, int offset)
#else
static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *UNUSED(dm), int offset)
{
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
Mesh *me = em->ob->data;
Gwn_Batch *batch = DRW_mesh_batch_cache_get_edges_with_select_id(me, offset);
@@ -502,7 +505,7 @@ static void bbs_mesh_face_dot(BMEditMesh *em, DerivedMesh *dm)
immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32);
- glPointSize(UI_GetThemeValuef(TH_FACEDOT_SIZE));
+ GPU_point_size(UI_GetThemeValuef(TH_FACEDOT_SIZE));
immBeginAtMost(GWN_PRIM_POINTS, em->bm->totface);
dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, &data, DM_FOREACH_NOP);
@@ -610,14 +613,18 @@ static void bbs_mesh_solid_faces(Scene *UNUSED(scene), Object *ob)
}
void draw_object_backbufsel(
- Depsgraph *depsgraph, Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
+ 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;
+ }
gpuMultMatrix(ob->obmat);
- glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT);
- glEnable(GL_DEPTH_TEST);
+ glClearDepth(1.0); GPU_clear(GPU_DEPTH_BIT);
+ GPU_depth_test(true);
switch (ob->type) {
case OB_MESH:
@@ -631,8 +638,8 @@ void draw_object_backbufsel(
DM_update_materials(dm, ob);
- bbs_mesh_solid_EM(em, scene, v3d, ob, dm, (ts->selectmode & SCE_SELECT_FACE) != 0);
- if (ts->selectmode & SCE_SELECT_FACE)
+ bbs_mesh_solid_EM(em, scene, v3d, ob, dm, (select_mode & SCE_SELECT_FACE) != 0);
+ if (select_mode & SCE_SELECT_FACE)
bm_solidoffs = 1 + em->bm->totface;
else {
bm_solidoffs = 1;
@@ -641,7 +648,7 @@ void draw_object_backbufsel(
ED_view3d_polygon_offset(rv3d, 1.0);
/* we draw edges if edge select mode */
- if (ts->selectmode & SCE_SELECT_EDGE) {
+ if (select_mode & SCE_SELECT_EDGE) {
bbs_mesh_wire(em, dm, bm_solidoffs);
bm_wireoffs = bm_solidoffs + em->bm->totedge;
}
@@ -651,7 +658,7 @@ void draw_object_backbufsel(
}
/* we draw verts if vert select mode. */
- if (ts->selectmode & SCE_SELECT_VERTEX) {
+ if (select_mode & SCE_SELECT_VERTEX) {
bbs_mesh_verts(em, dm, bm_wireoffs);
bm_vertoffs = bm_wireoffs + em->bm->totvert;
}
@@ -705,7 +712,7 @@ void ED_draw_object_facemap(
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
-
+
#if 0
DM_update_materials(dm, ob);
@@ -717,7 +724,7 @@ void ED_draw_object_facemap(
glColor4fv(col);
gpuPushAttrib(GL_ENABLE_BIT);
- glEnable(GL_BLEND);
+ GPU_blend(true);
glDisable(GL_LIGHTING);
/* always draw using backface culling */
@@ -747,8 +754,8 @@ void ED_draw_object_facemap(
immUniformColor4fv(col);
/* XXX, alpha isn't working yet, not sure why. */
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
MVert *mvert;
@@ -805,10 +812,9 @@ void ED_draw_object_facemap(
immUnbindProgram();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
#endif
dm->release(dm);
}
-
diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c
index 3b648e3b13a..c6874a663a5 100644
--- a/source/blender/editors/space_view3d/drawvolume.c
+++ b/source/blender/editors/space_view3d/drawvolume.c
@@ -1,4 +1,4 @@
-/*
+/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
@@ -40,8 +40,8 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_colorband.h"
+#include "BKE_deform.h"
#include "BKE_particle.h"
#include "smoke_API.h"
@@ -50,6 +50,7 @@
#include "GPU_shader.h"
#include "GPU_texture.h"
+#include "GPU_state.h"
#include "view3d_intern.h" // own include
@@ -632,11 +633,11 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth);
glGetBooleanv(GL_DEPTH_WRITEMASK, (GLboolean *)&gl_depth_write);
- glEnable(GL_DEPTH_TEST);
+ GPU_depth_test(true);
glDepthMask(GL_FALSE);
- glEnable(GL_BLEND);
+ GPU_blend(true);
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
draw_buffer(sds, shader, &slicer, ob_sizei, invsize, num_points, false);
/* Draw fire separately (T47639). */
@@ -655,11 +656,11 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
glDepthMask(gl_depth_write);
if (!gl_blend) {
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
if (gl_depth) {
- glEnable(GL_DEPTH_TEST);
+ GPU_depth_test(true);
}
}
@@ -684,7 +685,7 @@ static void add_needle(float (*verts)[3], float (*colors)[3], float center[3],
float len = len_v3(dir);
float rgb[3];
- weight_to_rgb(rgb, len);
+ BKE_defvert_weight_to_rgb(rgb, len);
if (len != 0.0f) {
mul_v3_fl(dir, 1.0f / len);
@@ -724,7 +725,7 @@ static void add_streamline(float (*verts)[3], float(*colors)[3], float center[3]
const float len = len_v3(dir);
float rgb[3];
- weight_to_rgb(rgb, len);
+ BKE_defvert_weight_to_rgb(rgb, len);
copy_v3_v3(colors[(*offset)], rgb);
copy_v3_v3(verts[(*offset)++], center);
@@ -831,7 +832,7 @@ void draw_smoke_velocity(SmokeDomainSettings *domain, float viewnormal[3])
}
}
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, verts);
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index d6413e8bdfb..cb7066d218c 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -69,6 +69,7 @@
#include "WM_api.h"
#include "WM_types.h"
#include "WM_message.h"
+#include "WM_toolsystem.h"
#include "RE_engine.h"
#include "RE_pipeline.h"
@@ -94,21 +95,21 @@ ARegion *view3d_has_buttons_region(ScrArea *sa)
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);
/* is error! */
if (ar == NULL) return NULL;
-
+
arnew = MEM_callocN(sizeof(ARegion), "buttons for view3d");
-
+
BLI_insertlinkafter(&sa->regionbase, ar, arnew);
arnew->regiontype = RGN_TYPE_UI;
arnew->alignment = RGN_ALIGN_RIGHT;
-
+
arnew->flag = RGN_FLAG_HIDDEN;
-
+
return arnew;
}
@@ -131,12 +132,12 @@ ARegion *view3d_has_tools_region(ScrArea *sa)
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;
@@ -152,7 +153,7 @@ ARegion *view3d_has_tools_region(ScrArea *sa)
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) {
@@ -295,8 +296,10 @@ void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa)
ARegion *ar;
for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiondata)
+ if ((ar->regiontype == RGN_TYPE_WINDOW) && ar->regiondata) {
ED_view3d_stop_render_preview(wm, ar);
+ break;
+ }
}
}
}
@@ -308,10 +311,9 @@ 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;
- v3d->blockscale = 0.7f;
v3d->lay = v3d->layact = 1;
if (scene) {
v3d->lay = v3d->layact = scene->lay;
@@ -322,16 +324,27 @@ static SpaceLink *view3d_new(const ScrArea *UNUSED(sa), const Scene *scene)
v3d->gridlines = 16;
v3d->gridsubdiv = 10;
v3d->drawtype = OB_SOLID;
+ v3d->shading.flag = V3D_SHADING_SPECULAR_HIGHLIGHT;
v3d->shading.light = V3D_LIGHTING_STUDIO;
- v3d->shading.shadow_intensity = 0.5;
+ v3d->shading.shadow_intensity = 0.5f;
+ v3d->shading.xray_alpha = 0.5f;
+ v3d->shading.cavity_valley_factor = 1.0f;
+ v3d->shading.cavity_ridge_factor = 1.0f;
copy_v3_fl(v3d->shading.single_color, 0.8f);
+ v3d->overlay.flag = V3D_OVERLAY_LOOK_DEV;
+ v3d->overlay.wireframe_threshold = 0.5f;
+ v3d->overlay.bone_selection_alpha = 0.5f;
+ v3d->overlay.texture_paint_mode_opacity = 0.8;
+ v3d->overlay.weight_paint_mode_opacity = 0.8;
+ v3d->overlay.vertex_paint_mode_opacity = 0.8;
+
v3d->gridflag = V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_FLOOR;
-
+
v3d->flag = V3D_SELECT_OUTLINE;
v3d->flag2 = V3D_SHOW_RECONSTRUCTION | V3D_SHOW_GPENCIL;
-
- v3d->lens = 35.0f;
+
+ v3d->lens = 50.0f;
v3d->near = 0.01f;
v3d->far = 1000.0f;
@@ -348,14 +361,14 @@ static SpaceLink *view3d_new(const ScrArea *UNUSED(sa), const Scene *scene)
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for view3d");
-
+
BLI_addtail(&v3d->regionbase, ar);
ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = RGN_ALIGN_BOTTOM;
-
+ ar->alignment = 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;
@@ -363,25 +376,25 @@ static SpaceLink *view3d_new(const ScrArea *UNUSED(sa), const Scene *scene)
/* 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;
}
@@ -391,9 +404,9 @@ static void view3d_free(SpaceLink *sl)
View3D *vd = (View3D *) sl;
if (vd->localvd) MEM_freeN(vd->localvd);
-
+
if (vd->properties_storage) MEM_freeN(vd->properties_storage);
-
+
if (vd->fx_settings.ssao)
MEM_freeN(vd->fx_settings.ssao);
if (vd->fx_settings.dof)
@@ -411,7 +424,7 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
{
View3D *v3do = (View3D *)sl;
View3D *v3dn = MEM_dupallocN(sl);
-
+
/* clear or remove stuff from old */
if (v3dn->localvd) {
@@ -422,7 +435,7 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
if (v3dn->drawtype == OB_RENDER)
v3dn->drawtype = OB_SOLID;
-
+
/* copy or clear inside new stuff */
v3dn->properties_storage = NULL;
@@ -448,19 +461,19 @@ static void view3d_main_region_init(wmWindowManager *wm, ARegion *ar)
WM_manipulatormap_add_handlers(ar, ar->manipulator_map);
/* object ops. */
-
+
/* important to be before Pose keymap since they can both be enabled at once */
keymap = WM_keymap_find(wm->defaultconf, "Face Mask", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
-
-
+
+
keymap = WM_keymap_find(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_find(wm->defaultconf, "Pose", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
-
+
keymap = WM_keymap_find(wm->defaultconf, "Object Mode", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
@@ -481,13 +494,13 @@ static void view3d_main_region_init(wmWindowManager *wm, ARegion *ar)
keymap = WM_keymap_find(wm->defaultconf, "Sculpt", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
-
+
keymap = WM_keymap_find(wm->defaultconf, "Mesh", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
-
+
keymap = WM_keymap_find(wm->defaultconf, "Curve", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
-
+
keymap = WM_keymap_find(wm->defaultconf, "Armature", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
@@ -496,7 +509,7 @@ static void view3d_main_region_init(wmWindowManager *wm, ARegion *ar)
keymap = WM_keymap_find(wm->defaultconf, "Metaball", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
-
+
keymap = WM_keymap_find(wm->defaultconf, "Lattice", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
@@ -519,12 +532,12 @@ static void view3d_main_region_init(wmWindowManager *wm, ARegion *ar)
keymap = WM_keymap_find(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);
-
+
}
static void view3d_main_region_exit(wmWindowManager *wm, ARegion *ar)
@@ -549,7 +562,7 @@ static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent
return 0;
}
-static int view3d_group_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
+static int view3d_collection_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_ID) {
ID *id = drag->poin;
@@ -624,10 +637,10 @@ static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop)
RNA_string_set(drop->ptr, "name", id->name + 2);
}
-static void view3d_group_drop_copy(wmDrag *drag, wmDropBox *drop)
+static void view3d_collection_drop_copy(wmDrag *drag, wmDropBox *drop)
{
ID *id = drag->poin;
-
+
drop->opcontext = WM_OP_EXEC_DEFAULT;
RNA_string_set(drop->ptr, "name", id->name + 2);
}
@@ -635,14 +648,14 @@ static void view3d_group_drop_copy(wmDrag *drag, wmDropBox *drop)
static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop)
{
ID *id = drag->poin;
-
+
RNA_string_set(drop->ptr, "name", id->name + 2);
}
static void view3d_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
{
ID *id = drag->poin;
-
+
if (id) {
RNA_string_set(drop->ptr, "name", id->name + 2);
RNA_struct_property_unset(drop->ptr, "filepath");
@@ -658,13 +671,13 @@ static void view3d_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
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, "MESH_OT_drop_named_image", view3d_ima_mesh_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, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, view3d_id_path_drop_copy);
- WM_dropbox_add(lb, "OBJECT_OT_group_instance_add", view3d_group_drop_poll, view3d_group_drop_copy);
+ WM_dropbox_add(lb, "OBJECT_OT_collection_instance_add", view3d_collection_drop_poll, view3d_collection_drop_copy);
}
static void view3d_widgets(void)
@@ -696,14 +709,14 @@ static void view3d_widgets(void)
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);
@@ -725,19 +738,19 @@ 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->gpuoffscreen = NULL;
new->render_engine = NULL;
new->sms = NULL;
new->smooth_timer = NULL;
-
+
return new;
}
return NULL;
@@ -812,7 +825,6 @@ static void view3d_main_region_listener(
break;
case ND_OB_ACTIVE:
case ND_OB_SELECT:
- DEG_id_tag_update((ID *)&scene->id, DEG_TAG_SELECT_UPDATE);
ATTR_FALLTHROUGH;
case ND_FRAME:
case ND_TRANSFORM:
@@ -867,18 +879,6 @@ static void view3d_main_region_listener(
case ND_SELECT:
{
WM_manipulatormap_tag_refresh(mmap);
-
- ID *ob_data = wmn->reference;
- if (ob_data == NULL) {
- BLI_assert(wmn->window); // Use `WM_event_add_notifier` instead of `WM_main_add_notifier`
- ViewLayer *view_layer = WM_window_get_active_view_layer(wmn->window);
- ob_data = OBEDIT_FROM_VIEW_LAYER(view_layer)->data;
- }
- if (ob_data) {
- BLI_assert(OB_DATA_SUPPORT_ID(GS(ob_data->name)));
- /* TODO(sergey): Notifiers shouldn't really be doing DEG tags. */
- DEG_id_tag_update(ob_data, DEG_TAG_SELECT_UPDATE);
- }
ATTR_FALLTHROUGH;
}
case ND_DATA:
@@ -1017,8 +1017,8 @@ static void view3d_main_region_listener(
static void view3d_main_region_message_subscribe(
const struct bContext *C,
- struct WorkSpace *workspace, struct Scene *scene,
- struct bScreen *UNUSED(screen), struct ScrArea *UNUSED(sa), struct ARegion *ar,
+ 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,
@@ -1075,19 +1075,7 @@ static void view3d_main_region_message_subscribe(
WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, use_border, &msg_sub_value_region_tag_redraw);
}
- /* Each engine could be responsible for its own engine data types.
- * For now this is simplest. */
- if (STREQ(scene->r.engine, RE_engine_id_BLENDER_EEVEE)) {
- extern StructRNA RNA_ViewLayerEngineSettingsEevee;
- WM_msg_subscribe_rna_anon_type(mbus, ViewLayerEngineSettingsEevee, &msg_sub_value_region_tag_redraw);
- }
-#ifdef WITH_CLAY_ENGINE
- else if (STREQ(scene->r.engine, RE_engine_id_BLENDER_CLAY)) {
- extern StructRNA RNA_ViewLayerEngineSettingsClay;
- WM_msg_subscribe_rna_anon_type(mbus, ViewLayerEngineSettingsClay, &msg_sub_value_region_tag_redraw);
- }
-#endif
-
+ 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);
@@ -1103,10 +1091,10 @@ static void view3d_main_region_message_subscribe(
}
}
- if (workspace->tool.spacetype == SPACE_VIEW3D) {
+ {
wmMsgSubscribeValue msg_sub_value_region_tag_refresh = {
.owner = ar,
- .user_data = ar,
+ .user_data = sa,
.notify = WM_toolsystem_do_msg_notify_tag_refresh,
};
WM_msg_subscribe_rna_anon_prop(
@@ -1115,9 +1103,27 @@ static void view3d_main_region_message_subscribe(
}
}
+static void view3d_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);
+}
+
/* concept is to retrieve cursor type context-less */
-static void view3d_main_region_cursor(wmWindow *win, ScrArea *UNUSED(sa), ARegion *UNUSED(ar))
+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) {
@@ -1132,7 +1138,7 @@ static void view3d_main_region_cursor(wmWindow *win, ScrArea *UNUSED(sa), ARegio
static void view3d_header_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap = WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
-
+
WM_event_add_keymap_handler(&ar->handlers, keymap);
ED_region_header_init(ar);
@@ -1211,14 +1217,14 @@ static void view3d_buttons_region_init(wmWindowManager *wm, ARegion *ar)
wmKeyMap *keymap;
ED_region_panels_init(wm, ar);
-
+
keymap = WM_keymap_find(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(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
static void view3d_buttons_region_listener(
@@ -1317,7 +1323,7 @@ static int view3d_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[] = {3 + 0.25f, 5 + 0.25};
+ 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;
@@ -1338,7 +1344,7 @@ static int view3d_tools_region_snap_size(const ARegion *ar, int size, int axis)
static void view3d_tools_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
-
+
ED_region_panels_init(wm, ar);
keymap = WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
@@ -1347,7 +1353,7 @@ static void view3d_tools_region_init(wmWindowManager *wm, ARegion *ar)
static void view3d_tools_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, CTX_data_mode_string(C), -1, true);
+ ED_region_panels_ex(C, ar, (const char * []){CTX_data_mode_string(C), NULL}, -1, true);
}
/* area (not region) level listener */
@@ -1404,11 +1410,11 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
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_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT)) {
+ 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")) {
@@ -1416,11 +1422,11 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
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_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT) != 0) {
+ 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 {
@@ -1479,10 +1485,10 @@ 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;
@@ -1509,7 +1515,7 @@ void ED_spacetype_view3d(void)
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;
@@ -1529,15 +1535,11 @@ void ED_spacetype_view3d(void)
art->prefsizey = 50; /* XXX */
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
art->listener = view3d_buttons_region_listener;
+ art->message_subscribe = view3d_tools_region_message_subscribe;
art->snap_size = view3d_tools_region_snap_size;
art->init = view3d_tools_region_init;
art->draw = view3d_tools_region_draw;
BLI_addhead(&st->regiontypes, art);
-
-#if 0
- /* unfinished still */
- view3d_toolshelf_register(art);
-#endif
/* regions: header */
art = MEM_callocN(sizeof(ARegionType), "spacetype view3d header region");
@@ -1549,6 +1551,10 @@ void ED_spacetype_view3d(void)
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 644a6956e54..6ebed88728e 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -69,6 +69,7 @@
#include "RNA_access.h"
#include "ED_armature.h"
+#include "ED_object.h"
#include "ED_mesh.h"
#include "ED_screen.h"
@@ -835,7 +836,7 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
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);
@@ -864,7 +865,7 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
UI_but_flag_enable(but, UI_BUT_INACTIVE);
}
xco += x;
-
+
row = uiLayoutRow(split, true);
uiLayoutSetEnabled(row, !locked);
@@ -1163,6 +1164,11 @@ static void view3d_panel_transform(const bContext *C, Panel *pa)
}
}
+static void hide_collections_menu_draw(const bContext *C, Menu *menu)
+{
+ ED_hide_collections_menu_draw(C, menu->layout);
+}
+
void view3d_buttons_register(ARegionType *art)
{
PanelType *pt;
@@ -1182,6 +1188,15 @@ void view3d_buttons_register(ARegionType *art)
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))
@@ -1197,7 +1212,7 @@ static int view3d_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
void VIEW3D_OT_properties(wmOperatorType *ot)
{
- ot->name = "Properties";
+ ot->name = "Toggle Sidebar";
ot->description = "Toggle the properties region visibility";
ot->idname = "VIEW3D_OT_properties";
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 99f7abba065..e9c2ddbab76 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -44,6 +44,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_key.h"
+#include "BKE_main.h"
#include "BKE_scene.h"
#include "BKE_object.h"
#include "BKE_paint.h"
@@ -79,6 +80,8 @@
#include "GPU_immediate_util.h"
#include "GPU_material.h"
#include "GPU_viewport.h"
+#include "GPU_state.h"
+#include "GPU_framebuffer.h"
#include "MEM_guardedalloc.h"
@@ -302,6 +305,7 @@ static void view3d_camera_border(
{
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);
@@ -316,7 +320,7 @@ static void view3d_camera_border(
/* fallback for non camera objects */
params.clipsta = v3d->near;
params.clipend = v3d->far;
- BKE_camera_params_from_object(&params, v3d->camera);
+ BKE_camera_params_from_object(&params, camera_eval);
if (no_shift) {
params.shiftx = 0.0f;
params.shifty = 0.0f;
@@ -440,15 +444,15 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View
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;
-
- glLineWidth(1.0f);
+
+ GPU_line_width(1.0f);
/* apply offsets so the real 3D camera shows through */
@@ -476,8 +480,8 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View
float alpha = 1.0f;
if (ca->passepartalpha != 1.0f) {
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
+ 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;
}
@@ -492,7 +496,7 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View
if (y2i > 0.0f)
immRectf(shdr_pos, x1i, y1i, x2i, 0.0f);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
immUniformThemeColor(TH_BACK);
@@ -514,7 +518,7 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View
{
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
immUniform1i("num_colors", 0); /* "simple" mode */
@@ -646,7 +650,7 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View
/* 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... */
@@ -671,12 +675,12 @@ static void drawrenderborder(ARegion *ar, View3D *v3d)
/* use the same program for everything */
uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
immUniform1i("num_colors", 0); /* "simple" mode */
@@ -715,7 +719,7 @@ void ED_view3d_draw_depth(
ED_view3d_draw_setup_view(NULL, depsgraph, scene, ar, v3d, NULL, NULL, NULL);
- glClear(GL_DEPTH_BUFFER_BIT);
+ GPU_clear(GPU_DEPTH_BIT);
if (rv3d->rflag & RV3D_CLIPPING) {
ED_view3d_clipping_set(rv3d);
@@ -724,7 +728,7 @@ void ED_view3d_draw_depth(
rv3d->rflag |= RV3D_ZOFFSET_DISABLED;
v3d->zbuf = true;
- glEnable(GL_DEPTH_TEST);
+ GPU_depth_test(true);
DRW_draw_depth_loop(depsgraph, ar, v3d);
@@ -734,7 +738,7 @@ void ED_view3d_draw_depth(
rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED;
v3d->zbuf = zbuf;
- if (!v3d->zbuf) glDisable(GL_DEPTH_TEST);
+ if (!v3d->zbuf) GPU_depth_test(false);
U.glalphaclip = glalphaclip;
v3d->flag = flag;
@@ -776,8 +780,13 @@ static void draw_view_axis(RegionView3D *rv3d, const rcti *rect)
const float k = U.rvisize * U.pixelsize; /* axis size */
const int bright = - 20 * (10 - U.rvibright); /* axis alpha offset (rvibright has range 0-10) */
- const float startx = rect->xmin + k + 1.0f; /* axis center in screen coordinates, x=y */
- const float starty = rect->ymin + k + 1.0f;
+ /* 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];
unsigned char axis_col[3][4];
@@ -801,10 +810,10 @@ static void draw_view_axis(RegionView3D *rv3d, const rcti *rect)
}
/* draw axis lines */
- glLineWidth(2.0f);
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ 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);
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -824,7 +833,7 @@ static void draw_view_axis(RegionView3D *rv3d, const rcti *rect)
immEnd();
immUnbindProgram();
- glDisable(GL_LINE_SMOOTH);
+ GPU_line_smooth(false);
/* draw axis names */
for (int axis_i = 0; axis_i < 3; axis_i++) {
@@ -847,8 +856,8 @@ static void UNUSED_FUNCTION(draw_rotation_guide)(RegionView3D *rv3d)
negate_v3_v3(o, rv3d->ofs);
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
glDepthMask(GL_FALSE); /* don't overwrite zbuf */
Gwn_VertFormat *format = immVertexFormat();
@@ -884,7 +893,7 @@ static void UNUSED_FUNCTION(draw_rotation_guide)(RegionView3D *rv3d)
sub_v3_v3v3(end, o, scaled_axis);
immVertex3fv(pos, end);
immEnd();
-
+
/* -- draw ring around rotation center -- */
{
#define ROT_AXIS_DETAIL 13
@@ -931,7 +940,7 @@ static void UNUSED_FUNCTION(draw_rotation_guide)(RegionView3D *rv3d)
/* -- draw rotation center -- */
immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR);
- glPointSize(5.0f);
+ GPU_point_size(5.0f);
immBegin(GWN_PRIM_POINTS, 1);
immAttrib4ubv(col, color);
immVertex3fv(pos, o);
@@ -945,7 +954,7 @@ static void UNUSED_FUNCTION(draw_rotation_guide)(RegionView3D *rv3d)
/* ^^ just playing around, does not work */
#endif
- glDisable(GL_BLEND);
+ GPU_blend(false);
glDepthMask(GL_TRUE);
}
#endif /* WITH_INPUT_NDOF */
@@ -1078,7 +1087,6 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect)
char info[300];
char *s = info;
- short offset = 1.5f * UI_UNIT_X + rect->xmin;
s += sprintf(s, "(%d)", cfra);
@@ -1169,10 +1177,7 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect)
s += sprintf(s, " <%s>", markern);
}
- if (U.uiflag & USER_SHOW_ROTVIEWICON)
- offset = U.widget_unit + (U.rvisize * 2) + rect->xmin;
-
- BLF_draw_default(offset, 0.5f * U.widget_unit, 0.0f, info, sizeof(info));
+ BLF_draw_default(rect->xmin + UI_UNIT_X, rect->ymax - (2 * U.widget_unit), 0.0f, info, sizeof(info));
}
/* ******************** view loop ***************** */
@@ -1180,7 +1185,7 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect)
/**
* Information drawn on top of the solid plates and composed data
*/
-void view3d_draw_region_info(const bContext *C, ARegion *ar, const int offset)
+void view3d_draw_region_info(const bContext *C, ARegion *ar, const int UNUSED(offset))
{
RegionView3D *rv3d = ar->regiondata;
View3D *v3d = CTX_wm_view3d(C);
@@ -1194,45 +1199,53 @@ void view3d_draw_region_info(const bContext *C, ARegion *ar, const int offset)
rcti rect;
ED_region_visible_rect(ar, &rect);
- /* Leave room for previously drawn info. */
- rect.ymax -= offset;
view3d_draw_border(C, ar);
view3d_draw_grease_pencil(C);
BLF_batch_draw_begin();
- if (U.uiflag & USER_SHOW_ROTVIEWICON) {
+ if (((U.uiflag & USER_SHOW_ROTVIEWICON) != 0) &&
+ ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
+ /* No need to display manipulator and this info. */
+ ((U.manipulator_flag & USER_MANIPULATOR_DRAW_NAVIGATE) == 0))
+ {
draw_view_axis(rv3d, &rect);
}
- if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) {
- ED_scene_draw_fps(scene, &rect);
- }
- else if (U.uiflag & USER_SHOW_VIEWPORTNAME) {
- draw_viewport_name(ar, v3d, &rect);
- }
+ if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 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, &rect);
+ }
+ else if (U.uiflag & USER_SHOW_VIEWPORTNAME) {
+ draw_viewport_name(ar, v3d, &rect);
+ }
- if (U.uiflag & USER_DRAWVIEWINFO) {
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- draw_selected_name(scene, ob, &rect);
- }
+ if (U.uiflag & USER_DRAWVIEWINFO) {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ draw_selected_name(scene, ob, &rect);
+ }
#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);
+ }
- BLF_draw_default_ascii(rect.xmin + U.widget_unit,
- rect.ymax - (USER_SHOW_VIEWPORTNAME ? 2 * U.widget_unit : U.widget_unit), 0.0f,
- numstr[0] ? numstr : grid_unit, sizeof(numstr));
- }
+ BLF_draw_default_ascii(
+ rect.xmin + U.widget_unit,
+ rect.ymax - (USER_SHOW_VIEWPORTNAME ? 2 * U.widget_unit : U.widget_unit), 0.0f,
+ numstr[0] ? numstr : grid_unit, sizeof(numstr));
+ }
#endif
+ }
+
BLF_batch_draw_end();
}
@@ -1247,7 +1260,7 @@ static void view3d_draw_view(const bContext *C, ARegion *ar)
RenderEngineType *ED_view3d_engine_type(Scene *scene, int drawtype)
{
/*
- * Tempory viewport draw modes until we have a proper system.
+ * Tempory 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.
*/
@@ -1259,11 +1272,12 @@ RenderEngineType *ED_view3d_engine_type(Scene *scene, int drawtype)
void view3d_main_region_draw(const bContext *C, ARegion *ar)
{
+ Main *bmain = CTX_data_main(C);
View3D *v3d = CTX_wm_view3d(C);
view3d_draw_view(C, ar);
- GPU_free_images_old();
+ GPU_free_images_old(bmain);
GPU_pass_cache_garbage_collect();
/* XXX This is in order to draw UI batches with the DRW
@@ -1271,7 +1285,7 @@ void view3d_main_region_draw(const bContext *C, ARegion *ar)
gpu_batch_presets_reset();
/* No depth test for drawing action zones afterwards. */
- glDisable(GL_DEPTH_TEST);
+ GPU_depth_test(false);
v3d->flag |= V3D_INVALID_BACKBUF;
}
@@ -1336,7 +1350,7 @@ void ED_view3d_draw_offscreen(
if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
/* free images which can have changed on frame-change
* warning! can be slow so only free animated images - campbell */
- GPU_free_images_anim();
+ GPU_free_images_anim(G.main); /* XXX :((( */
}
gpuPushProjectionMatrix();
@@ -1417,13 +1431,16 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
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.clipsta = v3d->near;
params.clipend = v3d->far;
- BKE_camera_params_from_object(&params, camera);
- BKE_camera_multiview_params(&scene->r, &params, camera, viewname);
+ 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);
@@ -1597,11 +1614,13 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
{
CameraParams params;
- Object *view_camera = BKE_camera_multiview_render(scene, v3d.camera, viewname);
+ 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);
- BKE_camera_multiview_params(&scene->r, &params, view_camera, viewname);
+ 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);
diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c
index 5b0f50b7a68..06cdba3f537 100644
--- a/source/blender/editors/space_view3d/view3d_draw_legacy.c
+++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c
@@ -57,7 +57,6 @@
#include "BKE_camera.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_image.h"
#include "BKE_key.h"
#include "BKE_layer.h"
@@ -105,6 +104,7 @@
#include "GPU_immediate_util.h"
#include "GPU_select.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "RE_engine.h"
@@ -163,7 +163,8 @@ bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], const
static void backdrawview3d(
struct Depsgraph *depsgraph, Scene *scene,
ARegion *ar, View3D *v3d,
- Object *obact, Object *obedit)
+ Object *obact, Object *obedit,
+ short select_mode)
{
RegionView3D *rv3d = ar->regiondata;
Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id);
@@ -245,16 +246,16 @@ static void backdrawview3d(
if (rv3d->gpuoffscreen)
GPU_offscreen_bind(rv3d->gpuoffscreen, true);
else
- glScissor(ar->winrct.xmin, ar->winrct.ymin, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct));
+ GPU_scissor(ar->winrct.xmin, ar->winrct.ymin, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct));
- glClearColor(0.0, 0.0, 0.0, 0.0);
+ GPU_clear_color(0.0, 0.0, 0.0, 0.0);
if (v3d->zbuf) {
- glEnable(GL_DEPTH_TEST);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ GPU_depth_test(true);
+ GPU_clear(GPU_COLOR_BIT | GPU_DEPTH_BIT);
}
else {
- glClear(GL_COLOR_BUFFER_BIT);
- glDisable(GL_DEPTH_TEST);
+ GPU_clear(GPU_COLOR_BIT);
+ GPU_depth_test(false);
}
if (rv3d->rflag & RV3D_CLIPPING)
@@ -262,8 +263,8 @@ static void backdrawview3d(
G.f |= G_BACKBUFSEL;
- if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLED) != 0)) {
- draw_object_backbufsel(depsgraph, scene_eval, v3d, rv3d, obact_eval);
+ if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) {
+ draw_object_backbufsel(depsgraph, scene_eval, v3d, rv3d, obact_eval, select_mode);
}
if (rv3d->gpuoffscreen)
@@ -273,7 +274,7 @@ static void backdrawview3d(
G.f &= ~G_BACKBUFSEL;
v3d->zbuf = false;
- glDisable(GL_DEPTH_TEST);
+ GPU_depth_test(false);
glEnable(GL_DITHER);
if (rv3d->rflag & RV3D_CLIPPING)
@@ -301,13 +302,18 @@ static void view3d_opengl_read_Z_pixels(ARegion *ar, int x, int y, int w, int h,
glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data);
}
-void ED_view3d_backbuf_validate(ViewContext *vc)
+void ED_view3d_backbuf_validate_with_select_mode(ViewContext *vc, short select_mode)
{
if (vc->v3d->flag & V3D_INVALID_BACKBUF) {
- backdrawview3d(vc->depsgraph, vc->scene, vc->ar, vc->v3d, vc->obact, vc->obedit);
+ backdrawview3d(vc->depsgraph, vc->scene, vc->ar, vc->v3d, vc->obact, vc->obedit, select_mode);
}
}
+void ED_view3d_backbuf_validate(ViewContext *vc)
+{
+ ED_view3d_backbuf_validate_with_select_mode(vc, -1);
+}
+
/**
* allow for small values [0.5 - 2.5],
* and large values, FLT_MAX by clamping by the area size
@@ -678,11 +684,11 @@ static void view3d_draw_bgpic(Scene *scene, Depsgraph *depsgraph,
ibuf = ibuf->mipmap[mip - 1];
}
- if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
+ if (v3d->zbuf) GPU_depth_test(false);
glDepthMask(GL_FALSE);
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
gpuPushProjectionMatrix();
gpuPushMatrix();
@@ -709,10 +715,10 @@ static void view3d_draw_bgpic(Scene *scene, Depsgraph *depsgraph,
gpuPopProjectionMatrix();
gpuPopMatrix();
- glDisable(GL_BLEND);
+ GPU_blend(false);
glDepthMask(GL_TRUE);
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
+ if (v3d->zbuf) GPU_depth_test(true);
if (freeibuf)
IMB_freeImBuf(freeibuf);
@@ -877,17 +883,17 @@ void ED_view3d_draw_depth_gpencil(
/* Setup view matrix. */
ED_view3d_draw_setup_view(NULL, depsgraph, scene, ar, v3d, NULL, NULL, NULL);
- glClear(GL_DEPTH_BUFFER_BIT);
+ GPU_clear(GPU_DEPTH_BIT);
v3d->zbuf = true;
- glEnable(GL_DEPTH_TEST);
+ GPU_depth_test(true);
if (v3d->flag2 & V3D_SHOW_GPENCIL) {
ED_gpencil_draw_view3d(NULL, scene, view_layer, depsgraph, v3d, ar, true);
}
v3d->zbuf = zbuf;
- if (!zbuf) glDisable(GL_DEPTH_TEST);
+ if (!zbuf) GPU_depth_test(false);
}
/* *********************** customdata **************** */
@@ -1026,7 +1032,7 @@ void ED_scene_draw_fps(Scene *scene, const rcti *rect)
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->render_to_view);
+ 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)
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 95e688dcc08..590ab80a4c8 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -54,6 +54,7 @@
#include "BKE_font.h"
#include "BKE_layer.h"
#include "BKE_library.h"
+#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_report.h"
@@ -62,7 +63,7 @@
#include "BKE_action.h"
#include "DEG_depsgraph.h"
-
+#include "DEG_depsgraph_query.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -86,8 +87,6 @@
#include "view3d_intern.h" /* own include */
-#include "DEG_depsgraph_query.h"
-
/* -------------------------------------------------------------------- */
/** \name Generic View Operator Properties
* \{ */
@@ -132,6 +131,7 @@ 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;
@@ -222,6 +222,7 @@ static void viewops_data_alloc(bContext *C, wmOperator *op)
/* 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);
@@ -250,9 +251,11 @@ 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 = CTX_data_view_layer(C);
- Object *ob_act = OBACT(view_layer);
+ ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
+ 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 */
@@ -264,16 +267,16 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
*/
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, stroke);
+ BKE_paint_stroke_get_average(scene, ob_act_eval, stroke);
copy_v3_v3(lastofs, stroke);
}
else {
- copy_v3_v3(lastofs, ob_act->obmat[3]);
+ 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->data;
+ Curve *cu = ob_act_eval->data;
EditFont *ef = cu->editfont;
int i;
@@ -283,32 +286,32 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
}
mul_v2_fl(lastofs, 1.0f / 4.0f);
- mul_m4_v3(ob_act->obmat, lastofs);
+ 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;
+ Base *base_eval;
unsigned int tot = 0;
float select_center[3];
zero_v3(select_center);
- for (base = FIRSTBASE(view_layer); base; base = base->next) {
- if (TESTBASE(base)) {
+ for (base_eval = FIRSTBASE(view_layer_eval); base_eval; base_eval = base_eval->next) {
+ if (TESTBASE(base_eval)) {
/* use the boundbox if we can */
- Object *ob = base->object;
+ Object *ob_eval = base_eval->object;
- if (ob->bb && !(ob->bb->flag & BOUNDBOX_DIRTY)) {
+ if (ob_eval->bb && !(ob_eval->bb->flag & BOUNDBOX_DIRTY)) {
float cent[3];
- BKE_boundbox_calc_center_aabb(ob->bb, cent);
+ BKE_boundbox_calc_center_aabb(ob_eval->bb, cent);
- mul_m4_v3(ob->obmat, cent);
+ mul_m4_v3(ob_eval->obmat, cent);
add_v3_v3(select_center, cent);
}
else {
- add_v3_v3(select_center, ob->obmat[3]);
+ add_v3_v3(select_center, ob_eval->obmat[3]);
}
tot++;
}
@@ -371,6 +374,7 @@ 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;
@@ -381,7 +385,6 @@ static void viewops_data_create(
/* we need the depth info before changing any viewport options */
if (viewops_flag & VIEWOPS_FLAG_DEPTH_NAVIGATE) {
- struct Depsgraph *graph = CTX_data_depsgraph(C);
float fallback_depth_pt[3];
view3d_operator_needs_opengl(C); /* needed for zbuf drawing */
@@ -389,7 +392,7 @@ static void viewops_data_create(
negate_v3_v3(fallback_depth_pt, rv3d->ofs);
vod->use_dyn_ofs = ED_view3d_autodist(
- graph, vod->ar, vod->v3d,
+ depsgraph, vod->ar, vod->v3d,
event->mval, vod->dyn_ofs, true, fallback_depth_pt);
}
else {
@@ -397,7 +400,7 @@ static void viewops_data_create(
}
if (viewops_flag & VIEWOPS_FLAG_PERSP_ENSURE) {
- if (ED_view3d_persp_ensure(vod->v3d, vod->ar)) {
+ 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.
@@ -408,7 +411,7 @@ static void viewops_data_create(
/* 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(vod->v3d, vod->rv3d);
+ ED_view3d_camera_lock_init(depsgraph, vod->v3d, vod->rv3d);
vod->init.dist = rv3d->dist;
vod->init.camzoom = rv3d->camzoom;
@@ -811,7 +814,7 @@ static void viewrotate_apply(ViewOpsData *vod, const int event_xy[2])
vod->prev.event_xy[0] = event_xy[0];
vod->prev.event_xy[1] = event_xy[1];
- ED_view3d_camera_lock_sync(vod->v3d, rv3d);
+ ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, rv3d);
ED_region_tag_redraw(vod->ar);
}
@@ -1109,8 +1112,7 @@ static void view3d_ndof_pan_zoom(
static void view3d_ndof_orbit(
const struct wmNDOFMotionData *ndof, ScrArea *sa, ARegion *ar,
- /* optional, can be NULL*/
- ViewOpsData *vod)
+ ViewOpsData *vod, const bool apply_dyn_ofs)
{
View3D *v3d = sa->spacedata.first;
RegionView3D *rv3d = ar->regiondata;
@@ -1119,7 +1121,7 @@ static void view3d_ndof_orbit(
BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0);
- ED_view3d_persp_ensure(v3d, ar);
+ ED_view3d_persp_ensure(vod->depsgraph, v3d, ar);
rv3d->view = RV3D_VIEW_USER;
@@ -1173,7 +1175,7 @@ static void view3d_ndof_orbit(
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat);
}
- if (vod) {
+ if (apply_dyn_ofs) {
viewrotate_apply_dyn_ofs(vod, rv3d->viewquat);
}
}
@@ -1308,6 +1310,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
}
else {
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
ViewOpsData *vod;
View3D *v3d;
RegionView3D *rv3d;
@@ -1328,7 +1331,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* off by default, until changed later this function */
rv3d->rot_angle = 0.0f;
- ED_view3d_camera_lock_init_ex(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;
@@ -1341,11 +1344,11 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
if (has_rotation) {
- view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod);
+ view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, true);
}
}
- ED_view3d_camera_lock_sync(v3d, rv3d);
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
ED_region_tag_redraw(vod->ar);
@@ -1376,6 +1379,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
return OPERATOR_CANCELLED;
}
else {
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
ViewOpsData *vod;
View3D *v3d;
RegionView3D *rv3d;
@@ -1397,7 +1401,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
/* off by default, until changed later this function */
rv3d->rot_angle = 0.0f;
- ED_view3d_camera_lock_init_ex(v3d, rv3d, false);
+ ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
if (ndof->progress == P_FINISHING) {
/* pass */
@@ -1422,7 +1426,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
}
if (has_rotation) {
- view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod);
+ view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, true);
}
}
else { /* free/explore (like fly mode) */
@@ -1440,13 +1444,13 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
ED_view3d_distance_set(rv3d, 0.0f);
if (has_rotation) {
- view3d_ndof_orbit(ndof, vod->sa, vod->ar, NULL);
+ view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, false);
}
ED_view3d_distance_set(rv3d, dist_backup);
}
- ED_view3d_camera_lock_sync(v3d, rv3d);
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
ED_region_tag_redraw(vod->ar);
@@ -1480,6 +1484,7 @@ static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *e
return OPERATOR_CANCELLED;
}
else {
+ 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;
@@ -1493,7 +1498,7 @@ static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *e
if (!(has_translate || has_zoom))
return OPERATOR_CANCELLED;
- ED_view3d_camera_lock_init_ex(v3d, rv3d, false);
+ ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
if (ndof->progress != P_FINISHING) {
ScrArea *sa = CTX_wm_area(C);
@@ -1504,7 +1509,7 @@ static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *e
}
}
- ED_view3d_camera_lock_sync(v3d, rv3d);
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
ED_region_tag_redraw(CTX_wm_region(C));
@@ -1549,7 +1554,7 @@ static int ndof_all_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void VIEW3D_OT_ndof_all(struct wmOperatorType *ot)
{
/* identifiers */
- ot->name = "NDOF Move View";
+ ot->name = "NDOF Pan View";
ot->description = "Pan and rotate the view with the 3D mouse";
ot->idname = "VIEW3D_OT_ndof_all";
@@ -1637,7 +1642,7 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y)
vod->prev.event_xy[0] = x;
vod->prev.event_xy[1] = y;
- ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
+ ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
ED_region_tag_redraw(vod->ar);
}
@@ -1739,7 +1744,7 @@ void VIEW3D_OT_move(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Move View";
+ ot->name = "Pan View";
ot->description = "Move the view";
ot->idname = "VIEW3D_OT_move";
@@ -1806,7 +1811,7 @@ static void view_zoom_to_window_xy_camera(
{
RegionView3D *rv3d = ar->regiondata;
const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom);
- const float zoomfac_new = CLAMPIS(zoomfac * (1.0f / dfac), RV3D_CAMZOOM_MIN_FACTOR, RV3D_CAMZOOM_MAX_FACTOR);
+ 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);
@@ -2036,7 +2041,7 @@ static void viewzoom_apply_3d(
view3d_boxview_sync(vod->sa, vod->ar);
}
- ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
+ ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
ED_region_tag_redraw(vod->ar);
}
@@ -2187,7 +2192,7 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
ED_view3d_depth_tag_update(rv3d);
- ED_view3d_camera_lock_sync(v3d, rv3d);
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, true);
ED_region_tag_redraw(ar);
@@ -2381,7 +2386,7 @@ static void viewdolly_apply(ViewOpsData *vod, const int xy[2], const short zoom_
view3d_boxview_sync(vod->sa, vod->ar);
}
- ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
+ ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
ED_region_tag_redraw(vod->ar);
}
@@ -2482,7 +2487,7 @@ static int viewdolly_exec(bContext *C, wmOperator *op)
ED_view3d_depth_tag_update(rv3d);
- ED_view3d_camera_lock_sync(v3d, rv3d);
+ ED_view3d_camera_lock_sync(CTX_data_depsgraph(C), v3d, rv3d);
ED_region_tag_redraw(ar);
@@ -2516,7 +2521,8 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if (vod->rv3d->persp != RV3D_PERSP) {
if (vod->rv3d->persp == RV3D_CAMOB) {
/* ignore rv3d->lpersp because dolly only makes sense in perspective mode */
- ED_view3d_persp_switch_from_camera(vod->v3d, vod->rv3d, RV3D_PERSP);
+ 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;
@@ -2650,7 +2656,7 @@ static void view3d_from_minmax(
}
if (ok_dist) {
- new_dist = ED_view3d_radius_to_dist(v3d, ar, persp, true, (size / 2) * VIEW3D_MARGIN);
+ 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->near * 1.5f);
@@ -2705,8 +2711,9 @@ static int view3d_all_exec(bContext *C, wmOperator *op)
ARegion *ar = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *base;
+ 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 */
@@ -2729,15 +2736,16 @@ static int view3d_all_exec(bContext *C, wmOperator *op)
INIT_MINMAX(min, max);
}
- for (base = view_layer->object_bases.first; base; base = base->next) {
- if (BASE_VISIBLE(base)) {
+ for (base_eval = view_layer_eval->object_bases.first; base_eval; base_eval = base_eval->next) {
+ if (BASE_VISIBLE(base_eval)) {
changed = true;
- if (skip_camera && base->object == v3d->camera) {
+ Object *ob = DEG_get_original_object(base_eval->object);
+ if (skip_camera && ob == v3d->camera) {
continue;
}
- BKE_object_minmax(base->object, min, max, false);
+ BKE_object_minmax(base_eval->object, min, max, false);
}
}
if (!changed) {
@@ -2759,6 +2767,10 @@ static int view3d_all_exec(bContext *C, wmOperator *op)
view3d_from_minmax(C, v3d, ar, min, max, true, smooth_viewtx);
}
+ if (center) {
+ DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
+ }
+
return OPERATOR_FINISHED;
}
@@ -2981,7 +2993,8 @@ static int view_lock_to_active_exec(bContext *C, wmOperator *UNUSED(op))
if (obact && obact->type == OB_ARMATURE) {
if (obact->mode & OB_MODE_POSE) {
- bPoseChannel *pcham_act = BKE_pose_channel_active(obact);
+ 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));
}
@@ -3078,7 +3091,7 @@ static int viewcenter_pick_invoke(bContext *C, wmOperator *op, const wmEvent *ev
ARegion *ar = CTX_wm_region(C);
if (rv3d) {
- struct Depsgraph *graph = CTX_data_depsgraph(C);
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
float new_ofs[3];
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
@@ -3086,7 +3099,7 @@ static int viewcenter_pick_invoke(bContext *C, wmOperator *op, const wmEvent *ev
view3d_operator_needs_opengl(C);
- if (ED_view3d_autodist(graph, ar, v3d, event->mval, new_ofs, false, NULL)) {
+ if (ED_view3d_autodist(depsgraph, ar, v3d, event->mval, new_ofs, false, NULL)) {
/* pass */
}
else {
@@ -3276,6 +3289,9 @@ static int render_border_exec(bContext *C, wmOperator *op)
v3d->flag2 |= V3D_RENDER_BORDER;
}
+ if (rv3d->persp == RV3D_CAMOB) {
+ DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
+ }
return OPERATOR_FINISHED;
}
@@ -3339,6 +3355,9 @@ static int clear_render_border_exec(bContext *C, wmOperator *UNUSED(op))
border->xmax = 1.0f;
border->ymax = 1.0f;
+ if (rv3d->persp == RV3D_CAMOB) {
+ DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
+ }
return OPERATOR_FINISHED;
}
@@ -3665,7 +3684,8 @@ static void axis_set_view(
dist = rv3d->dist;
/* so we animate _from_ the camera location */
- ED_view3d_from_object(v3d->camera, rv3d->ofs, NULL, &rv3d->dist, NULL);
+ 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,
@@ -3695,8 +3715,6 @@ static int viewnumpad_exec(bContext *C, wmOperator *op)
View3D *v3d;
ARegion *ar;
RegionView3D *rv3d;
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
static int perspo = RV3D_PERSP;
int viewnum, nextperspo;
bool align_active;
@@ -3730,6 +3748,9 @@ static int viewnumpad_exec(bContext *C, wmOperator *op)
if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
/* lastview - */
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Scene *scene = CTX_data_scene(C);
+
if (rv3d->persp != RV3D_CAMOB) {
Object *ob = OBACT(view_layer);
@@ -3874,7 +3895,8 @@ static int vieworbit_exec(bContext *C, wmOperator *op)
float quat_new[4];
if (view_opposite == RV3D_VIEW_USER) {
- ED_view3d_persp_ensure(v3d, ar);
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ED_view3d_persp_ensure(depsgraph, v3d, ar);
}
if (ELEM(orbitdir, V3D_VIEW_STEPLEFT, V3D_VIEW_STEPRIGHT)) {
@@ -3999,7 +4021,7 @@ static void viewroll_apply(ViewOpsData *vod, int x, int UNUSED(y))
view3d_boxview_sync(vod->sa, vod->ar);
}
- ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
+ ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
ED_region_tag_redraw(vod->ar);
}
@@ -4233,8 +4255,8 @@ static int viewpan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void VIEW3D_OT_view_pan(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "View Pan";
- ot->description = "Pan the view";
+ ot->name = "Pan View Direction";
+ ot->description = "Pan the view in a given direction";
ot->idname = "VIEW3D_OT_view_pan";
/* api callbacks */
@@ -4531,7 +4553,7 @@ 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, float fp[3], const int mval[2])
+void ED_view3d_cursor3d_position(bContext *C, const int mval[2], bool use_depth, float cursor_co[3])
{
ARegion *ar = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -4544,49 +4566,62 @@ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2])
if (rv3d == NULL)
return;
- ED_view3d_calc_zfac(rv3d, fp, &flip);
+ 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(fp, rv3d->ofs);
+ negate_v3_v3(cursor_co, rv3d->ofs);
/* re initialize, no need to check flip again */
- ED_view3d_calc_zfac(rv3d, fp, NULL /* &flip */ );
+ ED_view3d_calc_zfac(rv3d, cursor_co, NULL /* &flip */ );
}
- if (U.uiflag & USER_DEPTH_CURSOR) { /* maybe this should be accessed some other way */
- struct Depsgraph *graph = CTX_data_depsgraph(C);
+ 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(graph, ar, v3d, mval, fp, true, NULL)) {
+ 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, fp);
- ED_view3d_win_to_3d_int(v3d, ar, depth_pt, mval, fp);
+ copy_v3_v3(depth_pt, cursor_co);
+ ED_view3d_win_to_3d_int(v3d, ar, depth_pt, mval, cursor_co);
}
}
-void ED_view3d_cursor3d_update(bContext *C, const int mval[2])
+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;
- View3DCursor *cursor_curr = ED_view3d_cursor3d_get(scene, v3d);
- View3DCursor cursor_prev = *cursor_curr;
+ /* XXX, caller should check. */
+ if (rv3d == NULL)
+ return;
- ED_view3d_cursor3d_position(C, cursor_curr->location, mval);
- copy_qt_qt(cursor_curr->rotation, rv3d->viewquat);
- cursor_curr->rotation[0] *= -1.0f;
+ 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_GEOM) {
+ copy_qt_qt(cursor_quat, rv3d->viewquat);
+ cursor_quat[0] *= -1.0f;
- {
- struct Main *bmain = CTX_data_main(C);
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);
@@ -4601,17 +4636,22 @@ void ED_view3d_cursor3d_update(bContext *C, const int mval[2])
.snap_select = SNAP_ALL,
.use_object_edit_cage = false,
},
- mval_fl, &dist_px, NULL,
- cursor_curr->location, ray_no, NULL,
+ 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_curr->rotation, z_src);
+ mul_qt_v3(cursor_quat, z_src);
rotation_between_vecs_to_quat(tquat, z_src, ray_no);
- mul_qt_qtqt(cursor_curr->rotation, tquat, cursor_curr->rotation);
+ mul_qt_qtqt(cursor_quat, tquat, cursor_quat);
}
/* Match object matrix (X). */
@@ -4624,27 +4664,47 @@ void ED_view3d_cursor3d_update(bContext *C, const int mval[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_curr->rotation, x_src);
+ 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_curr->rotation, tquat, cursor_curr->rotation);
+ 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 = ED_view3d_cursor3d_get(scene, v3d);
+ View3DCursor cursor_prev = *cursor_curr;
+
+ ED_view3d_cursor3d_position_rotation(
+ C, mval,
+ use_depth, orientation,
+ cursor_curr->location, cursor_curr->rotation);
/* offset the cursor lock to avoid jumping to new offset */
if (v3d->ob_centre_cursor) {
if (U.uiflag & USER_LOCK_CURSOR_ADJUST) {
- float co_curr[2], co_prev[2];
+ float co_2d_curr[2], co_2d_prev[2];
- if ((ED_view3d_project_float_global(ar, cursor_prev.location, co_prev, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) &&
- (ED_view3d_project_float_global(ar, cursor_curr->location, co_curr, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK))
+ 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_curr[0] - co_prev[0]) / (ar->winx * 0.5f);
- rv3d->ofs_lock[1] += (co_curr[1] - co_prev[1]) / (ar->winy * 0.5f);
+ 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 {
@@ -4667,9 +4727,20 @@ void ED_view3d_cursor3d_update(bContext *C, const int mval[2])
DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
}
-static int view3d_cursor3d_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+static int view3d_cursor3d_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ED_view3d_cursor3d_update(C, event->mval);
+ 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;
}
@@ -4689,6 +4760,24 @@ void VIEW3D_OT_cursor3d(wmOperatorType *ot)
/* 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_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_enum(
+ ot->srna, "orientation", orientation_items, V3D_CURSOR_ORIENT_VIEW,
+ "Orientation", "Preset viewpoint to use");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c
index 3715f4672d7..f9fdf8c2cc0 100644
--- a/source/blender/editors/space_view3d/view3d_fly.c
+++ b/source/blender/editors/space_view3d/view3d_fly.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
+ *
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
@@ -151,7 +151,7 @@ void fly_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, KM_ANY, 0, FLY_MODAL_DECELERATE);
WM_modalkeymap_add_item(keymap, MOUSEPAN, 0, 0, 0, FLY_MODAL_SPEED);
-
+
WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_PRESS, KM_ANY, 0, FLY_MODAL_PAN_ENABLE);
/* XXX - Bug in the event system, middle mouse release doesnt work */
WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, FLY_MODAL_PAN_DISABLE);
@@ -333,7 +333,7 @@ static void fly_update_header(bContext *C, wmOperator *op, FlyInfo *fly)
#undef WM_MODALKEY
- ED_area_headerprint(CTX_wm_area(C), header);
+ ED_workspace_status_text(C, header);
}
/* FlyInfo->state */
@@ -550,12 +550,12 @@ static void flyEvent(bContext *C, wmOperator *op, FlyInfo *fly, const wmEvent *e
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;
@@ -563,7 +563,7 @@ static void flyEvent(bContext *C, wmOperator *op, FlyInfo *fly, const wmEvent *e
fly->speed = 0.0f;
else
fly->speed += fly->grid * fac;
-
+
break;
}
case FLY_MODAL_ACCELERATE:
@@ -1082,7 +1082,7 @@ static int fly_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
if (ELEM(exit_code, OPERATOR_FINISHED, OPERATOR_CANCELLED))
- ED_area_headerprint(CTX_wm_area(C), NULL);
+ ED_workspace_status_text(C, NULL);
return exit_code;
}
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index e7f6cf36476..4f81fa7585c 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2004-2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -117,7 +117,7 @@ static int view3d_layers_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
int nr = RNA_int_get(op->ptr, "nr");
const bool toggle = RNA_boolean_get(op->ptr, "toggle");
-
+
if (nr < 0)
return OPERATOR_CANCELLED;
@@ -165,13 +165,13 @@ static int view3d_layers_exec(bContext *C, wmOperator *op)
}
}
}
-
+
if (v3d->scenelock) handle_view3d_lock(C);
-
+
DEG_on_visible_update(CTX_data_main(C), false);
ED_area_tag_redraw(sa);
-
+
return OPERATOR_FINISHED;
}
@@ -181,18 +181,18 @@ static int view3d_layers_invoke(bContext *C, wmOperator *op, const wmEvent *even
{
if (event->ctrl || event->oskey)
return OPERATOR_PASS_THROUGH;
-
+
if (event->shift)
RNA_boolean_set(op->ptr, "extend", true);
else
RNA_boolean_set(op->ptr, "extend", false);
-
+
if (event->alt) {
const int nr = RNA_int_get(op->ptr, "nr") + 10;
RNA_int_set(op->ptr, "nr", nr);
}
view3d_layers_exec(C, op);
-
+
return OPERATOR_FINISHED;
}
@@ -207,20 +207,86 @@ void VIEW3D_OT_layers(wmOperatorType *ot)
ot->name = "Layers";
ot->description = "Toggle layer(s) visibility";
ot->idname = "VIEW3D_OT_layers";
-
+
/* api callbacks */
ot->invoke = view3d_layers_invoke;
ot->exec = view3d_layers_exec;
ot->poll = view3d_layers_poll;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
RNA_def_int(ot->srna, "nr", 1, 0, 20, "Number", "The layer number to set, zero for all layers", 0, 20);
RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Add this layer to the current view layers");
RNA_def_boolean(ot->srna, "toggle", 1, "Toggle", "Toggle the layer");
}
+/* -------------------------------------------------------------------- */
+/** \name Toggle Bone selection Overlay Operator
+ * \{ */
+
+static int toggle_show_xray(bContext *C, wmOperator *UNUSED(op))
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ v3d->shading.flag ^= V3D_SHADING_XRAY;
+ ED_view3d_shade_update(CTX_data_main(C), v3d, CTX_wm_area(C));
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ return OPERATOR_FINISHED;
+}
+
+static int toggle_show_xray_poll(bContext *C)
+{
+ bool result = (ED_operator_view3d_active(C) && !ED_operator_posemode(C) && !ED_operator_editmesh(C));
+ if (result) {
+ // Additional test for SOLID or TEXTURE mode
+ View3D *v3d = CTX_wm_view3d(C);
+ result = (v3d->drawtype & (OB_SOLID | OB_TEXTURE)) > 0;
+ }
+ return result;
+}
+
+void VIEW3D_OT_toggle_xray_draw_option(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Toggle Show X-Ray";
+ ot->description = "Toggle show X-Ray";
+ ot->idname = "VIEW3D_OT_toggle_xray_draw_option";
+
+ /* api callbacks */
+ ot->exec = toggle_show_xray;
+ ot->poll = toggle_show_xray_poll;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Toggle Bone selection Overlay Operator
+ * \{ */
+
+static int toggle_matcap_flip(bContext *C, wmOperator *UNUSED(op))
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ 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);
+ 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";
+
+ /* api callbacks */
+ ot->exec = toggle_matcap_flip;
+ // ot->poll = toggle_show_xray_poll;
+}
+
+/** \} */
+
+
static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event)
{
wmWindow *win = CTX_wm_window(C);
@@ -332,7 +398,7 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
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));
-
+
RNA_pointer_create(&screen->id, &RNA_SpaceView3D, v3d, &v3dptr);
RNA_pointer_create(&scene->id, &RNA_ToolSettings, ts, &toolsptr);
RNA_pointer_create(&scene->id, &RNA_Scene, scene, &sceneptr);
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 006b0117b99..8263d1d892c 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -41,7 +41,6 @@ struct Base;
struct BoundBox;
struct Gwn_Batch;
struct Depsgraph;
-struct DerivedMesh;
struct Object;
struct SmokeDomainSettings;
struct bAnimVizSettings;
@@ -65,6 +64,8 @@ enum {
/* view3d_header.c */
void VIEW3D_OT_layers(struct wmOperatorType *ot);
+void VIEW3D_OT_toggle_xray_draw_option(struct wmOperatorType *ot);
+void VIEW3D_OT_toggle_matcap_flip(struct wmOperatorType *ot);
/* view3d_ops.c */
void view3d_operatortypes(void);
@@ -132,7 +133,10 @@ void VIEW3D_OT_walk(struct wmOperatorType *ot);
void VIEW3D_OT_ruler(struct wmOperatorType *ot);
/* drawobject.c */
-void draw_object_backbufsel(struct Depsgraph *depsgraph, Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob);
+void draw_object_backbufsel(
+ struct Depsgraph *depsgraph, Scene *scene,
+ View3D *v3d, RegionView3D *rv3d, struct Object *ob,
+ short select_mode);
int view3d_effective_drawtype(const struct View3D *v3d);
@@ -182,6 +186,7 @@ typedef struct V3D_SmoothParams {
} 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);
@@ -229,7 +234,6 @@ struct Object *ED_view3d_cameracontrol_object_get(
/* view3d_toolbar.c */
void VIEW3D_OT_toolshelf(struct wmOperatorType *ot);
-void view3d_toolshelf_register(struct ARegionType *art);
/* view3d_snap.c */
bool ED_view3d_minmax_verts(struct Object *obedit, float min[3], float max[3]);
diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c
index 35127c7c8c6..eae0cf8e459 100644
--- a/source/blender/editors/space_view3d/view3d_iterators.c
+++ b/source/blender/editors/space_view3d/view3d_iterators.c
@@ -35,14 +35,17 @@
#include "BLI_utildefines.h"
#include "BLI_rect.h"
+#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_curve.h"
#include "BKE_DerivedMesh.h"
#include "BKE_displist.h"
#include "BKE_editmesh.h"
#include "BKE_context.h"
+#include "BKE_mesh_runtime.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "bmesh.h"
@@ -449,19 +452,21 @@ void pose_foreachScreenBone(
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)
{
- bArmature *arm = vc->obact->data;
+ 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, pchan->bone)) {
+ 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->pose_head, screen_co_a, clip_flag) == V3D_PROJ_RET_OK) {
+ 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 {
@@ -470,7 +475,7 @@ void pose_foreachScreenBone(
}
/* project tail location to screenspace */
- if (ED_view3d_project_float_object(vc->ar, pchan->pose_tail, screen_co_b, clip_flag) == V3D_PROJ_RET_OK) {
+ 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 {
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_armature.c b/source/blender/editors/space_view3d/view3d_manipulator_armature.c
index 5d3d88ff2a2..abbd6c888b2 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_armature.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_armature.c
@@ -134,7 +134,10 @@ static bool WIDGETGROUP_armature_spline_poll(const bContext *C, wmManipulatorGro
const bArmature *arm = ob->data;
if (arm->drawtype == ARM_B_BONE) {
if (arm->act_bone && arm->act_bone->segments > 1) {
- return true;
+ View3D *v3d = CTX_wm_view3d(C);
+ if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
+ return true;
+ }
}
}
}
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_camera.c b/source/blender/editors/space_view3d/view3d_manipulator_camera.c
index 87e550ba638..023e16c070e 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_camera.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_camera.c
@@ -47,8 +47,6 @@
#include "WM_types.h"
#include "WM_message.h"
-#include "DEG_depsgraph_query.h"
-
#include "view3d_intern.h" /* own include */
@@ -65,6 +63,11 @@ struct CameraWidgetGroup {
static bool WIDGETGROUP_camera_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
{
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
+ return false;
+ }
+
Object *ob = CTX_data_active_object(C);
if (ob && ob->type == OB_CAMERA) {
Camera *camera = ob->data;
@@ -78,9 +81,7 @@ static bool WIDGETGROUP_camera_poll(const bContext *C, wmManipulatorGroupType *U
static void WIDGETGROUP_camera_setup(const bContext *C, wmManipulatorGroup *mgroup)
{
- const Depsgraph *depsgraph = CTX_data_depsgraph(C);
Object *ob = CTX_data_active_object(C);
- const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
float dir[3];
const wmManipulatorType *wt_arrow = WM_manipulatortype_find("MANIPULATOR_WT_arrow_3d", true);
@@ -88,7 +89,7 @@ static void WIDGETGROUP_camera_setup(const bContext *C, wmManipulatorGroup *mgro
struct CameraWidgetGroup *camgroup = MEM_callocN(sizeof(struct CameraWidgetGroup), __func__);
mgroup->customdata = camgroup;
- negate_v3_v3(dir, ob_eval->obmat[2]);
+ negate_v3_v3(dir, ob->obmat[2]);
/* dof distance */
{
@@ -108,7 +109,7 @@ static void WIDGETGROUP_camera_setup(const bContext *C, wmManipulatorGroup *mgro
mpr = camgroup->focal_len = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL);
mpr->flag |= WM_MANIPULATOR_DRAW_NO_SCALE;
RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_CONE);
- RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED);
+ RNA_enum_set(mpr->ptr, "transform", ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED);
UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color);
UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi);
@@ -116,7 +117,7 @@ static void WIDGETGROUP_camera_setup(const bContext *C, wmManipulatorGroup *mgro
mpr = camgroup->ortho_scale = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL);
mpr->flag |= WM_MANIPULATOR_DRAW_NO_SCALE;
RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_CONE);
- RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED);
+ RNA_enum_set(mpr->ptr, "transform", ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED);
UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color);
UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi);
@@ -128,28 +129,26 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmManipulatorGroup *mg
if (!mgroup->customdata)
return;
- const Depsgraph *depsgraph = CTX_data_depsgraph(C);
struct CameraWidgetGroup *camgroup = mgroup->customdata;
Object *ob = CTX_data_active_object(C);
- const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
Camera *ca = ob->data;
PointerRNA camera_ptr;
float dir[3];
const float ob_scale_inv[3] = {
- 1.0f / len_v3(ob_eval->obmat[0]),
- 1.0f / len_v3(ob_eval->obmat[1]),
- 1.0f / len_v3(ob_eval->obmat[2]),
+ 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;
RNA_pointer_create(&ca->id, &RNA_Camera, ca, &camera_ptr);
- negate_v3_v3(dir, ob_eval->obmat[2]);
+ negate_v3_v3(dir, ob->obmat[2]);
if (ca->flag & CAM_SHOWLIMITS) {
- WM_manipulator_set_matrix_location(camgroup->dop_dist, ob_eval->obmat[3]);
- WM_manipulator_set_matrix_rotation_from_yz_axis(camgroup->dop_dist, ob_eval->obmat[1], dir);
+ WM_manipulator_set_matrix_location(camgroup->dop_dist, ob->obmat[3]);
+ WM_manipulator_set_matrix_rotation_from_yz_axis(camgroup->dop_dist, ob->obmat[1], dir);
WM_manipulator_set_scale(camgroup->dop_dist, ca->drawsize);
WM_manipulator_set_flag(camgroup->dop_dist, WM_MANIPULATOR_HIDDEN, false);
@@ -186,8 +185,8 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmManipulatorGroup *mg
aspect[1] = (sensor_fit == CAMERA_SENSOR_FIT_HOR) ? aspy / aspx : 1.0f;
unit_m4(widget->matrix_basis);
- WM_manipulator_set_matrix_location(widget, ob_eval->obmat[3]);
- WM_manipulator_set_matrix_rotation_from_yz_axis(widget, ob_eval->obmat[1], dir);
+ WM_manipulator_set_matrix_location(widget, ob->obmat[3]);
+ WM_manipulator_set_matrix_rotation_from_yz_axis(widget, ob->obmat[1], dir);
if (is_ortho) {
scale_matrix = ca->ortho_scale * 0.5f;
@@ -252,6 +251,7 @@ static void WIDGETGROUP_camera_message_subscribe(
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_draw_size,
@@ -261,6 +261,7 @@ static void WIDGETGROUP_camera_message_subscribe(
&rna_Camera_shift_x,
&rna_Camera_shift_y,
&rna_Camera_type,
+ &rna_Camera_lens,
};
PointerRNA idptr;
@@ -356,9 +357,13 @@ static bool WIDGETGROUP_camera_view_poll(const bContext *C, wmManipulatorGroupTy
}
}
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
+ return false;
+ }
+
ARegion *ar = CTX_wm_region(C);
RegionView3D *rv3d = ar->regiondata;
- View3D *v3d = CTX_wm_view3d(C);
if (rv3d->persp == RV3D_CAMOB) {
if (scene->r.mode & R_BORDER) {
/* TODO: support overrides. */
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_empty.c b/source/blender/editors/space_view3d/view3d_manipulator_empty.c
index 1d56c5ee7f4..75e4a9e3314 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_empty.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_empty.c
@@ -106,6 +106,11 @@ static void manipulator_empty_image_prop_matrix_set(
static bool WIDGETGROUP_empty_image_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
{
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
+ return false;
+ }
+
Object *ob = CTX_data_active_object(C);
if (ob && ob->type == OB_EMPTY) {
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c b/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c
index e76be448be4..b42f49e6d1c 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c
@@ -54,6 +54,11 @@
static bool WIDGETGROUP_forcefield_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
{
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
+ return false;
+ }
+
Object *ob = CTX_data_active_object(C);
return (ob && ob->pd && ob->pd->forcefield);
@@ -67,7 +72,7 @@ static void WIDGETGROUP_forcefield_setup(const bContext *UNUSED(C), wmManipulato
wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_arrow_3d", mgroup, NULL);
wmManipulator *mpr = wwrapper->manipulator;
- RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED);
+ RNA_enum_set(mpr->ptr, "transform", ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED);
ED_manipulator_arrow3d_set_ui_range(mpr, -200.0f, 200.0f);
ED_manipulator_arrow3d_set_range_fac(mpr, 6.0f);
@@ -115,4 +120,3 @@ void VIEW3D_WGT_force_field(wmManipulatorGroupType *wgt)
}
/** \} */
-
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_lamp.c b/source/blender/editors/space_view3d/view3d_manipulator_lamp.c
index 93b6b69a105..f98a2f336bc 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_lamp.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_lamp.c
@@ -54,6 +54,11 @@
static bool WIDGETGROUP_lamp_spot_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
{
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
+ return false;
+ }
+
Object *ob = CTX_data_active_object(C);
if (ob && ob->type == OB_LAMP) {
@@ -69,7 +74,7 @@ static void WIDGETGROUP_lamp_spot_setup(const bContext *UNUSED(C), wmManipulator
wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_arrow_3d", mgroup, NULL);
wmManipulator *mpr = wwrapper->manipulator;
- RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_INVERTED);
+ RNA_enum_set(mpr->ptr, "transform", ED_MANIPULATOR_ARROW_XFORM_FLAG_INVERTED);
mgroup->customdata = wwrapper;
@@ -129,7 +134,7 @@ static void manipulator_area_lamp_prop_matrix_get(
const Lamp *la = mpr_prop->custom_func.user_data;
matrix[0][0] = la->area_size;
- matrix[1][1] = (la->area_shape == LA_AREA_RECT) ? la->area_sizey : la->area_size;
+ matrix[1][1] = ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE) ? la->area_sizey : la->area_size;
}
static void manipulator_area_lamp_prop_matrix_set(
@@ -140,7 +145,7 @@ static void manipulator_area_lamp_prop_matrix_set(
BLI_assert(mpr_prop->type->array_length == 16);
Lamp *la = mpr_prop->custom_func.user_data;
- if (la->area_shape == LA_AREA_RECT) {
+ 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]);
}
@@ -151,8 +156,12 @@ static void manipulator_area_lamp_prop_matrix_set(
static bool WIDGETGROUP_lamp_area_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
{
- Object *ob = CTX_data_active_object(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
+ return false;
+ }
+ Object *ob = CTX_data_active_object(C);
if (ob && ob->type == OB_LAMP) {
Lamp *la = ob->data;
return (la->type == LA_AREA);
@@ -185,9 +194,11 @@ static void WIDGETGROUP_lamp_area_refresh(const bContext *C, wmManipulatorGroup
copy_m4_m4(mpr->matrix_basis, ob->obmat);
- RNA_enum_set(mpr->ptr, "transform",
- ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE |
- ((la->area_shape == LA_AREA_SQUARE) ? ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM : 0));
+ int flag = ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE;
+ if (ELEM(la->area_shape, LA_AREA_SQUARE, LA_AREA_DISK)) {
+ flag |= ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM;
+ }
+ RNA_enum_set(mpr->ptr, "transform", flag);
/* need to set property here for undo. TODO would prefer to do this in _init */
WM_manipulator_target_property_def_func(
@@ -224,6 +235,11 @@ void VIEW3D_WGT_lamp_area(wmManipulatorGroupType *wgt)
static bool WIDGETGROUP_lamp_target_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
{
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
+ return false;
+ }
+
Object *ob = CTX_data_active_object(C);
if (ob != NULL) {
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_navigate.c b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
index 2d3f42f9c61..22b7af48de6 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
@@ -51,13 +51,13 @@
* \{ */
/* Offset from screen edge. */
-#define MANIPULATOR_OFFSET_FAC 2.5
+#define MANIPULATOR_OFFSET_FAC 1.5f
/* Size of main icon. */
#define MANIPULATOR_SIZE 64
/* Factor for size of smaller button. */
-#define MANIPULATOR_MINI_FAC 0.5
+#define MANIPULATOR_MINI_FAC 0.35f
/* How much mini buttons offset from the primary. */
-#define MANIPULATOR_MINI_OFFSET_FAC 0.6666f
+#define MANIPULATOR_MINI_OFFSET_FAC 0.42f
enum {
@@ -166,20 +166,23 @@ struct NavigateWidgetGroup {
wmManipulator *mpr_array[MPR_TOTAL];
/* Store the view state to check for changes. */
struct {
- struct {
- short winx, winy;
- } ar;
+ rcti rect_visible;
struct {
char is_persp;
+ char is_camera;
char viewlock;
} rv3d;
} state;
int region_size[2];
- bool is_persp;
};
-static bool WIDGETGROUP_navigate_poll(const bContext *UNUSED(C), wmManipulatorGroupType *UNUSED(wgt))
+static bool WIDGETGROUP_navigate_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
{
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
+ return false;
+ }
+
if (U.manipulator_flag & USER_MANIPULATOR_DRAW_NAVIGATE) {
return true;
}
@@ -211,6 +214,7 @@ static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmManipulatorG
RNA_property_string_set_bytes(
mpr->ptr, prop,
(const char *)info->shape, info->shape_size);
+ RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_BUTTON_SHOW_OUTLINE);
}
wmOperatorType *ot = WM_operatortype_find(info->opname, true);
@@ -276,25 +280,38 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmManipulatorGr
copy_v3_v3(navgroup->mpr_array[MPR_ROTATE]->matrix_offset[i], rv3d->viewmat[i]);
}
- if ((navgroup->state.ar.winx == ar->winx) &&
- (navgroup->state.ar.winy == ar->winy) &&
+ 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.ar.winx = ar->winx;
- navgroup->state.ar.winy = ar->winy;
+ 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 = MANIPULATOR_SIZE;
- const float icon_offset = (icon_size / 2.0) * MANIPULATOR_OFFSET_FAC * UI_DPI_FAC;
+ const float icon_offset = (icon_size * 0.52f) * MANIPULATOR_OFFSET_FAC * UI_DPI_FAC;
const float icon_offset_mini = icon_size * MANIPULATOR_MINI_OFFSET_FAC * UI_DPI_FAC;
- const float co[2] = {ar->winx - icon_offset, ar->winy - icon_offset};
+ 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,
+ };
wmManipulator *mpr;
@@ -303,43 +320,38 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmManipulatorGr
WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true);
}
- if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
+ /* RV3D_LOCKED or Camera: only show supported buttons. */
+ if (show_rotate) {
mpr = navgroup->mpr_array[MPR_ROTATE];
- mpr->matrix_basis[3][0] = co[0];
- mpr->matrix_basis[3][1] = co[1];
+ mpr->matrix_basis[3][0] = co_rotate[0];
+ mpr->matrix_basis[3][1] = co_rotate[1];
WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+ }
- mpr = navgroup->mpr_array[MPR_MOVE];
- mpr->matrix_basis[3][0] = co[0] + icon_offset_mini;
- mpr->matrix_basis[3][1] = co[1] - icon_offset_mini;
- WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+ int icon_mini_slot = 0;
- mpr = navgroup->mpr_array[MPR_ZOOM];
- mpr->matrix_basis[3][0] = co[0] - icon_offset_mini;
- mpr->matrix_basis[3][1] = co[1] - icon_offset_mini;
- WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+ mpr = navgroup->mpr_array[MPR_ZOOM];
+ mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
+ mpr->matrix_basis[3][1] = co[1];
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
- mpr = navgroup->mpr_array[rv3d->is_persp ? MPR_ORTHO : MPR_PERSP];
- mpr->matrix_basis[3][0] = co[0] + icon_offset_mini;
- mpr->matrix_basis[3][1] = co[1] + icon_offset_mini;
- WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+ mpr = navgroup->mpr_array[MPR_MOVE];
+ mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
+ mpr->matrix_basis[3][1] = co[1];
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+ if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
mpr = navgroup->mpr_array[MPR_CAMERA];
- mpr->matrix_basis[3][0] = co[0] - icon_offset_mini;
- mpr->matrix_basis[3][1] = co[1] + icon_offset_mini;
- WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
- }
- else {
- /* RV3D_LOCKED: only show supported buttons. */
- mpr = navgroup->mpr_array[MPR_MOVE];
- mpr->matrix_basis[3][0] = co[0] + icon_offset_mini;
- mpr->matrix_basis[3][1] = co[1] + icon_offset_mini;
+ mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
+ mpr->matrix_basis[3][1] = co[1];
WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
- mpr = navgroup->mpr_array[MPR_ZOOM];
- mpr->matrix_basis[3][0] = co[0];
- mpr->matrix_basis[3][1] = co[1] + icon_offset_mini;
- WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+ if (navgroup->state.rv3d.is_camera == false) {
+ mpr = navgroup->mpr_array[rv3d->is_persp ? MPR_PERSP : MPR_ORTHO];
+ mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
+ mpr->matrix_basis[3][1] = co[1];
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+ }
}
}
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c b/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c
index b232be35462..996da2a1475 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c
@@ -43,6 +43,7 @@
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -64,7 +65,7 @@
static void axis_geom_draw(
const wmManipulator *mpr, const float color[4], const bool UNUSED(select))
{
- glLineWidth(mpr->line_width);
+ GPU_line_width(mpr->line_width);
Gwn_VertFormat *format = immVertexFormat();
const uint pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
@@ -128,15 +129,15 @@ static void axis_geom_draw(
zero_v3(center);
copy_v3_fl(size, HANDLE_SIZE);
- glEnable(GL_DEPTH_TEST);
+ GPU_depth_test(true);
glDepthMask(GL_TRUE);
glDepthFunc(GL_LEQUAL);
- glBlendFunc(GL_ONE, GL_ZERO);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_blend_set_func(GPU_ONE, GPU_ZERO);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
- glLineWidth(1.0f);
+ GPU_line_smooth(true);
+ GPU_blend(true);
+ GPU_line_width(1.0f);
/* Just draw depth values. */
immUniformColor4fv(axis_nop);
imm_draw_cube_fill_3d(pos_id, center, size);
@@ -150,9 +151,9 @@ static void axis_geom_draw(
},
0.08f);
imm_draw_cube_wire_3d(pos_id, center, size);
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_DEPTH_TEST);
+ GPU_blend(false);
+ GPU_line_smooth(false);
+ GPU_depth_test(false);
}
draw_center_done = true;
@@ -216,9 +217,9 @@ static void axis3d_draw_intern(
gpuPushMatrix();
gpuMultMatrix(matrix_final);
- glEnable(GL_BLEND);
+ GPU_blend(true);
axis_geom_draw(mpr, color, select);
- glDisable(GL_BLEND);
+ GPU_blend(false);
gpuPopMatrix();
}
@@ -229,9 +230,9 @@ static void manipulator_axis_draw(const bContext *C, wmManipulator *mpr)
(void)is_modal;
- glEnable(GL_BLEND);
+ GPU_blend(true);
axis3d_draw_intern(C, mpr, false, is_highlight);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
static int manipulator_axis_test_select(
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
index eedc346db1d..4a9f07c34e8 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
@@ -31,8 +31,10 @@
#include "BLT_translation.h"
#include "BKE_context.h"
-#include "BKE_object.h"
#include "BKE_gpencil.h"
+#include "BKE_main.h"
+
+#include "BKE_object.h"
#include "BKE_unit.h"
#include "DNA_object_types.h"
@@ -54,12 +56,14 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_toolsystem.h"
#include "view3d_intern.h" /* own include */
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_select.h"
+#include "GPU_state.h"
#include "BLF_api.h"
@@ -262,6 +266,7 @@ 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;
}
@@ -277,7 +282,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state)
}
else if (state == RULER_STATE_DRAG) {
ruler_info->snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), CTX_data_scene(C), CTX_data_depsgraph(C), 0,
+ bmain, CTX_data_scene(C), CTX_data_depsgraph(C), 0,
ruler_info->ar, CTX_wm_view3d(C));
}
else {
@@ -320,14 +325,14 @@ static bool view3d_ruler_item_mousemove(
co_other = ruler_item->co[inter->co_index == 0 ? 2 : 0];
- if (ED_transform_snap_object_project_view3d_mixed(
+ if (ED_transform_snap_object_project_view3d(
ruler_info->snap_context,
- SCE_SELECT_FACE,
+ SCE_SNAP_MODE_FACE,
&(const struct SnapObjectParams){
.snap_select = SNAP_ALL,
.use_object_edit_cage = true,
},
- mval_fl, &dist_px, true,
+ mval_fl, &dist_px,
co, ray_normal))
{
negate_v3(ray_normal);
@@ -344,19 +349,17 @@ static bool view3d_ruler_item_mousemove(
}
}
else if (do_snap) {
- // Scene *scene = CTX_data_scene(C);
- View3D *v3d = ruler_info->sa->spacedata.first;
const float mval_fl[2] = {UNPACK2(mval)};
- bool use_depth = (v3d->drawtype >= OB_SOLID);
- if (ED_transform_snap_object_project_view3d_mixed(
+ if (ED_transform_snap_object_project_view3d(
ruler_info->snap_context,
- (SCE_SELECT_VERTEX | SCE_SELECT_EDGE) | (use_depth ? SCE_SELECT_FACE : 0),
+ (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, use_depth,
+ mval_fl, &dist_px,
co, NULL))
{
ruler_info->snap_flag |= RULER_SNAP_OK;
@@ -380,6 +383,7 @@ static bool view3d_ruler_item_mousemove(
static bool view3d_ruler_to_gpencil(bContext *C, wmManipulatorGroup *mgroup)
{
// RulerInfo *ruler_info = mgroup->customdata;
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
bGPDlayer *gpl;
bGPDframe *gpf;
@@ -391,7 +395,7 @@ static bool view3d_ruler_to_gpencil(bContext *C, wmManipulatorGroup *mgroup)
bool changed = false;
if (scene->gpd == NULL) {
- scene->gpd = BKE_gpencil_data_addnew("GPencil");
+ scene->gpd = BKE_gpencil_data_addnew(bmain, "GPencil");
}
gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info));
@@ -523,7 +527,7 @@ static void manipulator_ruler_draw(const bContext *C, wmManipulator *mpr)
float color_back[4] = {1.0f, 1.0f, 1.0f, 0.5f};
/* anti-aliased lines for more consistent appearance */
- glEnable(GL_LINE_SMOOTH);
+ GPU_line_smooth(true);
BLF_enable(blf_mono_font, BLF_ROTATION);
BLF_size(blf_mono_font, 14 * U.pixelsize, U.dpi);
@@ -542,7 +546,7 @@ static void manipulator_ruler_draw(const bContext *C, wmManipulator *mpr)
ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP);
}
- glEnable(GL_BLEND);
+ GPU_blend(true);
const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -550,7 +554,7 @@ static void manipulator_ruler_draw(const bContext *C, wmManipulator *mpr)
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
immUniform1i("num_colors", 2); /* "advanced" mode */
@@ -629,7 +633,7 @@ static void manipulator_ruler_draw(const bContext *C, wmManipulator *mpr)
rot_90_vec_b[1] = dir_ruler[0];
normalize_v2(rot_90_vec_b);
- glEnable(GL_BLEND);
+ GPU_blend(true);
immUniformColor3ubv(color_wire);
@@ -653,7 +657,7 @@ static void manipulator_ruler_draw(const bContext *C, wmManipulator *mpr)
immEnd();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
immUnbindProgram();
@@ -690,7 +694,7 @@ static void manipulator_ruler_draw(const bContext *C, wmManipulator *mpr)
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
immUniform1i("num_colors", 2); /* "advanced" mode */
@@ -718,7 +722,7 @@ static void manipulator_ruler_draw(const bContext *C, wmManipulator *mpr)
normalize_v2(rot_90_vec);
- glEnable(GL_BLEND);
+ GPU_blend(true);
immUniformColor3ubv(color_wire);
@@ -736,7 +740,7 @@ static void manipulator_ruler_draw(const bContext *C, wmManipulator *mpr)
immEnd();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
immUnbindProgram();
@@ -772,7 +776,7 @@ static void manipulator_ruler_draw(const bContext *C, wmManipulator *mpr)
}
}
- glDisable(GL_LINE_SMOOTH);
+ GPU_line_smooth(false);
BLF_disable(blf_mono_font, BLF_ROTATION);
@@ -980,8 +984,10 @@ void VIEW3D_WT_ruler_item(wmManipulatorType *wt)
static bool WIDGETGROUP_ruler_poll(const bContext *C, wmManipulatorGroupType *wgt)
{
- WorkSpace *workspace = CTX_wm_workspace(C);
- if (!STREQ(wgt->idname, workspace->tool.manipulator_group)) {
+ bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C);
+ if ((tref_rt == NULL) ||
+ !STREQ(wgt->idname, tref_rt->manipulator_group))
+ {
WM_manipulator_group_type_unlink_delayed_ptr(wgt);
return false;
}
@@ -1028,8 +1034,9 @@ void VIEW3D_WGT_ruler(wmManipulatorGroupType *wgt)
static int view3d_ruler_poll(bContext *C)
{
- WorkSpace *workspace = CTX_wm_workspace(C);
- if (!STREQ(view3d_wgt_ruler_id, workspace->tool.manipulator_group) ||
+ bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C);
+ if ((tref_rt == NULL) ||
+ !STREQ(view3d_wgt_ruler_id, tref_rt->manipulator_group) ||
CTX_wm_region_view3d(C) == NULL)
{
return false;
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index d986e8ff6ee..b16327d2a4a 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -45,8 +45,8 @@
#include "BKE_appdir.h"
#include "BKE_blender_copybuffer.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_group.h"
#include "BKE_main.h"
#include "BKE_report.h"
@@ -71,9 +71,9 @@ static int view3d_copybuffer_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
char str[FILE_MAX];
-
+
BKE_copybuffer_begin(bmain);
-
+
/* context, selection, could be generalized */
CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
{
@@ -81,22 +81,22 @@ static int view3d_copybuffer_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- for (Group *group = bmain->group.first; group; group = group->id.next) {
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
- {
+ for (Collection *collection = bmain->collection.first; collection; collection = collection->id.next) {
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ Object *object = cob->ob;
+
if (object && (object->id.tag & LIB_TAG_DOIT)) {
- BKE_copybuffer_tag_ID(&group->id);
+ BKE_copybuffer_tag_ID(&collection->id);
/* don't expand out to all other objects */
- group->id.tag &= ~LIB_TAG_NEED_EXPAND;
+ collection->id.tag &= ~LIB_TAG_NEED_EXPAND;
break;
}
}
- FOREACH_GROUP_OBJECT_END;
}
-
+
BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
BKE_copybuffer_save(bmain, str, op->reports);
-
+
BKE_report(op->reports, RPT_INFO, "Copied selected objects to buffer");
return OPERATOR_FINISHED;
@@ -104,15 +104,15 @@ static int view3d_copybuffer_exec(bContext *C, wmOperator *op)
static void VIEW3D_OT_copybuffer(wmOperatorType *ot)
{
-
+
/* identifiers */
ot->name = "Copy Selection to Buffer";
ot->idname = "VIEW3D_OT_copybuffer";
ot->description = "Selected objects are saved in a temp file";
-
+
/* api callbacks */
ot->exec = view3d_copybuffer_exec;
- ot->poll = ED_operator_view3d_active;
+ ot->poll = ED_operator_scene;
}
static int view3d_pastebuffer_exec(bContext *C, wmOperator *op)
@@ -141,16 +141,16 @@ static int view3d_pastebuffer_exec(bContext *C, wmOperator *op)
static void VIEW3D_OT_pastebuffer(wmOperatorType *ot)
{
-
+
/* identifiers */
ot->name = "Paste Selection from Buffer";
ot->idname = "VIEW3D_OT_pastebuffer";
ot->description = "Contents of copy buffer gets pasted";
-
+
/* api callbacks */
ot->exec = view3d_pastebuffer_exec;
- ot->poll = ED_operator_view3d_active;
-
+ ot->poll = ED_operator_scene_editable;
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -209,10 +209,10 @@ void view3d_operatortypes(void)
WM_operatortype_append(VIEW3D_OT_layers);
WM_operatortype_append(VIEW3D_OT_copybuffer);
WM_operatortype_append(VIEW3D_OT_pastebuffer);
-
+
WM_operatortype_append(VIEW3D_OT_properties);
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);
@@ -222,6 +222,8 @@ void view3d_operatortypes(void)
WM_operatortype_append(VIEW3D_OT_snap_cursor_to_active);
WM_operatortype_append(VIEW3D_OT_toggle_render);
+ WM_operatortype_append(VIEW3D_OT_toggle_xray_draw_option);
+ WM_operatortype_append(VIEW3D_OT_toggle_matcap_flip);
WM_operatortype_append(VIEW3D_OT_ruler_add);
@@ -232,17 +234,17 @@ void view3d_keymap(wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
wmKeyMapItem *kmi;
-
+
keymap = WM_keymap_find(keyconf, "3D View Generic", SPACE_VIEW3D, 0);
WM_keymap_add_item(keymap, "VIEW3D_OT_properties", NKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "VIEW3D_OT_toolshelf", TKEY, KM_PRESS, 0, 0);
-
+
/* only for region 3D window */
keymap = WM_keymap_find(keyconf, "3D View", SPACE_VIEW3D, 0);
WM_keymap_verify_item(keymap, "VIEW3D_OT_cursor3d", ACTIONMOUSE, KM_CLICK, 0, 0);
-
+
WM_keymap_verify_item(keymap, "VIEW3D_OT_rotate", MIDDLEMOUSE, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "VIEW3D_OT_move", MIDDLEMOUSE, KM_PRESS, KM_SHIFT, 0);
WM_keymap_verify_item(keymap, "VIEW3D_OT_zoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0);
@@ -252,26 +254,28 @@ void view3d_keymap(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "use_all_regions", false);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_verify_item(keymap, "VIEW3D_OT_view_lock_to_active", PADPERIOD, KM_PRESS, KM_SHIFT, 0);
WM_keymap_verify_item(keymap, "VIEW3D_OT_view_lock_clear", PADPERIOD, KM_PRESS, KM_ALT, 0);
WM_keymap_verify_item(keymap, "VIEW3D_OT_navigate", FKEY, KM_PRESS, KM_SHIFT, 0);
+#endif
WM_keymap_verify_item(keymap, "VIEW3D_OT_smoothview", TIMER1, KM_ANY, KM_ANY, 0);
-
+
WM_keymap_add_item(keymap, "VIEW3D_OT_rotate", MOUSEPAN, 0, 0, 0);
WM_keymap_add_item(keymap, "VIEW3D_OT_rotate", MOUSEROTATE, 0, 0, 0);
WM_keymap_add_item(keymap, "VIEW3D_OT_move", MOUSEPAN, 0, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "VIEW3D_OT_zoom", MOUSEZOOM, 0, 0, 0);
WM_keymap_add_item(keymap, "VIEW3D_OT_zoom", MOUSEPAN, 0, KM_CTRL, 0);
-
+
/*numpad +/-*/
RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_zoom", PADPLUSKEY, KM_PRESS, 0, 0)->ptr, "delta", 1);
RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_zoom", PADMINUS, KM_PRESS, 0, 0)->ptr, "delta", -1);
/*ctrl +/-*/
RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_zoom", EQUALKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", 1);
RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_zoom", MINUSKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", -1);
-
+
/*wheel mouse forward/back*/
RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_zoom", WHEELINMOUSE, KM_PRESS, 0, 0)->ptr, "delta", 1);
RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_zoom", WHEELOUTMOUSE, KM_PRESS, 0, 0)->ptr, "delta", -1);
@@ -284,21 +288,29 @@ void view3d_keymap(wmKeyConfig *keyconf)
RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_dolly", EQUALKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0)->ptr, "delta", 1);
RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_dolly", MINUSKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0)->ptr, "delta", -1);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "VIEW3D_OT_zoom_camera_1_to_1", PADENTER, KM_PRESS, KM_SHIFT, 0);
+#endif
WM_keymap_add_item(keymap, "VIEW3D_OT_view_center_camera", HOMEKEY, KM_PRESS, 0, 0); /* only with camera view */
WM_keymap_add_item(keymap, "VIEW3D_OT_view_center_lock", HOMEKEY, KM_PRESS, 0, 0); /* only with lock view */
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "VIEW3D_OT_view_center_cursor", HOMEKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "VIEW3D_OT_view_center_pick", FKEY, KM_PRESS, KM_ALT, 0);
+#endif
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "center", false); /* only without camera view */
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_view_all", HOMEKEY, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "use_all_regions", true);
RNA_boolean_set(kmi->ptr, "center", false); /* only without camera view */
+#ifdef USE_WM_KEYMAP_27X
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_view_all", CKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "center", true);
+#endif
+
+ WM_keymap_add_menu_pie(keymap, "VIEW3D_MT_view_pie", ACCENTGRAVEKEY, KM_CLICK_DRAG, 0, 0);
/* numpad view hotkeys*/
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD0, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_CAMERA);
@@ -307,7 +319,7 @@ void view3d_keymap(wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD3, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_RIGHT);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", PAD4, KM_PRESS, 0, 0)->ptr, "type", V3D_VIEW_STEPLEFT);
WM_keymap_add_item(keymap, "VIEW3D_OT_view_persportho", PAD5, KM_PRESS, 0, 0);
-
+
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", PAD6, KM_PRESS, 0, 0)->ptr, "type", V3D_VIEW_STEPRIGHT);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD7, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_TOP);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", PAD8, KM_PRESS, 0, 0)->ptr, "type", V3D_VIEW_STEPUP);
@@ -324,6 +336,7 @@ void view3d_keymap(wmKeyConfig *keyconf)
RNA_enum_set(kmi->ptr, "type", V3D_VIEW_STEPRIGHT);
RNA_float_set(kmi->ptr, "angle", (float)M_PI);
+#ifdef USE_WM_KEYMAP_27X
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", WHEELUPMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANRIGHT);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANLEFT);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", WHEELUPMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "type", V3D_VIEW_PANUP);
@@ -333,9 +346,10 @@ void view3d_keymap(wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL | KM_ALT, 0)->ptr, "type", V3D_VIEW_STEPRIGHT);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", WHEELUPMOUSE, KM_PRESS, KM_SHIFT | KM_ALT, 0)->ptr, "type", V3D_VIEW_STEPUP);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT | KM_ALT, 0)->ptr, "type", V3D_VIEW_STEPDOWN);
-
+
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", WHEELUPMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0)->ptr, "type", V3D_VIEW_STEPLEFT);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0)->ptr, "type", V3D_VIEW_STEPRIGHT);
+#endif
/* active aligned, replaces '*' key in 2.4x */
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD1, KM_PRESS, KM_SHIFT, 0);
@@ -356,7 +370,7 @@ void view3d_keymap(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD7, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_BOTTOM);
RNA_boolean_set(kmi->ptr, "align_active", true);
-
+
#ifdef WITH_INPUT_NDOF
/* note: positioned here so keymaps show keyboard keys if assigned */
/* 3D mouse */
@@ -375,7 +389,7 @@ void view3d_keymap(wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_RIGHT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_RIGHT);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_TOP, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_TOP);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BOTTOM, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BOTTOM);
-
+
/* 3D mouse align */
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, KM_SHIFT, 0);
RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_FRONT);
@@ -388,32 +402,17 @@ void view3d_keymap(wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "align_active", true);
#endif /* WITH_INPUT_NDOF */
- /* layers, shift + alt are properties set in invoke() */
- RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", ACCENTGRAVEKEY, KM_PRESS, 0, 0)->ptr, "nr", 0);
- RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", ONEKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 1);
- RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", TWOKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 2);
- RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", THREEKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 3);
- RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", FOURKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 4);
- RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", FIVEKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 5);
- RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", SIXKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 6);
- RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", SEVENKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 7);
- RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", EIGHTKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 8);
- RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", NINEKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 9);
- RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", ZEROKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 10);
-
/* drawtype */
-
- kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle_enum", ZKEY, KM_PRESS, 0, 0);
- RNA_string_set(kmi->ptr, "data_path", "space_data.shading.type");
- RNA_string_set(kmi->ptr, "value_1", "SOLID");
- RNA_string_set(kmi->ptr, "value_2", "WIREFRAME");
-
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle_enum", ZKEY, KM_PRESS, KM_ALT, 0);
RNA_string_set(kmi->ptr, "data_path", "space_data.shading.type");
RNA_string_set(kmi->ptr, "value_1", "SOLID");
RNA_string_set(kmi->ptr, "value_2", "TEXTURED");
WM_keymap_add_item(keymap, "VIEW3D_OT_toggle_render", ZKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_toggle_xray_draw_option", ZKEY, KM_PRESS, 0, 0);
+
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", ZKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "data_path", "space_data.use_occlude_geometry");
/* selection*/
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
@@ -481,7 +480,7 @@ void view3d_keymap(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_SHIFT | KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "deselect", true);
WM_keymap_add_item(keymap, "VIEW3D_OT_select_circle", CKEY, KM_PRESS, 0, 0);
-
+
WM_keymap_add_item(keymap, "VIEW3D_OT_clip_border", BKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "VIEW3D_OT_zoom_border", BKEY, KM_PRESS, KM_SHIFT, 0);
@@ -491,46 +490,47 @@ void view3d_keymap(wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "camera_only", false);
WM_keymap_add_item(keymap, "VIEW3D_OT_clear_render_border", BKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
-
+
WM_keymap_add_item(keymap, "VIEW3D_OT_camera_to_view", PAD0, KM_PRESS, KM_ALT | KM_CTRL, 0);
WM_keymap_add_item(keymap, "VIEW3D_OT_object_as_camera", PAD0, KM_PRESS, KM_CTRL, 0);
-
+
WM_keymap_add_menu(keymap, "VIEW3D_MT_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
-
+
#ifdef __APPLE__
WM_keymap_add_item(keymap, "VIEW3D_OT_copybuffer", CKEY, KM_PRESS, KM_OSKEY, 0);
WM_keymap_add_item(keymap, "VIEW3D_OT_pastebuffer", VKEY, KM_PRESS, KM_OSKEY, 0);
#endif
WM_keymap_add_item(keymap, "VIEW3D_OT_copybuffer", CKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "VIEW3D_OT_pastebuffer", VKEY, KM_PRESS, KM_CTRL, 0);
-
+
/* context ops */
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_PRESS, 0, 0);
- RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.transform_pivot_point");
RNA_string_set(kmi->ptr, "value", "BOUNDING_BOX_CENTER");
- kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_PRESS, KM_CTRL, 0); /* 2.4x allowed Comma+Shift too, rather not use both */
- RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ /* 2.4x allowed Comma+Shift too, rather not use both */
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_PRESS, KM_CTRL, 0);
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.transform_pivot_point");
RNA_string_set(kmi->ptr, "value", "MEDIAN_POINT");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", COMMAKEY, KM_PRESS, KM_ALT, 0); /* new in 2.5 */
- RNA_string_set(kmi->ptr, "data_path", "space_data.use_pivot_point_align");
-
- kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", SPACEKEY, KM_PRESS, KM_CTRL, 0); /* new in 2.5 */
- RNA_string_set(kmi->ptr, "data_path", "space_data.show_manipulator");
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_transform_pivot_point_align");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM_PRESS, 0, 0);
- RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.transform_pivot_point");
RNA_string_set(kmi->ptr, "value", "CURSOR");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM_PRESS, KM_CTRL, 0);
- RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.transform_pivot_point");
RNA_string_set(kmi->ptr, "value", "INDIVIDUAL_ORIGINS");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM_PRESS, KM_ALT, 0);
- RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.transform_pivot_point");
RNA_string_set(kmi->ptr, "value", "ACTIVE_ELEMENT");
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", SPACEKEY, KM_PRESS, KM_CTRL, 0); /* new in 2.5 */
+ RNA_string_set(kmi->ptr, "data_path", "space_data.show_manipulator");
+
transform_keymap_for_space(keyconf, keymap, SPACE_VIEW3D);
fly_modal_keymap(keyconf);
@@ -540,4 +540,3 @@ void view3d_keymap(wmKeyConfig *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 eb86800f4a9..30b91c1a8ee 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -57,13 +57,13 @@
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];
-
+
copy_v3_v3(vec4, co);
vec4[3] = 1.0;
/* r_co[0] = IS_CLIPPED; */ /* always overwritten */
-
+
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];
@@ -79,13 +79,13 @@ void ED_view3d_project_float_v2_m4(const ARegion *ar, const float co[3], float r
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];
-
+
copy_v3_v3(vec4, vec);
vec4[3] = 1.0;
/* r_co[0] = IS_CLIPPED; */ /* always overwritten */
-
+
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];
@@ -282,6 +282,11 @@ 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;
}
+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;
+}
+
/**
* Calculate a depth value from \a co, use with #ED_view3d_win_to_delta
*/
@@ -546,10 +551,10 @@ void ED_view3d_win_to_delta(const ARegion *ar, const float mval[2], float out[3]
{
RegionView3D *rv3d = ar->regiondata;
float dx, dy;
-
+
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);
diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c
index 6706a98ba55..3a86f70febb 100644
--- a/source/blender/editors/space_view3d/view3d_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_ruler.c
@@ -38,13 +38,15 @@
#include "BLT_translation.h"
#include "BKE_context.h"
-#include "BKE_unit.h"
#include "BKE_gpencil.h"
+#include "BKE_main.h"
+#include "BKE_unit.h"
#include "BIF_gl.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
+#include "GPU_state.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -267,6 +269,7 @@ static bool view3d_ruler_pick(RulerInfo *ruler_info, const float mval[2],
*/
static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state)
{
+ Main *bmain = CTX_data_main(C);
if (state == ruler_info->state) {
return;
}
@@ -282,7 +285,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state)
}
else if (state == RULER_STATE_DRAG) {
ruler_info->snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), CTX_data_scene(C), CTX_data_depsgraph(C), 0,
+ bmain, CTX_data_scene(C), CTX_data_depsgraph(C), 0,
ruler_info->ar, CTX_wm_view3d(C));
}
else {
@@ -295,6 +298,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state)
#define RULER_ID "RulerData3D"
static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info)
{
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
bGPDlayer *gpl;
bGPDframe *gpf;
@@ -306,7 +310,7 @@ static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info)
bool changed = false;
if (scene->gpd == NULL) {
- scene->gpd = BKE_gpencil_data_addnew("GPencil");
+ scene->gpd = BKE_gpencil_data_addnew(bmain, "GPencil");
}
gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info));
@@ -326,7 +330,7 @@ static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info)
if (palcolor == NULL) {
palcolor = BKE_gpencil_palettecolor_addnew(palette, (char *)ruler_name, true);
}
-
+
gpf = BKE_gpencil_layer_getframe(gpl, CFRA, true);
BKE_gpencil_free_strokes(gpf);
@@ -435,7 +439,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
float color_back[4] = {1.0f, 1.0f, 1.0f, 0.5f};
/* anti-aliased lines for more consistent appearance */
- glEnable(GL_LINE_SMOOTH);
+ GPU_line_smooth(true);
BLF_enable(blf_mono_font, BLF_ROTATION);
BLF_size(blf_mono_font, 14 * U.pixelsize, U.dpi);
@@ -455,7 +459,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP);
}
- glEnable(GL_BLEND);
+ GPU_blend(true);
const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -463,7 +467,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
immUniform1i("num_colors", 2); /* "advanced" mode */
@@ -542,7 +546,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
rot_90_vec_b[1] = dir_ruler[0];
normalize_v2(rot_90_vec_b);
- glEnable(GL_BLEND);
+ GPU_blend(true);
immUniformColor3ubv(color_wire);
@@ -566,7 +570,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
immEnd();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
immUnbindProgram();
@@ -602,7 +606,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
immUniform1i("num_colors", 2); /* "advanced" mode */
@@ -630,7 +634,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
normalize_v2(rot_90_vec);
- glEnable(GL_BLEND);
+ GPU_blend(true);
immUniformColor3ubv(color_wire);
@@ -648,7 +652,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
immEnd();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
immUnbindProgram();
@@ -684,7 +688,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
}
}
- glDisable(GL_LINE_SMOOTH);
+ GPU_line_smooth(false);
BLF_disable(blf_mono_font, BLF_ROTATION);
@@ -761,14 +765,14 @@ static bool view3d_ruler_item_mousemove(
co_other = ruler_item->co[ruler_item->co_index == 0 ? 2 : 0];
- if (ED_transform_snap_object_project_view3d_mixed(
+ if (ED_transform_snap_object_project_view3d(
ruler_info->snap_context,
- SCE_SELECT_FACE,
+ SCE_SNAP_MODE_FACE,
&(const struct SnapObjectParams){
.snap_select = SNAP_ALL,
.use_object_edit_cage = true,
},
- mval_fl, &dist_px, true,
+ mval_fl, &dist_px,
co, ray_normal))
{
negate_v3(ray_normal);
@@ -785,19 +789,17 @@ static bool view3d_ruler_item_mousemove(
}
}
else if (do_snap) {
- // Scene *scene = CTX_data_scene(C);
- View3D *v3d = ruler_info->sa->spacedata.first;
const float mval_fl[2] = {UNPACK2(mval)};
- bool use_depth = (v3d->drawtype >= OB_SOLID);
- if (ED_transform_snap_object_project_view3d_mixed(
+ if (ED_transform_snap_object_project_view3d(
ruler_info->snap_context,
- (SCE_SELECT_VERTEX | SCE_SELECT_EDGE) | (use_depth ? SCE_SELECT_FACE : 0),
+ (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, use_depth,
+ mval_fl, &dist_px,
co, NULL))
{
ruler_info->snap_flag |= RULER_SNAP_OK;
@@ -810,7 +812,7 @@ static bool view3d_ruler_item_mousemove(
}
}
-static void view3d_ruler_header_update(ScrArea *sa)
+static void view3d_ruler_header_update(bContext *C)
{
const char *text = IFACE_("Ctrl+LMB: Add, "
"Del: Remove, "
@@ -820,7 +822,7 @@ static void view3d_ruler_header_update(ScrArea *sa)
"Enter: Store, "
"Esc: Cancel");
- ED_area_headerprint(sa, text);
+ ED_workspace_status_text(C, text);
}
/* -------------------------------------------------------------------- */
@@ -846,7 +848,7 @@ static int view3d_ruler_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
ruler_info->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ruler_info_draw_pixel,
ruler_info, REGION_DRAW_POST_PIXEL);
- view3d_ruler_header_update(sa);
+ view3d_ruler_header_update(C);
op->flag |= OP_IS_MODAL_CURSOR_REGION;
@@ -1078,7 +1080,7 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
if (do_draw) {
- view3d_ruler_header_update(sa);
+ view3d_ruler_header_update(C);
/* all 3d views draw rulers */
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
@@ -1092,7 +1094,7 @@ exit:
view3d_ruler_free(ruler_info);
op->customdata = NULL;
- ED_area_headerprint(sa, NULL);
+ ED_workspace_status_text(C, NULL);
}
return exit_code;
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 555bb0e70de..02a70d91277 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -116,6 +116,7 @@ void ED_view3d_viewcontext_init(bContext *C, ViewContext *vc)
{
memset(vc, 0, sizeof(ViewContext));
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);
@@ -299,25 +300,25 @@ static bool edge_fully_inside_rect(const rctf *rect, const float v1[2], const fl
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;
}
@@ -373,7 +374,7 @@ static void do_lasso_select_pose(ViewContext *vc, Object *ob, const int mcords[]
ViewContext vc_tmp;
LassoSelectUserData data;
rcti rect;
-
+
if ((ob->type != OB_ARMATURE) || (ob->pose == NULL)) {
return;
}
@@ -395,6 +396,8 @@ static void do_lasso_select_pose(ViewContext *vc, Object *ob, const int mcords[]
/* mask modifier ('armature' mode), etc. */
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
+ /* bone selection status is on armature not object */
+ DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
}
}
@@ -415,22 +418,22 @@ static void do_lasso_select_objects(
{
bool is_pose_mode = vc->obact ? (vc->obact->mode & OB_MODE_POSE) : false;
Base *base;
-
+
if (extend == false && select)
object_deselect_all_visible(vc->view_layer);
for (base = vc->view_layer->object_bases.first; base; base = base->next) {
if (BASE_SELECTABLE(base)) { /* use this to avoid un-needed lasso lookups */
- if (ED_view3d_project_base(vc->ar, base) == V3D_PROJ_RET_OK) {
+ if (((vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ?
+ (is_pose_mode == false) : true) &&
+ ED_view3d_project_base(vc->ar, base) == V3D_PROJ_RET_OK)
+ {
if (BLI_lasso_is_point_inside(mcords, moves, base->sx, base->sy, IS_CLIPPED)) {
ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
}
}
- if (is_pose_mode &&
- ((vc->obact == base->object) || (base->flag & BASE_SELECTED)) &&
- (base->object->mode & OB_MODE_POSE))
- {
+ if (is_pose_mode && (base->object->mode & OB_MODE_POSE)) {
do_lasso_select_pose(vc, base->object, mcords, moves, select);
}
}
@@ -493,7 +496,7 @@ static void do_lasso_select_mesh(
ToolSettings *ts = vc->scene->toolsettings;
rcti rect;
int bbsel;
-
+
/* set editmesh */
vc->em = BKE_editmesh_from_object(vc->obedit);
@@ -509,7 +512,7 @@ static void do_lasso_select_mesh(
gpuLoadMatrix(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) {
edbm_backbuf_check_and_select_verts(vc->em, select);
@@ -528,7 +531,7 @@ static void do_lasso_select_mesh(
mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
}
}
-
+
if (ts->selectmode & SCE_SELECT_FACE) {
if (bbsel) {
edbm_backbuf_check_and_select_faces(vc->em, select);
@@ -537,7 +540,7 @@ static void do_lasso_select_mesh(
mesh_foreachScreenFace(vc, do_lasso_select_mesh__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
}
}
-
+
EDBM_backbuf_free();
EDBM_selectmode_flush(vc->em);
}
@@ -789,7 +792,7 @@ static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], sh
BLI_lasso_boundbox(&rect, mcords, moves);
EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
-
+
edbm_backbuf_check_and_select_tfaces(me, select);
EDBM_backbuf_free();
@@ -801,19 +804,19 @@ static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], sh
static void do_lasso_select_node(int mcords[][2], short moves, const bool select)
{
SpaceNode *snode = sa->spacedata.first;
-
+
bNode *node;
rcti rect;
int node_cent[2];
float node_centf[2];
-
+
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);
if (BLI_rcti_isect_pt_v(&rect, node_cent) && BLI_lasso_is_point_inside(mcords, moves, node_cent[0], node_cent[1])) {
if (select) {
@@ -850,6 +853,7 @@ static void view3d_lasso_select(
}
else {
do_lasso_select_objects(vc, mcords, moves, extend, select);
+ DEG_id_tag_update(&vc->scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene);
}
}
@@ -880,6 +884,7 @@ static void view3d_lasso_select(
break;
}
+ DEG_id_tag_update(vc->obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc->obedit->data);
}
FOREACH_OBJECT_IN_MODE_END;
@@ -894,18 +899,18 @@ 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);
-
+
if (mcords) {
bool extend, select;
view3d_operator_needs_opengl(C);
-
+
/* setup view context for argument to callbacks */
ED_view3d_viewcontext_init(C, &vc);
-
+
extend = RNA_boolean_get(op->ptr, "extend");
select = !RNA_boolean_get(op->ptr, "deselect");
view3d_lasso_select(C, &vc, mcords, mcords_tot, extend, select);
-
+
MEM_freeN((void *)mcords);
return OPERATOR_FINISHED;
@@ -918,16 +923,16 @@ 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->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;
-
+
/* properties */
WM_operator_properties_gesture_lasso_select(ot);
}
@@ -1004,7 +1009,9 @@ static int object_select_menu_exec(bContext *C, wmOperator *op)
/* undo? */
if (changed) {
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
return OPERATOR_FINISHED;
}
else {
@@ -1165,7 +1172,7 @@ static int selectbuffer_ret_hits_5(unsigned int *buffer, const int hits15, const
/* so check three selection levels and compare */
static int mixed_bones_object_selectbuffer(
ViewContext *vc, unsigned int *buffer, const int mval[2],
- bool use_cycle, bool enumerate,
+ bool use_cycle, bool enumerate, eV3DSelectObjectFilter select_filter,
bool *r_do_nearest)
{
rcti rect;
@@ -1204,7 +1211,7 @@ static int mixed_bones_object_selectbuffer(
view3d_opengl_select_cache_begin();
BLI_rcti_init_pt_radius(&rect, mval, 14);
- hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode);
+ hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter);
if (hits15 == 1) {
hits = selectbuffer_ret_hits_15(buffer, hits15);
goto finally;
@@ -1215,7 +1222,7 @@ static int mixed_bones_object_selectbuffer(
offs = 4 * hits15;
BLI_rcti_init_pt_radius(&rect, mval, 9);
- hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode);
+ 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;
@@ -1225,7 +1232,7 @@ static int mixed_bones_object_selectbuffer(
offs += 4 * hits9;
BLI_rcti_init_pt_radius(&rect, mval, 5);
- hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode);
+ 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;
@@ -1247,6 +1254,23 @@ static int mixed_bones_object_selectbuffer(
finally:
view3d_opengl_select_cache_end();
+ if (vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
+ const bool is_pose_mode = (vc->obact && vc->obact->mode & OB_MODE_POSE);
+ 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;
}
@@ -1258,12 +1282,12 @@ static Base *mouse_select_eval_buffer(
ViewLayer *view_layer = vc->view_layer;
Base *base, *basact = NULL;
int a;
-
+
if (do_nearest) {
unsigned int min = 0xFFFFFFFF;
int selcol = 0, notcol = 0;
-
-
+
+
if (has_bones) {
/* we skip non-bone hits */
for (a = 0; a < hits; a++) {
@@ -1278,7 +1302,7 @@ static Base *mouse_select_eval_buffer(
if (BASACT(view_layer) && (BASACT(view_layer)->flag & BASE_SELECTED) && hits > 1) {
notcol = BASACT(view_layer)->object->select_color;
}
-
+
for (a = 0; a < hits; a++) {
if (min > buffer[4 * a + 1] && notcol != (buffer[4 * a + 3] & 0xFFFF)) {
min = buffer[4 * a + 1];
@@ -1286,7 +1310,7 @@ static Base *mouse_select_eval_buffer(
}
}
}
-
+
base = FIRSTBASE(view_layer);
while (base) {
if (BASE_SELECTABLE(base)) {
@@ -1297,17 +1321,17 @@ static Base *mouse_select_eval_buffer(
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_SELECTABLED) == 0) {
+ if ((base->flag & BASE_SELECTABLE) == 0) {
base = base->next;
if (base == NULL) base = FIRSTBASE(view_layer);
if (base == startbase) break;
}
-
+
if (BASE_SELECTABLE(base)) {
for (a = 0; a < hits; a++) {
if (has_bones) {
@@ -1323,15 +1347,15 @@ static Base *mouse_select_eval_buffer(
}
}
}
-
+
if (basact) break;
-
+
base = base->next;
if (base == NULL) base = FIRSTBASE(view_layer);
if (base == startbase) break;
}
}
-
+
return basact;
}
@@ -1343,19 +1367,22 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2])
unsigned int buffer[MAXPICKBUF];
int hits;
bool do_nearest;
-
+
/* setup view context for argument to callbacks */
view3d_operator_needs_opengl(C);
ED_view3d_viewcontext_init(C, &vc);
-
- hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, false, false, &do_nearest);
-
+
+ hits = mixed_bones_object_selectbuffer(
+ &vc, buffer, mval,
+ false, false, 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);
}
-
+
return basact;
}
@@ -1387,14 +1414,14 @@ static bool ed_object_select_pick(
ARegion *ar = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *base, *startbase = NULL, *basact = NULL, *oldbasact = NULL;
+ Base *base, *startbase = NULL, *basact = NULL, *oldbasact = BASACT(view_layer);
+ 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]};
-
/* setup view context for argument to callbacks */
ED_view3d_viewcontext_init(C, &vc);
@@ -1410,11 +1437,11 @@ static bool ed_object_select_pick(
/* always start list from basact in wire mode */
startbase = FIRSTBASE(view_layer);
if (BASACT(view_layer) && BASACT(view_layer)->next) startbase = BASACT(view_layer)->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);
@@ -1437,11 +1464,24 @@ static bool ed_object_select_pick(
}
}
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 {
unsigned int buffer[MAXPICKBUF];
@@ -1450,7 +1490,13 @@ static bool ed_object_select_pick(
// TIMEIT_START(select_time);
/* if objects have posemode set, the bones are in the same selection buffer */
- hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, true, enumerate, &do_nearest);
+ const eV3DSelectObjectFilter select_filter = (
+ (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ?
+ VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK : VIEW3D_SELECT_FILTER_NOP);
+ hits = mixed_bones_object_selectbuffer(
+ &vc, buffer, mval,
+ true, enumerate, select_filter,
+ &do_nearest);
// TIMEIT_END(select_time);
@@ -1465,7 +1511,21 @@ static bool ed_object_select_pick(
else {
basact = mouse_select_eval_buffer(&vc, buffer, hits, startbase, has_bones, do_nearest);
}
-
+
+ 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 (has_bones && basact) {
if (basact->object->type == OB_CAMERA) {
if (BASACT(view_layer) == basact) {
@@ -1511,6 +1571,7 @@ static bool ed_object_select_pick(
retval = true;
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, track);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
@@ -1529,16 +1590,16 @@ static bool ed_object_select_pick(
view_layer, basact, buffer, hits, extend, deselect, toggle, do_nearest))
{
/* then bone is found */
-
- /* we make the armature selected:
+
+ /* 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 (BASACT(view_layer) && (BASACT(view_layer)->object->mode & OB_MODE_WEIGHT_PAINT)) {
/* prevent activating */
@@ -1552,11 +1613,25 @@ static bool ed_object_select_pick(
}
}
}
-
+
+ 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;
+ }
+ }
+ }
+ }
+
/* so, do we have something selected? */
if (basact) {
retval = true;
-
+
if (vc.obedit) {
/* only do select */
deselectall_except(view_layer, basact);
@@ -1564,9 +1639,6 @@ static bool ed_object_select_pick(
}
/* also prevent making it active on mouse selection */
else if (BASE_SELECTABLE(basact)) {
-
- oldbasact = BASACT(view_layer);
-
if (extend) {
ED_object_base_select(basact, BA_SELECT);
}
@@ -1596,6 +1668,7 @@ static bool ed_object_select_pick(
}
}
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
@@ -1766,7 +1839,7 @@ static void do_nurbs_box_select__doSelect(
static int do_nurbs_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
{
BoxSelectUserData data;
-
+
view3d_userdata_boxselect_init(&data, vc, rect, select);
if (extend == false && select) {
@@ -1800,7 +1873,7 @@ static int do_lattice_box_select(ViewContext *vc, rcti *rect, bool select, bool
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 OPERATOR_FINISHED;
}
@@ -1845,7 +1918,7 @@ static int do_mesh_box_select(
BoxSelectUserData data;
ToolSettings *ts = vc->scene->toolsettings;
int bbsel;
-
+
view3d_userdata_boxselect_init(&data, vc, rect, select);
if (extend == false && select)
@@ -1876,7 +1949,7 @@ static int do_mesh_box_select(
mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
}
}
-
+
if (ts->selectmode & SCE_SELECT_FACE) {
if (bbsel) {
edbm_backbuf_check_and_select_faces(vc->em, select);
@@ -1885,11 +1958,11 @@ static int do_mesh_box_select(
mesh_foreachScreenFace(vc, do_mesh_box_select__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
}
}
-
+
EDBM_backbuf_free();
-
+
EDBM_selectmode_flush(vc->em);
-
+
return OPERATOR_FINISHED;
}
@@ -1904,11 +1977,13 @@ static int do_meta_box_select(
unsigned int buffer[MAXPICKBUF];
int hits;
- hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL);
+ hits = view3d_opengl_select(
+ vc, buffer, MAXPICKBUF, rect,
+ VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
if (extend == false && select)
BKE_mball_deselect_all(mb);
-
+
for (ml = mb->editelems->first; ml; ml = ml->next) {
for (a = 0; a < hits; a++) {
if (ml->selcol1 == buffer[(4 * a) + 3]) {
@@ -1938,7 +2013,9 @@ static int do_armature_box_select(
unsigned int buffer[MAXPICKBUF];
int hits;
- hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL);
+ hits = view3d_opengl_select(
+ vc, buffer, MAXPICKBUF, rect,
+ VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(vc->view_layer, &objects_len);
@@ -2059,12 +2136,12 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
int bone_only;
int totobj = MAXPICKBUF; /* XXX solve later */
int hits;
-
+
if (vc->obact && (vc->obact->mode & OB_MODE_POSE))
bone_only = 1;
else
bone_only = 0;
-
+
if (extend == false && select) {
if (bone_only) {
FOREACH_OBJECT_IN_MODE_BEGIN (vc->view_layer, OB_MODE_POSE, ob_iter) {
@@ -2086,7 +2163,12 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
/* selection buffer now has bones potentially too, so we add MAXPICKBUF */
vbuffer = MEM_mallocN(4 * (totobj + MAXPICKELEMS) * sizeof(unsigned int), "selection buffer");
- hits = view3d_opengl_select(vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL);
+ const eV3DSelectObjectFilter select_filter = (
+ (vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ?
+ VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK : VIEW3D_SELECT_FILTER_NOP);
+ 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
@@ -2120,22 +2202,24 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
continue;
}
/* Loop over contiguous bone hits for 'base'. */
- bool bone_selected = false;
+ bool changed = false;
for (; col != col_end; col += 4) {
/* should never fail */
if (bone != NULL) {
if (select) {
if ((bone->flag & BONE_UNSELECTABLE) == 0) {
bone->flag |= BONE_SELECTED;
- bone_selected = true;
}
}
else {
bArmature *arm = base->object->data;
- bone->flag &= ~BONE_SELECTED;
- if (arm->act_bone == bone)
- arm->act_bone = NULL;
+ if ((bone->flag & BONE_UNSELECTABLE) == 0) {
+ bone->flag &= ~BONE_SELECTED;
+ if (arm->act_bone == bone)
+ arm->act_bone = NULL;
+ }
}
+ changed = true;
}
else if (!bone_only) {
ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
@@ -2149,7 +2233,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
if ((base->object->pose != NULL) && bone_only) {
const uint hit_bone = (col[4] & ~BONESEL_ANY) >> 16;
- bPoseChannel *pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone);;
+ bPoseChannel *pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone);
bone = pchan ? pchan->bone : NULL;
}
else {
@@ -2158,7 +2242,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
}
}
- if (bone_selected) {
+ if (changed) {
if (base->object && (base->object->type == OB_ARMATURE)) {
bArmature *arm = base->object->data;
@@ -2168,12 +2252,16 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
/* mask modifier ('armature' mode), etc. */
DEG_id_tag_update(&vc->obact->id, OB_RECALC_DATA);
}
+
+ /* copy on write tag is needed (for the armature), or else no refresh happens */
+ DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
}
}
}
MEM_freeN(bases);
+ DEG_id_tag_update(&vc->scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene);
}
MEM_freeN(vbuffer);
@@ -2194,7 +2282,7 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
/* setup view context for argument to callbacks */
ED_view3d_viewcontext_init(C, &vc);
-
+
select = !RNA_boolean_get(op->ptr, "deselect");
extend = RNA_boolean_get(op->ptr, "extend");
WM_operator_properties_border_to_rcti(op, &rect);
@@ -2209,6 +2297,7 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
vc.em = BKE_editmesh_from_object(vc.obedit);
ret |= do_mesh_box_select(&vc, &rect, select, extend);
if (ret & OPERATOR_FINISHED) {
+ DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
}
break;
@@ -2216,24 +2305,28 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
case OB_SURF:
ret |= do_nurbs_box_select(&vc, &rect, select, extend);
if (ret & OPERATOR_FINISHED) {
+ DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
}
break;
case OB_MBALL:
ret |= do_meta_box_select(&vc, &rect, select, extend);
if (ret & OPERATOR_FINISHED) {
+ DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
}
break;
case OB_ARMATURE:
ret |= do_armature_box_select(&vc, &rect, select, extend);
if (ret & OPERATOR_FINISHED) {
+ DEG_id_tag_update(&vc.obedit->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit);
}
break;
case OB_LATTICE:
ret |= do_lattice_box_select(&vc, &rect, select, extend);
if (ret & OPERATOR_FINISHED) {
+ DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
}
break;
@@ -2270,7 +2363,7 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
}
return ret;
-}
+}
/* *****************Selection Operators******************* */
@@ -2282,17 +2375,17 @@ void VIEW3D_OT_select_border(wmOperatorType *ot)
ot->name = "Border Select";
ot->description = "Select items using border selection";
ot->idname = "VIEW3D_OT_select_border";
-
+
/* api callbacks */
ot->invoke = WM_gesture_border_invoke;
ot->exec = view3d_borderselect_exec;
ot->modal = WM_gesture_border_modal;
ot->poll = view3d_selectable_data;
ot->cancel = WM_gesture_border_cancel;
-
+
/* flags */
ot->flag = OPTYPE_UNDO;
-
+
/* rna */
WM_operator_properties_gesture_border_select(ot);
}
@@ -2336,6 +2429,7 @@ static bool ed_wpaint_vertex_select_pick(
}
paintvert_flush_flags(obact);
+ DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
return true;
}
@@ -2392,7 +2486,7 @@ static int view3d_select_exec(bContext *C, wmOperator *op)
retval = ED_mball_select_pick(C, location, extend, deselect, toggle);
else if (obedit->type == OB_FONT)
retval = ED_curve_editfont_select_pick(C, location, extend, deselect, toggle);
-
+
}
else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT)
return PE_mouse_particles(C, location, extend, deselect, toggle);
@@ -2424,18 +2518,18 @@ void VIEW3D_OT_select(wmOperatorType *ot)
PropertyRNA *prop;
/* identifiers */
- ot->name = "Activate/Select";
- ot->description = "Activate/select item(s)";
+ 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);
@@ -2510,7 +2604,7 @@ static void mesh_circle_select(ViewContext *vc, const bool select, const int mva
ToolSettings *ts = vc->scene->toolsettings;
int bbsel;
CircleSelectUserData data;
-
+
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 */
@@ -2535,7 +2629,7 @@ static void mesh_circle_select(ViewContext *vc, const bool select, const int mva
mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
}
}
-
+
if (ts->selectmode & SCE_SELECT_FACE) {
if (bbsel) {
edbm_backbuf_check_and_select_faces(vc->em, select);
@@ -2728,11 +2822,11 @@ static void do_circle_select_pose__doSelectBone(
static void pose_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
{
CircleSelectUserData data;
-
+
view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
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) {
@@ -2744,6 +2838,9 @@ static void pose_circle_select(ViewContext *vc, const bool select, const int mva
/* mask modifier ('armature' mode), etc. */
DEG_id_tag_update(&vc->obact->id, OB_RECALC_DATA);
}
+
+ /* copy on write tag is needed (for the armature), or else no refresh happens */
+ DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
}
}
@@ -2755,13 +2852,13 @@ static bool armature_circle_doSelectJoint(void *userData, EditBone *ebone, const
if (head) {
if (data->select)
ebone->flag |= BONE_ROOTSEL;
- else
+ else
ebone->flag &= ~BONE_ROOTSEL;
}
else {
if (data->select)
ebone->flag |= BONE_TIPSEL;
- else
+ else
ebone->flag &= ~BONE_TIPSEL;
}
return 1;
@@ -2934,14 +3031,17 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
if (CTX_data_edit_object(C)) {
obedit_circle_select(&vc, select, mval, (float)radius);
+ DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
}
else if (BKE_paint_select_face_test(obact)) {
paint_facesel_circle_select(&vc, select, mval, (float)radius);
+ DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
}
else if (BKE_paint_select_vert_test(obact)) {
paint_vertsel_circle_select(&vc, select, mval, (float)radius);
+ DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
}
else if (obact->mode & OB_MODE_POSE) {
@@ -2958,10 +3058,11 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
}
else {
if (object_circle_select(&vc, select, mval, (float)radius)) {
+ DEG_id_tag_update(&vc.scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc.scene);
}
}
-
+
return OPERATOR_FINISHED;
}
@@ -2970,13 +3071,13 @@ 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->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;
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index 95ab30d3352..606c07cd1fa 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -30,6 +30,8 @@
*/
+#include "MEM_guardedalloc.h"
+
#include "DNA_armature_types.h"
#include "DNA_object_types.h"
@@ -40,6 +42,8 @@
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_context.h"
+#include "BKE_editmesh.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_mball.h"
#include "BKE_object.h"
@@ -47,6 +51,7 @@
#include "BKE_tracking.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -70,6 +75,7 @@ static bool snap_calc_active_center(bContext *C, const bool select_only, float r
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);
@@ -81,62 +87,83 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
gridf = rv3d->gridview;
if (obedit) {
- if (ED_transverts_check_obedit(obedit))
- ED_transverts_create_from_obedit(&tvs, obedit, 0);
- if (tvs.transverts_tot == 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, &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ 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;
+ }
- 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);
+ if (ED_transverts_check_obedit(obedit)) {
+ ED_transverts_create_from_obedit(&tvs, obedit, 0);
+ }
+
+ if (tvs.transverts_tot == 0) {
+ continue;
+ }
+
+ 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);
}
-
- 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);
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
+ FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN(view_layer_eval, ob_eval)
{
+ Object *ob = DEG_get_original_object(ob_eval);
if (ob->mode & OB_MODE_POSE) {
- bPoseChannel *pchan;
- bArmature *arm = ob->data;
-
- invert_m4_m4(ob->imat, ob->obmat);
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone->flag & BONE_SELECTED) {
- if (pchan->bone->layer & arm->layer) {
- if ((pchan->bone->flag & BONE_CONNECTED) == 0) {
+ 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->pose_mat[3]);
+ copy_v3_v3(nLoc, pchan_eval->pose_mat[3]);
/* We must operate in world space! */
- mul_m4_v3(ob->obmat, nLoc);
+ 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->imat, vec);
-
+ mul_m4_v3(ob_eval->imat, vec);
+
/* Get location of grid point in pose space. */
- BKE_armature_loc_pose_to_bone(pchan, vec, vec);
-
- /* adjust location */
+ 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)
@@ -154,39 +181,39 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
}
}
ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
-
+
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
else {
- vec[0] = -ob->obmat[3][0] + gridf * floorf(0.5f + ob->obmat[3][0] / gridf);
- vec[1] = -ob->obmat[3][1] + gridf * floorf(0.5f + ob->obmat[3][1] / gridf);
- vec[2] = -ob->obmat[3][2] + gridf * floorf(0.5f + ob->obmat[3][2] / gridf);
-
+ 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] += vec[0];
+ ob->loc[0] = ob_eval->loc[0] + vec[0];
if ((ob->protectflag & OB_LOCK_LOCY) == 0)
- ob->loc[1] += vec[1];
+ ob->loc[1] = ob_eval->loc[1] + vec[1];
if ((ob->protectflag & OB_LOCK_LOCZ) == 0)
- ob->loc[2] += vec[2];
-
+ ob->loc[2] = ob_eval->loc[2] + vec[2];
+
/* auto-keyframing */
ED_autokeyframe_object(C, scene, ob, ks);
DEG_id_tag_update(&ob->id, OB_RECALC_OB);
}
}
- CTX_DATA_END;
+ FOREACH_SELECTED_EDITABLE_OBJECT_END;
}
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -196,11 +223,11 @@ void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot)
ot->name = "Snap Selection to Grid";
ot->description = "Snap selected item(s) to 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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -235,7 +262,7 @@ static int snap_selected_to_location(bContext *C, const float snap_target_global
if (obedit) {
float snap_target_local[3];
-
+
if (ED_transverts_check_obedit(obedit))
ED_transverts_create_from_obedit(&tvs, obedit, 0);
if (tvs.transverts_tot == 0)
@@ -243,7 +270,7 @@ static int snap_selected_to_location(bContext *C, const float snap_target_global
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);
@@ -264,7 +291,7 @@ static int snap_selected_to_location(bContext *C, const float snap_target_global
copy_v3_v3(tv->loc, snap_target_local);
}
}
-
+
ED_transverts_update_obedit(&tvs, obedit);
ED_transverts_free(&tvs);
}
@@ -396,7 +423,7 @@ static int snap_selected_to_location(bContext *C, const float snap_target_global
}
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -418,11 +445,11 @@ void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot)
ot->name = "Snap Selection to Cursor";
ot->description = "Snap selected item(s) to 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;
@@ -473,8 +500,9 @@ static int snap_curs_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
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, DEG_TAG_COPY_ON_WRITE);
return OPERATOR_FINISHED;
}
@@ -485,18 +513,18 @@ void VIEW3D_OT_snap_cursor_to_grid(wmOperatorType *ot)
ot->name = "Snap Cursor to Grid";
ot->description = "Snap cursor to 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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* **************************************************** */
-static void bundle_midpoint(Scene *scene, Object *ob, float vec[3])
+static void bundle_midpoint(Depsgraph *depsgraph, Scene *scene, Object *ob, float vec[3])
{
MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
MovieTracking *tracking;
@@ -511,7 +539,7 @@ static void bundle_midpoint(Scene *scene, Object *ob, float vec[3])
copy_m4_m4(cammat, ob->obmat);
- BKE_tracking_get_camera_object_matrix(scene, ob, mat);
+ BKE_tracking_get_camera_object_matrix(depsgraph, scene, ob, mat);
INIT_MINMAX(min, max);
@@ -550,6 +578,8 @@ static void bundle_midpoint(Scene *scene, Object *ob, float vec[3])
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);
@@ -563,7 +593,6 @@ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
zero_v3(centroid);
if (obedit) {
-
if (ED_transverts_check_obedit(obedit))
ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS | TM_SKIP_HANDLES);
@@ -571,17 +600,18 @@ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
return false;
}
- copy_m3_m4(bmat, obedit->obmat);
-
+ 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->obmat[3]);
+ add_v3_v3(vec, obedit_eval->obmat[3]);
add_v3_v3(centroid, vec);
minmax_v3v3_v3(min, max, vec);
}
-
+
if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEAN) {
mul_v3_fl(centroid, 1.0f / (float)tvs.transverts_tot);
copy_v3_v3(cursor, centroid);
@@ -594,15 +624,16 @@ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
}
else {
Object *obact = CTX_data_active_object(C);
-
+
if (obact && (obact->mode & OB_MODE_POSE)) {
- bArmature *arm = obact->data;
+ Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact);
+ bArmature *arm = obact_eval->data;
bPoseChannel *pchan;
- for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
+ 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->obmat, vec);
+ mul_m4_v3(obact_eval->obmat, vec);
add_v3_v3(centroid, vec);
minmax_v3v3_v3(min, max, vec);
count++;
@@ -611,15 +642,15 @@ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
}
}
else {
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
+ FOREACH_SELECTED_OBJECT_BEGIN(view_layer_eval, ob_eval)
{
- copy_v3_v3(vec, ob->obmat[3]);
+ copy_v3_v3(vec, ob_eval->obmat[3]);
/* special case for camera -- snap to bundles */
- if (ob->type == OB_CAMERA) {
+ 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, ob, vec);
+ bundle_midpoint(depsgraph, scene, DEG_get_original_object(ob_eval), vec);
}
}
@@ -627,7 +658,7 @@ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
minmax_v3v3_v3(min, max, vec);
count++;
}
- CTX_DATA_END;
+ FOREACH_SELECTED_OBJECT_END;
}
if (count == 0) {
@@ -655,6 +686,7 @@ static int snap_curs_to_sel_exec(bContext *C, wmOperator *UNUSED(op))
if (snap_curs_to_sel_ex(C, curs)) {
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
return OPERATOR_FINISHED;
}
@@ -669,11 +701,11 @@ void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot)
ot->name = "Snap Cursor to Selected";
ot->description = "Snap cursor to center of 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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -685,31 +717,36 @@ 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])
{
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
Object *obedit = CTX_data_edit_object(C);
if (obedit) {
- if (ED_object_editmode_calc_active_center(obedit, select_only, r_center)) {
- mul_m4_v3(obedit->obmat, r_center);
+ Object *ob_edit_eval = DEG_get_evaluated_object(depsgraph, obedit);
+
+ if (ED_object_editmode_calc_active_center(ob_edit_eval, select_only, r_center)) {
+ mul_m4_v3(ob_edit_eval->obmat, r_center);
return true;
}
}
else {
Object *ob = CTX_data_active_object(C);
-
if (ob) {
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+
if (ob->mode & OB_MODE_POSE) {
- bPoseChannel *pchan = BKE_pose_channel_active(ob);
+ bPoseChannel *pchan = BKE_pose_channel_active(ob_eval);
if (pchan) {
if (!select_only || (pchan->bone->flag & BONE_SELECTED)) {
copy_v3_v3(r_center, pchan->pose_head);
- mul_m4_v3(ob->obmat, r_center);
+ mul_m4_v3(ob_eval->obmat, r_center);
return true;
}
}
}
else {
- if (!select_only || (ob->flag & SELECT)) {
- copy_v3_v3(r_center, ob->obmat[3]);
+
+ if (!select_only || (ob_eval->flag & SELECT)) {
+ copy_v3_v3(r_center, ob_eval->obmat[3]);
return true;
}
}
@@ -724,11 +761,13 @@ static int snap_curs_to_active_exec(bContext *C, wmOperator *UNUSED(op))
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
float *curs;
-
+
curs = ED_view3d_cursor3d_get(scene, v3d)->location;
if (snap_calc_active_center(C, false, curs)) {
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
+
return OPERATOR_FINISHED;
}
else {
@@ -742,11 +781,11 @@ void VIEW3D_OT_snap_cursor_to_active(wmOperatorType *ot)
ot->name = "Snap Cursor to Active";
ot->description = "Snap cursor to 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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -761,9 +800,10 @@ static int snap_curs_to_center_exec(bContext *C, wmOperator *UNUSED(op))
curs = ED_view3d_cursor3d_get(scene, v3d)->location;
zero_v3(curs);
-
+
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
-
+ DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
+
return OPERATOR_FINISHED;
}
@@ -773,11 +813,11 @@ void VIEW3D_OT_snap_cursor_to_center(wmOperatorType *ot)
ot->name = "Snap Cursor to Center";
ot->description = "Snap cursor to the Center";
ot->idname = "VIEW3D_OT_snap_cursor_to_center";
-
+
/* api callbacks */
ot->exec = snap_curs_to_center_exec;
ot->poll = ED_operator_view3d_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -807,12 +847,12 @@ bool ED_view3d_minmax_verts(Object *obedit, float min[3], float max[3])
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 (a = 0; a < tvs.transverts_tot; a++, tv++) {
copy_v3_v3(vec, (tv->flag & TX_VERT_USE_MAPLOC) ? tv->maploc : tv->loc);
@@ -821,8 +861,8 @@ bool ED_view3d_minmax_verts(Object *obedit, float min[3], float max[3])
add_v3_v3(centroid, vec);
minmax_v3v3_v3(min, 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 26dca5bf252..707e0e7a394 100644
--- a/source/blender/editors/space_view3d/view3d_toolbar.c
+++ b/source/blender/editors/space_view3d/view3d_toolbar.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -28,160 +28,31 @@
* \ingroup spview3d
*/
-
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <float.h>
-#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "MEM_guardedalloc.h"
-
-#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "BLI_ghash.h"
-
-#include "BLT_translation.h"
#include "BKE_context.h"
-#include "BKE_screen.h"
-
#include "WM_api.h"
#include "WM_types.h"
-#include "RNA_access.h"
-
#include "ED_screen.h"
-#include "ED_undo.h"
-
-#include "UI_interface.h"
-#include "UI_resources.h"
#include "view3d_intern.h" /* own include */
-/* ******************* */
-
-typedef struct CustomTool {
- struct CustomTool *next, *prev;
- char opname[OP_MAX_TYPENAME];
- char context[OP_MAX_TYPENAME];
-} CustomTool;
-
-static void operator_call_cb(struct bContext *C, void *arg_listbase, void *arg2)
-{
- wmOperatorType *ot = arg2;
-
- if (ot) {
- CustomTool *ct = MEM_callocN(sizeof(CustomTool), "CustomTool");
-
- BLI_addtail(arg_listbase, ct);
- BLI_strncpy(ct->opname, ot->idname, OP_MAX_TYPENAME);
- BLI_strncpy(ct->context, CTX_data_mode_string(C), OP_MAX_TYPENAME);
- }
-
-}
-
-static void operator_search_cb(const struct bContext *C, void *UNUSED(arg), const char *str, uiSearchItems *items)
-{
- GHashIterator iter;
-
- for (WM_operatortype_iter(&iter); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) {
- wmOperatorType *ot = BLI_ghashIterator_getValue(&iter);
-
- if (BLI_strcasestr(ot->name, str)) {
- if (WM_operator_poll((bContext *)C, ot)) {
-
- if (false == UI_search_item_add(items, ot->name, ot, 0))
- break;
- }
- }
- }
-}
-
-
-/* ID Search browse menu, open */
-static uiBlock *tool_search_menu(bContext *C, ARegion *ar, void *arg_listbase)
-{
- static char search[OP_MAX_TYPENAME];
- wmEvent event;
- 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, ar, "_popup", UI_EMBOSS);
- UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_SEARCH_MENU);
-
- /* fake button, it holds space for search items */
- uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 15, UI_searchbox_size_x(), UI_searchbox_size_y(), NULL, 0, 0, 0, 0, NULL);
-
- but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, 150, 19, 0, 0, "");
- UI_but_func_search_set(but, NULL, operator_search_cb, arg_listbase, operator_call_cb, NULL);
-
- UI_block_bounds_set_normal(block, 6);
- UI_block_direction_set(block, UI_DIR_DOWN);
- UI_block_end(C, block);
-
- wm_event_init_from_window(win, &event);
- event.type = EVT_BUT_OPEN;
- event.val = KM_PRESS;
- event.customdata = but;
- event.customdatafree = false;
- wm_event_add(win, &event);
-
- return block;
-}
-
-
-static void view3d_panel_tool_shelf(const bContext *C, Panel *pa)
-{
- SpaceLink *sl = CTX_wm_space_data(C);
- SpaceType *st = NULL;
- uiLayout *col;
- const char *context = CTX_data_mode_string(C);
-
- if (sl)
- st = BKE_spacetype_from_id(sl->spacetype);
-
- if (st && st->toolshelf.first) {
- CustomTool *ct;
-
- for (ct = st->toolshelf.first; ct; ct = ct->next) {
- if (STREQLEN(context, ct->context, OP_MAX_TYPENAME)) {
- col = uiLayoutColumn(pa->layout, true);
- uiItemFullO(col, ct->opname, NULL, ICON_NONE, NULL, WM_OP_INVOKE_REGION_WIN, 0, NULL);
- }
- }
- }
- col = uiLayoutColumn(pa->layout, true);
- uiDefBlockBut(uiLayoutGetBlock(pa->layout), tool_search_menu, &st->toolshelf, "Add Tool", 0, 0, UI_UNIT_X, UI_UNIT_Y, "Add Tool in shelf, gets saved in files");
-}
-
-
-void view3d_toolshelf_register(ARegionType *art)
-{
- PanelType *pt;
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel tools");
- strcpy(pt->idname, "VIEW3D_PT_tool_shelf");
- strcpy(pt->label, N_("Tool Shelf"));
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = view3d_panel_tool_shelf;
- BLI_addtail(&art->paneltypes, pt);
-}
-
/* ********** 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);
-
+
if (ar)
ED_region_toggle_hidden(C, ar);
@@ -190,14 +61,13 @@ static int view3d_toolshelf_toggle_exec(bContext *C, wmOperator *UNUSED(op))
void VIEW3D_OT_toolshelf(wmOperatorType *ot)
{
- ot->name = "Tool Shelf";
+ 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;
-
+
/* 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 bc6d174efa0..ca5375b6b54 100644
--- a/source/blender/editors/space_view3d/view3d_utils.c
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -46,6 +46,7 @@
#include "BKE_camera.h"
#include "BKE_context.h"
+#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_screen.h"
@@ -395,14 +396,15 @@ 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(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) {
- rv3d->dist = ED_view3d_offset_distance(v3d->camera->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
- ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
+ 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)) {
@@ -415,7 +417,7 @@ void ED_view3d_persp_switch_from_camera(View3D *v3d, RegionView3D *rv3d, const c
*
* shared with NDOF.
*/
-bool ED_view3d_persp_ensure(struct View3D *v3d, ARegion *ar)
+bool ED_view3d_persp_ensure(const Depsgraph *depsgraph, View3D *v3d, ARegion *ar)
{
RegionView3D *rv3d = ar->regiondata;
const bool autopersp = (U.uiflag & USER_AUTOPERSP) != 0;
@@ -429,7 +431,7 @@ bool ED_view3d_persp_ensure(struct View3D *v3d, ARegion *ar)
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(v3d, rv3d, persp);
+ ED_view3d_persp_switch_from_camera(depsgraph, v3d, rv3d, persp);
}
else if (autopersp && RV3D_VIEW_IS_AXIS(rv3d->view)) {
rv3d->persp = RV3D_PERSP;
@@ -463,20 +465,21 @@ bool ED_view3d_camera_lock_check(const View3D *v3d, const RegionView3D *rv3d)
* 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(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(v3d->camera->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
+ rv3d->dist = ED_view3d_offset_distance(ob_camera_eval->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
}
- ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
+ ED_view3d_from_object(ob_camera_eval, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
}
}
-void ED_view3d_camera_lock_init(View3D *v3d, RegionView3D *rv3d)
+void ED_view3d_camera_lock_init(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d)
{
- ED_view3d_camera_lock_init_ex(v3d, rv3d, true);
+ ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, true);
}
/**
@@ -484,7 +487,7 @@ void ED_view3d_camera_lock_init(View3D *v3d, RegionView3D *rv3d)
*
* \return true if the camera is moved.
*/
-bool ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d)
+bool ED_view3d_camera_lock_sync(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d)
{
if (ED_view3d_camera_lock_check(v3d, rv3d)) {
ObjectTfmProtectedChannels obtfm;
@@ -501,15 +504,17 @@ bool ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d)
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, v3d->camera->obmat);
+ 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->obmat);
+ 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);
@@ -526,7 +531,7 @@ bool ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d)
/* 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(v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist);
+ 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, OB_RECALC_OB);
@@ -895,7 +900,7 @@ static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int marg
* \param fallback_depth_pt: Use this points depth when no depth can be found.
*/
bool ED_view3d_autodist(
- struct Depsgraph *graph, ARegion *ar, View3D *v3d,
+ Depsgraph *depsgraph, ARegion *ar, View3D *v3d,
const int mval[2], float mouse_worldloc[3],
const bool alphaoverride, const float fallback_depth_pt[3])
{
@@ -905,7 +910,7 @@ bool ED_view3d_autodist(
bool depth_ok = false;
/* Get Z Depths, needed for perspective, nice for ortho */
- ED_view3d_draw_depth(graph, ar, v3d, alphaoverride);
+ ED_view3d_draw_depth(depsgraph, ar, v3d, alphaoverride);
/* Attempt with low margin's first */
i = 0;
@@ -932,19 +937,18 @@ bool ED_view3d_autodist(
}
}
-void ED_view3d_autodist_init(
- struct Depsgraph *graph,
+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(graph, ar, v3d, true);
+ ED_view3d_draw_depth(depsgraph, ar, v3d, true);
break;
case 1:
{
- Scene *scene = DEG_get_evaluated_scene(graph);
- ED_view3d_draw_depth_gpencil(graph, scene, ar, v3d);
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ ED_view3d_draw_depth_gpencil(depsgraph, scene, ar, v3d);
break;
}
}
@@ -1063,6 +1067,7 @@ float ED_view3d_radius_to_dist_ortho(const float lens, 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)
{
@@ -1083,7 +1088,8 @@ float ED_view3d_radius_to_dist(
BKE_camera_params_init(&params);
params.clipsta = v3d->near;
params.clipend = v3d->far;
- BKE_camera_params_from_object(&params, v3d->camera);
+ 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);
@@ -1273,7 +1279,7 @@ bool ED_view3d_lock(RegionView3D *rv3d)
* \param quat The view rotation, quaternion normally from RegionView3D.viewquat.
* \param dist The view distance from ofs, normally from RegionView3D.dist.
*/
-void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist)
+void ED_view3d_from_m4(const float mat[4][4], float ofs[3], float quat[4], float *dist)
{
float nmat[3][3];
@@ -1318,13 +1324,14 @@ void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], c
/**
* Set the RegionView3D members from an objects transformation and optionally lens.
+ * \param depsgraph The depsgraph to get the evaluated object for the lens calculation.
* \param ob The object to set the view to.
* \param ofs The view offset to be set, normally from RegionView3D.ofs.
* \param quat The view rotation to be set, quaternion normally from RegionView3D.viewquat.
* \param dist The view distance from ofs to be set, normally from RegionView3D.dist.
* \param lens The view lens angle set for cameras and lamps, normally from View3D.lens.
*/
-void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist, float *lens)
+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);
@@ -1339,16 +1346,19 @@ void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist,
/**
* Set the object transformation from RegionView3D members.
+ * \param depsgraph The depsgraph to get the evaluated object parent for the transformation calculation.
* \param ob The object which has the transformation assigned.
* \param ofs The view offset, normally from RegionView3D.ofs.
* \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(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);
- BKE_object_apply_mat4(ob, mat, true, true);
+
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ BKE_object_apply_mat4_ex(ob, mat, ob_eval->parent, ob_eval->parentinv, true);
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 0e78fd02b30..53e3fbb87b0 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -48,12 +48,14 @@
#include "BKE_scene.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "UI_resources.h"
#include "GPU_glew.h"
#include "GPU_select.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -62,8 +64,6 @@
#include "DRW_engine.h"
-#include "DEG_depsgraph_query.h"
-
#include "view3d_intern.h" /* own include */
/* -------------------------------------------------------------------- */
@@ -121,14 +121,14 @@ static void view3d_smooth_view_state_restore(const struct SmoothView3DState *sms
/* the arguments are the desired situation */
void ED_view3d_smooth_view_ex(
/* avoid passing in the context */
- wmWindowManager *wm, wmWindow *win, ScrArea *sa,
+ 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);
@@ -152,7 +152,7 @@ void ED_view3d_smooth_view_ex(
* 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(v3d, rv3d);
+ ED_view3d_camera_lock_init(depsgraph, v3d, rv3d);
}
/* store the options we want to end with */
@@ -177,15 +177,16 @@ void ED_view3d_smooth_view_ex(
}
if (sview->camera) {
- sms.dst.dist = ED_view3d_offset_distance(sview->camera->obmat, sview->ofs, VIEW3D_DIST_FALLBACK);
- ED_view3d_from_object(sview->camera, sms.dst.ofs, sms.dst.quat, &sms.dst.dist, &sms.dst.lens);
+ 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->drawtype != OB_RENDER) {
bool changed = false; /* zero means no difference */
-
+
if (sview->camera_old != sview->camera)
changed = true;
else if (sms.dst.dist != rv3d->dist)
@@ -196,15 +197,16 @@ void ED_view3d_smooth_view_ex(
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) {
- sms.src.dist = ED_view3d_offset_distance(sview->camera_old->obmat, rv3d->ofs, 0.0f);
+ 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(sview->camera_old, sms.src.ofs, sms.src.quat, &sms.src.dist, &sms.src.lens);
+ 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) {
@@ -213,10 +215,10 @@ void ED_view3d_smooth_view_ex(
}
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
+ * the angle between quats
* this means small rotations wont lag */
if (sview->quat && !sview->ofs && !sview->dist) {
/* scale the time allowed by the rotation */
@@ -226,14 +228,15 @@ void ED_view3d_smooth_view_ex(
/* 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) &&
- (sview->camera->type == OB_CAMERA) &&
- (((Camera *)sview->camera->data)->type == CAM_ORTHO)) ?
+ (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);
@@ -252,7 +255,7 @@ void ED_view3d_smooth_view_ex(
ok = true;
}
}
-
+
/* if we get here nothing happens */
if (ok == false) {
if (sms.to_camera == false) {
@@ -261,7 +264,7 @@ void ED_view3d_smooth_view_ex(
rv3d->dist = sms.dst.dist;
v3d->lens = sms.dst.lens;
- ED_view3d_camera_lock_sync(v3d, rv3d);
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
}
if (rv3d->viewlock & RV3D_BOXVIEW) {
@@ -277,11 +280,13 @@ void ED_view3d_smooth_view(
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);
@@ -290,18 +295,19 @@ void ED_view3d_smooth_view(
/* 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;
@@ -310,17 +316,17 @@ static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *ar, bool
else {
view3d_smooth_view_state_restore(&sms->dst, v3d, rv3d);
- ED_view3d_camera_lock_sync(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;
@@ -339,11 +345,11 @@ static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *ar, bool
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(v3d, rv3d);
+ 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);
}
@@ -351,7 +357,7 @@ static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *ar, bool
/* Event handling won't know if a UI item has been moved under the pointer. */
WM_event_add_mousemove(C);
}
-
+
if (sync_boxview && (rv3d->viewlock & RV3D_BOXVIEW)) {
view3d_boxview_copy(CTX_wm_area(C), ar);
}
@@ -431,6 +437,7 @@ 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;
@@ -444,15 +451,15 @@ static int view3d_camera_to_view_exec(bContext *C, wmOperator *UNUSED(op))
BKE_object_tfm_protected_backup(v3d->camera, &obtfm);
- ED_view3d_to_object(v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist);
+ ED_view3d_to_object(depsgraph, v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist);
BKE_object_tfm_protected_restore(v3d->camera, &obtfm, v3d->camera->protectflag);
DEG_id_tag_update(&v3d->camera->id, OB_RECALC_OB);
rv3d->persp = RV3D_CAMOB;
-
+
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, v3d->camera);
-
+
return OPERATOR_FINISHED;
}
@@ -482,11 +489,11 @@ void VIEW3D_OT_camera_to_view(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -503,28 +510,28 @@ static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op)
{
Depsgraph *depsgraph = CTX_data_depsgraph(C);
Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(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 == NULL) {
+ 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, view_layer, camera_ob, r_co, &r_scale)) {
+ 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->type == OB_CAMERA) && (((Camera *)camera_ob->data)->type == CAM_ORTHO)) {
+ 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->obmat);
+ copy_m4_m4(obmat_new, camera_ob_eval->obmat);
copy_v3_v3(obmat_new[3], r_co);
/* only touch location */
@@ -652,7 +659,7 @@ static int view3d_setobjectascamera_exec(bContext *C, wmOperator *op)
}
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene);
}
-
+
return OPERATOR_FINISHED;
}
@@ -670,11 +677,11 @@ void VIEW3D_OT_object_as_camera(wmOperatorType *ot)
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;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -694,7 +701,7 @@ void view3d_winmatrix_set(Depsgraph *depsgraph, ARegion *ar, const View3D *v3d,
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;
@@ -755,9 +762,9 @@ void view3d_viewmatrix_set(
{
if (rv3d->persp == RV3D_CAMOB) { /* obs/camera */
if (v3d->camera) {
- Object *camera_object = DEG_get_evaluated_object(depsgraph, v3d->camera);
- BKE_object_where_is_calc(depsgraph, scene, camera_object);
- obmat_to_viewmat(rv3d, camera_object);
+ Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
+ BKE_object_where_is_calc(depsgraph, scene, ob_camera_eval);
+ obmat_to_viewmat(rv3d, ob_camera_eval);
}
else {
quat_to_mat4(rv3d->viewmat, rv3d->viewquat);
@@ -771,19 +778,19 @@ void view3d_viewmatrix_set(
/* 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 = v3d->ob_centre;
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, v3d->ob_centre);
float vec[3];
-
- copy_v3_v3(vec, ob->obmat[3]);
- if (ob->type == OB_ARMATURE && v3d->ob_centre_bone[0]) {
- bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, v3d->ob_centre_bone);
+
+ 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->obmat, vec);
+ mul_m4_v3(ob_eval->obmat, vec);
}
}
translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]);
@@ -889,6 +896,13 @@ static bool drw_select_loop_pass(eDRWSelectStage stage, void *user_data)
}
#endif /* WITH_OPENGL_LEGACY */
+/** 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);
+}
+
/**
* \warning be sure to account for a negative return value
* This is an error, "Too many objects in select buffer"
@@ -898,10 +912,10 @@ static bool drw_select_loop_pass(eDRWSelectStage stage, void *user_data)
*/
int view3d_opengl_select(
ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input,
- eV3DSelectMode select_mode)
+ eV3DSelectMode select_mode, eV3DSelectObjectFilter select_filter)
{
struct bThemeState theme_state;
- Depsgraph *graph = vc->depsgraph;
+ Depsgraph *depsgraph = vc->depsgraph;
Scene *scene = vc->scene;
View3D *v3d = vc->v3d;
ARegion *ar = vc->ar;
@@ -946,6 +960,25 @@ int view3d_opengl_select(
}
}
+ struct {
+ DRW_ObjectFilterFn fn;
+ void *user_data;
+ } object_filter = {NULL, NULL};
+ switch (select_filter) {
+ case VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK:
+ {
+ Object *obact = OBACT(vc->view_layer);
+ 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_NOP:
+ break;
+
+ }
+
/* Tools may request depth outside of regular drawing code. */
UI_Theme_Store(&theme_state);
UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
@@ -968,16 +1001,16 @@ int view3d_opengl_select(
/* 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, graph, scene, ar, v3d, vc->rv3d->viewmat, NULL, &rect);
+ ED_view3d_draw_setup_view(vc->win, depsgraph, scene, ar, v3d, vc->rv3d->viewmat, NULL, &rect);
if (v3d->drawtype > OB_WIRE) {
v3d->zbuf = true;
- glEnable(GL_DEPTH_TEST);
+ GPU_depth_test(true);
}
if (vc->rv3d->rflag & RV3D_CLIPPING)
ED_view3d_clipping_set(vc->rv3d);
-
+
#ifdef WITH_OPENGL_LEGACY
if (IS_VIEWPORT_LEGACY(vc->v3d)) {
@@ -1005,21 +1038,22 @@ int view3d_opengl_select(
.gpu_select_mode = gpu_select_mode,
};
DRW_draw_select_loop(
- graph, ar, v3d,
+ depsgraph, ar, v3d,
use_obedit_skip, use_nearest, &rect,
- drw_select_loop_pass, &drw_select_loop_user_data);
+ drw_select_loop_pass, &drw_select_loop_user_data,
+ object_filter.fn, object_filter.user_data);
hits = drw_select_loop_user_data.hits;
}
#endif /* WITH_OPENGL_LEGACY */
G.f &= ~G_PICKSEL;
- ED_view3d_draw_setup_view(vc->win, graph, scene, ar, v3d, vc->rv3d->viewmat, NULL, NULL);
-
+ ED_view3d_draw_setup_view(vc->win, depsgraph, scene, ar, v3d, vc->rv3d->viewmat, NULL, NULL);
+
if (v3d->drawtype > OB_WIRE) {
v3d->zbuf = 0;
- glDisable(GL_DEPTH_TEST);
+ GPU_depth_test(false);
}
-
+
if (vc->rv3d->rflag & RV3D_CLIPPING)
ED_view3d_clipping_disable();
@@ -1045,28 +1079,28 @@ finally:
int ED_view3d_view_layer_set(int lay, const int *values, int *active)
{
int i, tot = 0;
-
+
/* ensure we always have some layer selected */
for (i = 0; i < 20; i++)
if (values[i])
tot++;
-
+
if (tot == 0)
return lay;
-
+
for (i = 0; i < 20; i++) {
-
+
if (active) {
/* if this value has just been switched on, make that layer active */
if (values[i] && (lay & (1 << i)) == 0) {
*active = (1 << i);
}
}
-
+
if (values[i]) lay |= (1 << i);
else lay &= ~(1 << i);
}
-
+
/* ensure always an active layer */
if (active && (lay & *active) == 0) {
for (i = 0; i < 20; i++) {
@@ -1076,7 +1110,7 @@ int ED_view3d_view_layer_set(int lay, const int *values, int *active)
}
}
}
-
+
return lay;
}
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index 6bbc0b7d985..e3e82e8b9c2 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -37,6 +37,7 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
+#include "BKE_main.h"
#include "BKE_report.h"
#include "BLT_translation.h"
@@ -403,7 +404,7 @@ static void walk_update_header(bContext *C, wmOperator *op, WalkInfo *walk)
#undef WM_MODALKEY
- ED_area_headerprint(CTX_wm_area(C), header);
+ ED_workspace_status_text(C, header);
}
static void walk_navigation_mode_set(bContext *C, wmOperator *op, WalkInfo *walk, eWalkMethod mode)
@@ -507,6 +508,7 @@ 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);
walk->rv3d = CTX_wm_region_view3d(C);
@@ -602,7 +604,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
walk->rv3d->rflag |= RV3D_NAVIGATING;
walk->snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), walk->scene, CTX_data_depsgraph(C), 0,
+ bmain, walk->scene, CTX_data_depsgraph(C), 0,
walk->ar, walk->v3d);
walk->v3d_camera_control = ED_view3d_cameracontrol_acquire(
@@ -1434,7 +1436,7 @@ static int walk_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
if (ELEM(exit_code, OPERATOR_FINISHED, OPERATOR_CANCELLED))
- ED_area_headerprint(CTX_wm_area(C), NULL);
+ ED_workspace_status_text(C, NULL);
return exit_code;
}
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 405c6213017..f233780a85b 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -74,6 +74,7 @@
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "ED_image.h"
#include "ED_keyframing.h"
@@ -651,7 +652,7 @@ static void viewRedrawForce(const bContext *C, TransInfo *t)
static void viewRedrawPost(bContext *C, TransInfo *t)
{
- ED_area_headerprint(t->sa, NULL);
+ ED_area_status_text(t->sa, NULL);
if (t->spacetype == SPACE_VIEW3D) {
/* if autokeying is enabled, send notifiers that keyframes were added */
@@ -1520,7 +1521,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
/* 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 && (t->launch_event == LEFTMOUSE || t->launch_event == RIGHTMOUSE)) {
+ if ((event->type == t->launch_event) && ISMOUSE(t->launch_event)) {
t->state = TRANS_CONFIRM;
}
}
@@ -1563,6 +1564,8 @@ bool calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], floa
TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data");
bool success;
+ t->context = C;
+
t->state = TRANS_RUNNING;
/* avoid calculating PET */
@@ -1749,12 +1752,12 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
UNUSED_VARS_NDEBUG(shdr_pos); /* silence warning */
BLI_assert(shdr_pos == POS_INDEX);
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
immUniform1i("num_colors", 0); /* "simple" mode */
@@ -1783,7 +1786,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
gpuTranslate3fv(mval);
gpuRotateAxis(-RAD2DEGF(atan2f(cent[0] - tmval[0], cent[1] - tmval[1])), 'Z');
- glLineWidth(3.0f);
+ GPU_line_width(3.0f);
drawArrow(UP, 5, 10, 5);
drawArrow(DOWN, 5, 10, 5);
break;
@@ -1791,7 +1794,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
immUniformThemeColor(TH_VIEW_OVERLAY);
gpuTranslate3fv(mval);
- glLineWidth(3.0f);
+ GPU_line_width(3.0f);
drawArrow(RIGHT, 5, 10, 5);
drawArrow(LEFT, 5, 10, 5);
break;
@@ -1800,7 +1803,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
gpuTranslate3fv(mval);
- glLineWidth(3.0f);
+ GPU_line_width(3.0f);
drawArrow(UP, 5, 10, 5);
drawArrow(DOWN, 5, 10, 5);
break;
@@ -1816,7 +1819,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
gpuTranslate3f(cent[0] - tmval[0] + mval[0], cent[1] - tmval[1] + mval[1], 0);
- glLineWidth(3.0f);
+ GPU_line_width(3.0f);
drawArc(dist, angle - delta_angle, angle - spacing_angle, 10);
drawArc(dist, angle + spacing_angle, angle + delta_angle, 10);
@@ -1842,16 +1845,16 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
gpuTranslate3fv(mval);
- glLineWidth(3.0f);
+ GPU_line_width(3.0f);
UI_make_axis_color(col, col2, 'X');
- immUniformColor3ubv((GLubyte *)col2);
+ immUniformColor3ubv(col2);
drawArrow(RIGHT, 5, 10, 5);
drawArrow(LEFT, 5, 10, 5);
UI_make_axis_color(col, col2, 'Y');
- immUniformColor3ubv((GLubyte *)col2);
+ immUniformColor3ubv(col2);
drawArrow(UP, 5, 10, 5);
drawArrow(DOWN, 5, 10, 5);
@@ -1868,7 +1871,7 @@ static void drawTransformView(const struct bContext *C, ARegion *UNUSED(ar), voi
{
TransInfo *t = arg;
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
drawConstraint(t);
drawPropCircle(C, t);
@@ -1908,15 +1911,15 @@ static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar)
#endif
/* autokey recording icon... */
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
xco -= U.widget_unit;
yco -= (int)printable_size[1] / 2;
UI_icon_draw(xco, yco, ICON_REC);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
static void drawTransformPixel(const struct bContext *UNUSED(C), ARegion *ar, void *arg)
@@ -2116,6 +2119,12 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
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;
@@ -2132,14 +2141,8 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->mode = mode;
- t->launch_event = event ? event->type : -1;
-
- if (t->launch_event == EVT_TWEAK_R) {
- t->launch_event = RIGHTMOUSE;
- }
- else if (t->launch_event == EVT_TWEAK_L) {
- t->launch_event = LEFTMOUSE;
- }
+ /* 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 manipulator only, so assume LEFTMOUSE
@@ -3005,7 +3008,7 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2]))
#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) {
+ 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;
@@ -3126,7 +3129,7 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -3280,7 +3283,7 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -3559,7 +3562,7 @@ static void applyResize(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -3662,7 +3665,7 @@ static void applySkinResize(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -3760,7 +3763,7 @@ static void applyToSphere(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -4119,7 +4122,7 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -4236,7 +4239,7 @@ static void applyTrackball(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -4565,7 +4568,7 @@ static void applyTranslation(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -4667,7 +4670,7 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -4746,7 +4749,7 @@ static void applyTilt(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -4827,7 +4830,7 @@ static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -4933,7 +4936,7 @@ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -5014,7 +5017,7 @@ static void applyGPShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -5109,7 +5112,7 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -5191,7 +5194,7 @@ static void applyBevelWeight(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -5276,7 +5279,7 @@ static void applyCrease(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -5399,7 +5402,7 @@ static void applyBoneSize(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -5476,7 +5479,7 @@ static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -6973,10 +6976,10 @@ static void drawEdgeSlide(TransInfo *t)
const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f;
if (v3d && v3d->zbuf)
- glDisable(GL_DEPTH_TEST);
+ GPU_depth_test(false);
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
gpuPushMatrix();
gpuMultMatrix(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
@@ -6996,7 +6999,7 @@ static void drawEdgeSlide(TransInfo *t)
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]);
- glLineWidth(line_size);
+ GPU_line_width(line_size);
immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
immBeginAtMost(GWN_PRIM_LINES, 4);
if (curr_sv->v_side[0]) {
@@ -7010,7 +7013,7 @@ static void drawEdgeSlide(TransInfo *t)
immEnd();
immUniformThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade);
- glPointSize(ctrl_size);
+ GPU_point_size(ctrl_size);
immBegin(GWN_PRIM_POINTS, 1);
if (slp->flipped) {
if (curr_sv->v_side[1]) immVertex3fv(pos, curr_sv->v_side[1]->co);
@@ -7021,7 +7024,7 @@ static void drawEdgeSlide(TransInfo *t)
immEnd();
immUniformThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade);
- glPointSize(guide_size);
+ GPU_point_size(guide_size);
immBegin(GWN_PRIM_POINTS, 1);
interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac);
immVertex3fv(pos, co_mark);
@@ -7034,7 +7037,7 @@ static void drawEdgeSlide(TransInfo *t)
int i;
const int alpha_shade = -160;
- glLineWidth(line_size);
+ GPU_line_width(line_size);
immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
immBegin(GWN_PRIM_LINES, sld->totsv * 2);
@@ -7069,10 +7072,10 @@ static void drawEdgeSlide(TransInfo *t)
gpuPopMatrix();
- glDisable(GL_BLEND);
+ GPU_blend(false);
if (v3d && v3d->zbuf)
- glEnable(GL_DEPTH_TEST);
+ GPU_depth_test(true);
}
}
}
@@ -7202,7 +7205,7 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -7609,15 +7612,15 @@ static void drawVertSlide(TransInfo *t)
int i;
if (v3d && v3d->zbuf)
- glDisable(GL_DEPTH_TEST);
+ GPU_depth_test(false);
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
gpuPushMatrix();
gpuMultMatrix(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
- glLineWidth(line_size);
+ GPU_line_width(line_size);
const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
@@ -7648,7 +7651,7 @@ static void drawVertSlide(TransInfo *t)
}
immEnd();
- glPointSize(ctrl_size);
+ GPU_point_size(ctrl_size);
immBegin(GWN_PRIM_POINTS, 1);
immVertex3fv(shdr_pos, (slp->flipped && slp->use_even) ?
@@ -7680,12 +7683,12 @@ static void drawVertSlide(TransInfo *t)
add_v3_v3(co_dest_3d, curr_sv->co_orig_3d);
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
immUniform1i("num_colors", 0); /* "simple" mode */
@@ -7704,7 +7707,7 @@ static void drawVertSlide(TransInfo *t)
gpuPopMatrix();
if (v3d && v3d->zbuf)
- glEnable(GL_DEPTH_TEST);
+ GPU_depth_test(true);
}
}
}
@@ -7801,7 +7804,7 @@ static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -7875,7 +7878,7 @@ static void applyBoneRoll(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -7966,7 +7969,7 @@ static void applyBakeTime(TransInfo *t, const int mval[2])
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -8027,7 +8030,7 @@ static void applyMirror(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
else {
size[0] = size[1] = size[2] = 1;
@@ -8050,9 +8053,9 @@ static void applyMirror(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
if (t->flag & T_2D_EDIT)
- ED_area_headerprint(t->sa, IFACE_("Select a mirror axis (X, Y)"));
+ ED_area_status_text(t->sa, IFACE_("Select a mirror axis (X, Y)"));
else
- ED_area_headerprint(t->sa, IFACE_("Select a mirror axis (X, Y, Z)"));
+ ED_area_status_text(t->sa, IFACE_("Select a mirror axis (X, Y, Z)"));
}
}
/** \} */
@@ -8114,7 +8117,7 @@ static void applyAlign(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, IFACE_("Align"));
+ ED_area_status_text(t->sa, IFACE_("Align"));
}
/** \} */
@@ -8213,7 +8216,7 @@ static void applySeqSlide(TransInfo *t, const int mval[2])
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -8497,7 +8500,7 @@ static void applyTimeTranslate(TransInfo *t, const int mval[2])
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -8687,7 +8690,7 @@ static void applyTimeSlide(TransInfo *t, const int mval[2])
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -8808,12 +8811,12 @@ static void applyTimeScale(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-/* TODO, move to: transform_queries.c */
+/* TODO, move to: transform_query.c */
bool checkUseAxisMatrix(TransInfo *t)
{
/* currently only checks for editmode */
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 0982f91f825..744170d9aba 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -65,6 +65,7 @@ struct wmEvent;
struct wmTimer;
struct ARegion;
struct ReportList;
+struct RNG;
struct EditBone;
struct RenderEngineType;
struct SnapObjectContext;
@@ -536,6 +537,9 @@ typedef struct TransInfo {
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;
@@ -551,11 +555,14 @@ typedef struct TransInfo {
/* transinfo->flag */
#define T_OBJECT (1 << 0)
+/** \note We could remove 'T_EDIT' and use 'obedit_type', for now ensure they're in sync. */
#define T_EDIT (1 << 1)
#define T_POSE (1 << 2)
#define T_TEXTURE (1 << 3)
/* transforming the camera while in camera view */
#define T_CAMERA (1 << 4)
+ /* transforming the 3D cursor. */
+#define T_CURSOR (1 << 5)
// trans on points, having no rotation/scale
#define T_POINTS (1 << 6)
/**
@@ -600,6 +607,8 @@ typedef struct TransInfo {
/** #TransInfo.center has been set, don't change it. */
#define T_OVERRIDE_CENTER (1 << 25)
+#define T_MODAL_CURSOR_SET (1 << 26)
+
/* TransInfo->modifiers */
#define MOD_CONSTRAINT_SELECT 0x01
#define MOD_PRECISION 0x02
@@ -717,7 +726,7 @@ 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(int *out_mode, short around, struct Object *ob);
+int count_set_pose_transflags(struct Object *ob, const int mode, const short around, bool has_translate_rotate[2]);
/* auto-keying stuff used by special_aftertrans_update */
void autokeyframe_ob_cb_func(
@@ -843,7 +852,7 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3]);
void calculatePropRatio(TransInfo *t);
-void getViewVector(TransInfo *t, float coord[3], float vec[3]);
+void getViewVector(const TransInfo *t, const float coord[3], float vec[3]);
void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot);
@@ -877,10 +886,9 @@ void freeVertSlideVerts(TransInfo *t, TransDataContainer *tc, TransCustomData *c
void projectVertSlideData(TransInfo *t, bool is_final);
-/* TODO. transform_queries.c */
+/* TODO. transform_query.c */
bool checkUseAxisMatrix(TransInfo *t);
-#define TRANSFORM_DIST_MAX_PX 1000.0f
#define TRANSFORM_SNAP_MAX_PX 100.0f
#define TRANSFORM_DIST_INVALID -FLT_MAX
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index 02cfc9c5e35..7aa1419b0dc 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -44,6 +44,7 @@
#include "GPU_immediate.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -171,7 +172,7 @@ static void postConstraintChecks(TransInfo *t, float vec[3], float pvec[3])
mul_m3_v3(t->con.mtx, vec);
}
-static void viewAxisCorrectCenter(TransInfo *t, float t_con_center[3])
+static void viewAxisCorrectCenter(const TransInfo *t, float t_con_center[3])
{
if (t->spacetype == SPACE_VIEW3D) {
// View3D *v3d = t->sa->spacedata.first;
@@ -195,7 +196,10 @@ static void viewAxisCorrectCenter(TransInfo *t, float t_con_center[3])
}
}
-static void axisProjection(TransInfo *t, const float axis[3], const float in[3], float out[3])
+/**
+ * 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])
{
float norm[3], vec[3], factor, angle;
float t_con_center[3];
@@ -213,12 +217,11 @@ static void axisProjection(TransInfo *t, const float axis[3], const float in[3],
if (angle > (float)M_PI_2) {
angle = (float)M_PI - angle;
}
- angle = RAD2DEGF(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 < 5.0f) {
+ 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 */
@@ -277,7 +280,7 @@ static void axisProjection(TransInfo *t, const float axis[3], const float in[3],
* Return true if the 2x axis are both aligned when projected into the view.
* In this case, we can't usefully project the cursor onto the plane.
*/
-static bool isPlaneProjectionViewAligned(TransInfo *t)
+static bool isPlaneProjectionViewAligned(const TransInfo *t)
{
const float eps = 0.001f;
const float *constraint_vector[2];
@@ -303,7 +306,7 @@ static bool isPlaneProjectionViewAligned(TransInfo *t)
return fabsf(factor) < eps;
}
-static void planeProjection(TransInfo *t, const float in[3], float out[3])
+static void planeProjection(const TransInfo *t, const float in[3], float out[3])
{
float vec[3], factor, norm[3];
@@ -341,8 +344,7 @@ static void applyAxisConstraintVec(
mul_m3_v3(t->con.pmtx, out);
// With snap, a projection is alright, no need to correct for view alignment
- if (!(!ELEM(t->tsnap.mode, SCE_SNAP_MODE_INCREMENT, SCE_SNAP_MODE_GRID) && activeSnap(t))) {
-
+ if (!validSnap(t)) {
const int dims = getConstraintSpaceDimension(t);
if (dims == 2) {
if (!is_zero_v3(out)) {
@@ -558,7 +560,7 @@ static void applyObjectConstraintRot(
/* on setup call, use first object */
if (td == NULL) {
- td = tc->data;
+ td = TRANS_DATA_CONTAINER_FIRST_OK(t)->data;
}
if (t->flag & T_EDIT) {
@@ -741,16 +743,16 @@ void drawConstraint(TransInfo *t)
drawLine(t, t->center_global, tc->mtx[1], 'Y', 0);
drawLine(t, t->center_global, tc->mtx[2], 'Z', 0);
- depth_test_enabled = glIsEnabled(GL_DEPTH_TEST);
+ depth_test_enabled = GPU_depth_test_enabled();
if (depth_test_enabled)
- glDisable(GL_DEPTH_TEST);
+ GPU_depth_test(false);
const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
immUniform1i("num_colors", 0); /* "simple" mode */
@@ -766,7 +768,7 @@ void drawConstraint(TransInfo *t)
immUnbindProgram();
if (depth_test_enabled)
- glEnable(GL_DEPTH_TEST);
+ GPU_depth_test(true);
}
if (tc->mode & CON_AXIS0) {
@@ -817,9 +819,9 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
gpuScale2f(1.0f, (ysize / xsize) * (xmask / ymask));
}
- depth_test_enabled = glIsEnabled(GL_DEPTH_TEST);
+ depth_test_enabled = GPU_depth_test_enabled();
if (depth_test_enabled)
- glDisable(GL_DEPTH_TEST);
+ GPU_depth_test(false);
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
@@ -833,7 +835,7 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
immUnbindProgram();
if (depth_test_enabled)
- glEnable(GL_DEPTH_TEST);
+ GPU_depth_test(true);
gpuPopMatrix();
}
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 7c5f7dba045..c622a50ff11 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -61,7 +61,6 @@
#include "BLI_bitmap.h"
#include "BLI_rect.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_constraint.h"
@@ -303,33 +302,29 @@ static void createTransTexspace(TransInfo *t)
ob = OBACT(view_layer);
if (ob == NULL) { // Shouldn't logically happen, but still...
- t->data_len_all = 0;
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");
- t->data_len_all = 0;
return;
}
if (BKE_object_obdata_is_libdata(ob)) {
BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform");
- t->data_len_all = 0;
return;
}
{
- TransDataContainer *tc = t->data_container = MEM_callocN(sizeof(*t->data_container), __func__);
+ 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");
}
- t->data_len_all = 1;
-
td->flag = TD_SELECTED;
copy_v3_v3(td->center, ob->obmat[3]);
td->ob = ob;
@@ -349,6 +344,43 @@ static void createTransTexspace(TransInfo *t)
copy_v3_v3(td->ext->isize, td->ext->size);
}
+static void createTransCursor3D(TransInfo *t)
+{
+ TransData *td;
+
+ Scene *scene = t->scene;
+ View3D *v3d = ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) ? t->view : NULL;
+ View3DCursor *cursor = ED_view3d_cursor3d_get(scene, v3d);
+
+ if ((cursor == &scene->cursor) && ID_IS_LINKED(scene)) {
+ 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");
+ }
+
+ td->flag = TD_SELECTED;
+ copy_v3_v3(td->center, cursor->location);
+ td->ob = NULL;
+
+ unit_m3(td->mtx);
+ quat_to_mat3(td->axismtx, cursor->rotation);
+ normalize_m3(td->axismtx);
+ pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
+
+ td->loc = cursor->location;
+ copy_v3_v3(td->iloc, cursor->location);
+
+ td->ext->quat = cursor->rotation;
+ copy_qt_qt(td->ext->iquat, cursor->rotation);
+}
+
/* ********************* edge (for crease) ***** */
static void createTransEdge(TransInfo *t)
@@ -715,12 +747,11 @@ static void bone_children_clear_transflag(int mode, short around, ListBase *lb)
/* sets transform flags in the bones
* returns total number of bones with BONE_TRANSFORM */
-int count_set_pose_transflags(int *out_mode, short around, Object *ob)
+int count_set_pose_transflags(Object *ob, const int mode, short around, bool has_translate_rotate[2])
{
bArmature *arm = ob->data;
bPoseChannel *pchan;
Bone *bone;
- int mode = *out_mode;
int total = 0;
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
@@ -748,42 +779,34 @@ int count_set_pose_transflags(int *out_mode, short around, Object *ob)
}
}
/* now count, and check if we have autoIK or have to switch from translate to rotate */
- bool has_translation = false, has_rotation = false;
-
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
bone = pchan->bone;
if (bone->flag & BONE_TRANSFORM) {
total++;
- if (mode == TFM_TRANSLATION) {
+ 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_translation = true;
+ if (pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM) {
+ has_translate_rotate[0] = true;
+ }
}
else {
- if ((pchan->protectflag & OB_LOCK_LOC) != OB_LOCK_LOC)
- has_translation = true;
+ 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;
}
- if ((pchan->protectflag & OB_LOCK_ROT) != OB_LOCK_ROT)
- has_rotation = true;
}
- else
- has_translation = true;
+ else {
+ has_translate_rotate[1] = true;
+ }
}
}
}
- /* if there are no translatable bones, do rotation */
- if (mode == TFM_TRANSLATION && !has_translation) {
- if (has_rotation) {
- *out_mode = TFM_ROTATION;
- }
- else {
- *out_mode = TFM_RESIZE;
- }
- }
-
return total;
}
@@ -827,6 +850,8 @@ static bool pchan_autoik_adjust(bPoseChannel *pchan, short chainlen)
/* 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;
@@ -863,12 +888,12 @@ void transform_autoik_update(TransInfo *t, short mode)
if (changed) {
/* TODO(sergey): Consider doing partial update only. */
- DEG_relations_tag_update(G.main);
+ DEG_relations_tag_update(bmain);
}
}
/* frees temporal IKs */
-static void pose_grab_with_ik_clear(Object *ob)
+static void pose_grab_with_ik_clear(Main *bmain, Object *ob)
{
bKinematicConstraint *data;
bPoseChannel *pchan;
@@ -906,7 +931,7 @@ static void pose_grab_with_ik_clear(Object *ob)
if (relations_changed) {
/* TODO(sergey): Consider doing partial update only. */
- DEG_relations_tag_update(G.main);
+ DEG_relations_tag_update(bmain);
}
}
@@ -1014,7 +1039,7 @@ static short pose_grab_with_ik_children(bPose *pose, Bone *bone)
}
/* main call which adds temporal IK chains */
-static short pose_grab_with_ik(Object *ob)
+static short pose_grab_with_ik(Main *bmain, Object *ob)
{
bArmature *arm;
bPoseChannel *pchan, *parent;
@@ -1060,8 +1085,8 @@ static short pose_grab_with_ik(Object *ob)
/* iTaSC needs clear for new IK constraints */
if (tot_ik) {
BIK_clear_data(ob->pose);
- /* TODO(sergey): Consuder doing partial update only. */
- DEG_relations_tag_update(G.main);
+ /* TODO(sergey): Consider doing partial update only. */
+ DEG_relations_tag_update(bmain);
}
return (tot_ik) ? 1 : 0;
@@ -1084,19 +1109,18 @@ static void createTransPose(TransInfo *t, Object **objects, uint objects_len)
tc->poseobj = objects[th_index];
}
}
+ 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;
- bPoseChannel *pchan;
- TransData *td;
- TransDataExtension *tdx;
short ik_on = 0;
- int i;
-
/* check validity of state */
arm = BKE_armature_from_object(tc->poseobj);
@@ -1113,16 +1137,34 @@ static void createTransPose(TransInfo *t, Object **objects, uint objects_len)
/* do we need to add temporal IK chains? */
if ((arm->flag & ARM_AUTO_IK) && t->mode == TFM_TRANSLATION) {
- ik_on = pose_grab_with_ik(ob);
+ ik_on = pose_grab_with_ik(bmain, ob);
if (ik_on) t->flag |= T_AUTOIK;
}
/* set flags and count total (warning, can change transform to rotate) */
- tc->data_len = count_set_pose_transflags(&t->mode, t->around, ob);
+ tc->data_len = count_set_pose_transflags(ob, t->mode, t->around, has_translate_rotate);
+ /* len may be zero, skip next iteration. */
+ }
+ /* 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 */
@@ -1136,7 +1178,7 @@ static void createTransPose(TransInfo *t, Object **objects, uint objects_len)
/* use pose channels to fill trans data */
td = tc->data;
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ 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++;
@@ -1212,7 +1254,7 @@ static void createTransArmatureVerts(TransInfo *t)
bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0);
int total_mirrored = 0, i;
int oldtot;
- BoneInitData *bid;
+ BoneInitData *bid = NULL;
tc->data_len = 0;
for (ebo = edbo->first; ebo; ebo = ebo->next) {
@@ -2023,7 +2065,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
if (!(point->flag & PEP_TRANSFORM)) continue;
if (psys && !(psys->flag & PSYS_GLOBAL_HAIR))
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles + i, mat);
+ psys_mat_hair_to_global(ob, psmd->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) {
@@ -2077,7 +2119,6 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
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);
@@ -2101,7 +2142,7 @@ void flushTransParticles(TransInfo *t)
if (!(point->flag & PEP_TRANSFORM)) continue;
if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles + i, mat);
+ psys_mat_hair_to_global(ob, psmd->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++) {
@@ -5736,8 +5777,7 @@ static void trans_object_base_deps_flag_finish(ViewLayer *view_layer)
/* it deselects Bases, so we have to call the clear function always after */
static void set_trans_object_base_flags(TransInfo *t)
{
- /* TODO(sergey): Get rid of global, use explicit main. */
- Main *bmain = G.main;
+ Main *bmain = CTX_data_main(t->context);
ViewLayer *view_layer = t->view_layer;
Scene *scene = t->scene;
Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
@@ -5883,11 +5923,13 @@ 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_ob_cb_func(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);
@@ -5914,7 +5956,7 @@ void autokeyframe_ob_cb_func(bContext *C, Scene *scene, ViewLayer *view_layer, O
if (adt && adt->action) {
for (fcu = adt->action->curves.first; fcu; fcu = fcu->next) {
fcu->flag &= ~FCURVE_SELECTED;
- insert_keyframe(reports, id, adt->action,
+ insert_keyframe(bmain, depsgraph, reports, id, adt->action,
(fcu->grp ? fcu->grp->name : NULL),
fcu->rna_path, fcu->array_index, cfra,
ts->keyframe_type, flag);
@@ -6003,6 +6045,7 @@ void autokeyframe_ob_cb_func(bContext *C, Scene *scene, ViewLayer *view_layer, O
// 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_cb_func(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;
@@ -6012,6 +6055,7 @@ void autokeyframe_pose_cb_func(bContext *C, Scene *scene, Object *ob, int tmode,
// 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);
@@ -6055,7 +6099,7 @@ void autokeyframe_pose_cb_func(bContext *C, Scene *scene, Object *ob, int tmode,
* NOTE: this will do constraints too, but those are ok to do here too?
*/
if (pchanName && STREQ(pchanName, pchan->name)) {
- insert_keyframe(reports, id, act,
+ insert_keyframe(bmain, depsgraph, reports, id, act,
((fcu->grp) ? (fcu->grp->name) : (NULL)),
fcu->rna_path, fcu->array_index, cfra,
ts->keyframe_type, flag);
@@ -6285,6 +6329,9 @@ 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);
@@ -6380,7 +6427,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
if (canceled == 0) {
ED_node_post_apply_transform(C, snode->edittree);
- ED_node_link_insert(t->sa);
+ ED_node_link_insert(bmain, t->sa);
}
/* clear link line */
@@ -6473,7 +6520,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
// XXX: BAD! this get gpencil datablocks directly from main db...
// but that's how this currently works :/
- for (gpd = G.main->gpencil.first; gpd; gpd = gpd->id.next) {
+ for (gpd = bmain->gpencil.first; gpd; gpd = gpd->id.next) {
if (ID_REAL_USERS(gpd))
posttrans_gpd_clean(gpd);
}
@@ -6493,7 +6540,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
// XXX: BAD! this get gpencil datablocks directly from main db...
// but that's how this currently works :/
- for (mask = G.main->mask.first; mask; mask = mask->id.next) {
+ for (mask = bmain->mask.first; mask; mask = mask->id.next) {
if (ID_REAL_USERS(mask))
posttrans_mask_clean(mask);
}
@@ -6642,8 +6689,9 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
}
/* set BONE_TRANSFORM flags for autokey, manipulator draw might have changed them */
- if (!canceled && (t->mode != TFM_DUMMY))
- count_set_pose_transflags(&t->mode, t->around, ob);
+ 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)
@@ -6657,7 +6705,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
}
if (t->mode == TFM_TRANSLATION)
- pose_grab_with_ik_clear(ob);
+ 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)) {
@@ -6687,6 +6735,9 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
{
/* do nothing */
}
+ else if (t->flag & T_CURSOR) {
+ /* do nothing */
+ }
else { /* Objects */
int i;
@@ -8319,8 +8370,16 @@ void createTransData(bContext *C, TransInfo *t)
t->data_len_all = -1;
/* if tests must match recalcData for correct updates */
- if (t->options & CTX_TEXTURE) {
+ if (t->options & CTX_CURSOR) {
+ t->flag |= T_CURSOR;
+ t->obedit_type = -1;
+
+ createTransCursor3D(t);
+ countAndCleanTransDataContainer(t);
+ }
+ else if (t->options & CTX_TEXTURE) {
t->flag |= T_TEXTURE;
+ t->obedit_type = -1;
createTransTexspace(t);
countAndCleanTransDataContainer(t);
@@ -8392,6 +8451,7 @@ void createTransData(bContext *C, TransInfo *t)
}
else if (t->spacetype == SPACE_ACTION) {
t->flag |= T_POINTS | T_2D_EDIT;
+ t->obedit_type = -1;
createTransActionData(C, t);
countAndCleanTransDataContainer(t);
@@ -8404,17 +8464,23 @@ void createTransData(bContext *C, TransInfo *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 transformations */
createTransSeqData(C, t);
countAndCleanTransDataContainer(t);
}
else if (t->spacetype == SPACE_IPO) {
t->flag |= T_POINTS | T_2D_EDIT;
+ t->obedit_type = -1;
+
createTransGraphEditData(C, t);
countAndCleanTransDataContainer(t);
@@ -8426,6 +8492,7 @@ void createTransData(bContext *C, TransInfo *t)
}
else if (t->spacetype == SPACE_NODE) {
t->flag |= T_POINTS | T_2D_EDIT;
+ t->obedit_type = -1;
createTransNodeData(C, t);
countAndCleanTransDataContainer(t);
@@ -8438,6 +8505,8 @@ void createTransData(bContext *C, TransInfo *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);
@@ -8507,6 +8576,7 @@ void createTransData(bContext *C, TransInfo *t)
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;
@@ -8538,7 +8608,10 @@ void createTransData(bContext *C, TransInfo *t)
countAndCleanTransDataContainer(t);
}
}
-
+ }
+ /* Mark as initialized if above checks fail. */
+ if (t->data_len_all == -1) {
+ t->data_len_all = 0;
}
}
else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) && PE_start_edit(PE_get_current(scene, ob))) {
@@ -8558,6 +8631,10 @@ void createTransData(bContext *C, TransInfo *t)
createTransPaintCurveVerts(C, t);
countAndCleanTransDataContainer(t);
}
+ /* Mark as initialized if above checks fail. */
+ if (t->data_len_all == -1) {
+ t->data_len_all = 0;
+ }
}
else {
createTransObject(C, t);
@@ -8585,4 +8662,6 @@ void createTransData(bContext *C, TransInfo *t)
/* Check that 'countAndCleanTransDataContainer' ran. */
BLI_assert(t->data_len_all != -1);
+
+ 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 ed146eb3227..db8bbe05c69 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -58,6 +58,8 @@
#include "BLI_rand.h"
#include "BLI_utildefines.h"
+#include "PIL_time.h"
+
#include "BLT_translation.h"
#include "RNA_access.h"
@@ -74,6 +76,7 @@
#include "BKE_fcurve.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
+#include "BKE_main.h"
#include "BKE_nla.h"
#include "BKE_context.h"
#include "BKE_paint.h"
@@ -115,7 +118,7 @@
/* ************************** Functions *************************** */
-void getViewVector(TransInfo *t, float coord[3], float vec[3])
+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]);
@@ -359,6 +362,7 @@ static void recalcData_actedit(TransInfo *t)
/* 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);
@@ -386,7 +390,7 @@ static void recalcData_actedit(TransInfo *t)
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(t->scene, ale);
+ ANIM_list_elem_update(CTX_data_main(t->context), t->scene, ale);
}
}
@@ -409,6 +413,7 @@ static void recalcData_graphedit(TransInfo *t)
/* 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);
@@ -445,7 +450,7 @@ static void recalcData_graphedit(TransInfo *t)
* BUT only if realtime updates are enabled
*/
if ((sipo->flag & SIPO_NOREALTIMEUPDATES) == 0)
- ANIM_list_elem_update(t->scene, ale);
+ ANIM_list_elem_update(CTX_data_main(t->context), t->scene, ale);
}
/* do resort and other updates? */
@@ -1007,6 +1012,11 @@ static void recalcData_objects(TransInfo *t)
}
}
+static void recalcData_cursor(TransInfo *t)
+{
+ DEG_id_tag_update(&t->scene->id, DEG_TAG_COPY_ON_WRITE);
+}
+
/* helper for recalcData() - for sequencer transforms */
static void recalcData_sequencer(TransInfo *t)
{
@@ -1056,7 +1066,10 @@ static void recalcData_gpencil_strokes(TransInfo *t)
void recalcData(TransInfo *t)
{
/* if tests must match createTransData for correct updates */
- if (t->options & CTX_TEXTURE) {
+ if (t->options & CTX_CURSOR) {
+ recalcData_cursor(t);
+ }
+ else if (t->options & CTX_TEXTURE) {
recalcData_objects(t);
}
else if (t->options & CTX_EDGE) {
@@ -1323,9 +1336,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
prop_id = "use_even_offset";
}
- if (prop_id && (prop = RNA_struct_find_property(op->ptr, prop_id)) &&
- RNA_property_is_set(op->ptr, prop))
- {
+ 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);
}
}
@@ -1629,6 +1640,10 @@ void postTrans(bContext *C, TransInfo *t)
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) {
@@ -1683,6 +1698,10 @@ void postTrans(bContext *C, TransInfo *t)
MEM_freeN(t->mouse.data);
}
+ if (t->rng != NULL) {
+ BLI_rng_free(t->rng);
+ }
+
freeSnapping(t);
}
@@ -1944,7 +1963,7 @@ bool calculateCenterActive(TransInfo *t, 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);
- mul_m4_v3(tc->obedit->obmat, r_center);
+ mul_m4_v3(ob->obmat, r_center);
ok = true;
}
}
@@ -2151,7 +2170,12 @@ void calculatePropRatio(TransInfo *t)
td->factor = sqrtf(2 * dist - dist * dist);
break;
case PROP_RANDOM:
- td->factor = BLI_frand() * dist;
+ 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);
@@ -2312,4 +2336,3 @@ void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot)
copy_v3_v3(td->ext->rot, eul);
}
}
-
diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c
index 2004bba4f09..5b5c4902377 100644
--- a/source/blender/editors/transform/transform_input.c
+++ b/source/blender/editors/transform/transform_input.c
@@ -351,7 +351,8 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode)
case HLP_NONE:
/* INPUT_VECTOR, INPUT_CUSTOM_RATIO, INPUT_CUSTOM_RATIO_FLIP */
if (t->flag & T_MODAL) {
- WM_cursor_set(win, BC_NSEW_SCROLLCURSOR);
+ t->flag |= T_MODAL_CURSOR_SET;
+ WM_cursor_modal_set(win, BC_NSEW_SCROLLCURSOR);
}
break;
case HLP_SPRING:
@@ -360,7 +361,8 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode)
case HLP_HARROW:
case HLP_VARROW:
if (t->flag & T_MODAL) {
- WM_cursor_set(win, CURSOR_NONE);
+ t->flag |= T_MODAL_CURSOR_SET;
+ WM_cursor_modal_set(win, CURSOR_NONE);
}
break;
default:
@@ -373,8 +375,11 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode)
MEM_freeN(mi_data_prev);
}
- /* bootstrap mouse input with initial values */
- applyMouseInput(t, mi, mi->imval, t->values);
+ /* Don't write into the values when non-modal because they are already set from operator redo values. */
+ if (t->flag & T_MODAL) {
+ /* bootstrap mouse input with initial values */
+ applyMouseInput(t, mi, mi->imval, t->values);
+ }
}
void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float values[3]))
diff --git a/source/blender/editors/transform/transform_manipulator_3d.c b/source/blender/editors/transform/transform_manipulator_3d.c
index 8257ad595d7..f584a7cf623 100644
--- a/source/blender/editors/transform/transform_manipulator_3d.c
+++ b/source/blender/editors/transform/transform_manipulator_3d.c
@@ -65,6 +65,7 @@
#include "WM_api.h"
#include "WM_types.h"
#include "WM_message.h"
+#include "WM_toolsystem.h"
#include "ED_armature.h"
#include "ED_curve.h"
@@ -106,8 +107,15 @@
#define MAN_SCALE_C (MAN_SCALE_X | MAN_SCALE_Y | MAN_SCALE_Z)
/* threshold for testing view aligned manipulator axis */
-#define TW_AXIS_DOT_MIN 0.02f
-#define TW_AXIS_DOT_MAX 0.1f
+struct {
+ 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},
+};
/* axes as index */
enum {
@@ -151,18 +159,15 @@ enum {
MAN_AXES_SCALE,
};
-/* naming from old blender we may combine. */
-enum {
- V3D_MANIP_TRANSLATE = 1,
- V3D_MANIP_ROTATE = 2,
- V3D_MANIP_SCALE = 4,
-};
-
-
typedef struct ManipulatorGroup {
bool all_hidden;
int twtype;
+ /* Users may change the twtype, detect changes to re-setup manipulator options. */
+ int twtype_init;
+ int twtype_prev;
+ int use_twtype_refresh;
+
struct wmManipulator *manipulators[MAN_AXIS_LAST];
} ManipulatorGroup;
@@ -246,22 +251,24 @@ static bool manipulator_is_axis_visible(
const RegionView3D *rv3d, const int twtype,
const float idot[3], const int axis_type, const int axis_idx)
{
- bool is_plane = false;
- const uint aidx_norm = manipulator_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 < TW_AXIS_DOT_MIN) {
- 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 = manipulator_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_MANIP_TRANSLATE)) ||
- (axis_type == MAN_AXES_ROTATE && !(twtype & V3D_MANIP_ROTATE)) ||
- (axis_type == MAN_AXES_SCALE && !(twtype & V3D_MANIP_SCALE)))
+ if ((axis_type == MAN_AXES_TRANSLATE && !(twtype & SCE_MANIP_TRANSLATE)) ||
+ (axis_type == MAN_AXES_ROTATE && !(twtype & SCE_MANIP_ROTATE)) ||
+ (axis_type == MAN_AXES_SCALE && !(twtype & SCE_MANIP_SCALE)))
{
return false;
}
@@ -291,34 +298,34 @@ static bool manipulator_is_axis_visible(
case MAN_AXIS_SCALE_Z:
return (rv3d->twdrawflag & MAN_SCALE_Z);
case MAN_AXIS_SCALE_C:
- return (rv3d->twdrawflag & MAN_SCALE_C && (twtype & V3D_MANIP_TRANSLATE) == 0);
+ return (rv3d->twdrawflag & MAN_SCALE_C && (twtype & SCE_MANIP_TRANSLATE) == 0);
case MAN_AXIS_TRANS_XY:
return (rv3d->twdrawflag & MAN_TRANS_X &&
rv3d->twdrawflag & MAN_TRANS_Y &&
- (twtype & V3D_MANIP_ROTATE) == 0);
+ (twtype & SCE_MANIP_ROTATE) == 0);
case MAN_AXIS_TRANS_YZ:
return (rv3d->twdrawflag & MAN_TRANS_Y &&
rv3d->twdrawflag & MAN_TRANS_Z &&
- (twtype & V3D_MANIP_ROTATE) == 0);
+ (twtype & SCE_MANIP_ROTATE) == 0);
case MAN_AXIS_TRANS_ZX:
return (rv3d->twdrawflag & MAN_TRANS_Z &&
rv3d->twdrawflag & MAN_TRANS_X &&
- (twtype & V3D_MANIP_ROTATE) == 0);
+ (twtype & SCE_MANIP_ROTATE) == 0);
case MAN_AXIS_SCALE_XY:
return (rv3d->twdrawflag & MAN_SCALE_X &&
rv3d->twdrawflag & MAN_SCALE_Y &&
- (twtype & V3D_MANIP_TRANSLATE) == 0 &&
- (twtype & V3D_MANIP_ROTATE) == 0);
+ (twtype & SCE_MANIP_TRANSLATE) == 0 &&
+ (twtype & SCE_MANIP_ROTATE) == 0);
case MAN_AXIS_SCALE_YZ:
return (rv3d->twdrawflag & MAN_SCALE_Y &&
rv3d->twdrawflag & MAN_SCALE_Z &&
- (twtype & V3D_MANIP_TRANSLATE) == 0 &&
- (twtype & V3D_MANIP_ROTATE) == 0);
+ (twtype & SCE_MANIP_TRANSLATE) == 0 &&
+ (twtype & SCE_MANIP_ROTATE) == 0);
case MAN_AXIS_SCALE_ZX:
return (rv3d->twdrawflag & MAN_SCALE_Z &&
rv3d->twdrawflag & MAN_SCALE_X &&
- (twtype & V3D_MANIP_TRANSLATE) == 0 &&
- (twtype & V3D_MANIP_ROTATE) == 0);
+ (twtype & SCE_MANIP_TRANSLATE) == 0 &&
+ (twtype & SCE_MANIP_ROTATE) == 0);
}
return false;
}
@@ -332,22 +339,31 @@ static void manipulator_get_axis_color(
const float alpha_hi = 1.0f;
float alpha_fac;
- bool is_plane = false;
- const int axis_idx_norm = manipulator_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) {
- float idot_axis = idot[axis_idx_norm];
- if (is_plane) {
- idot_axis = 1.0f - idot_axis;
- }
- alpha_fac = (idot_axis > TW_AXIS_DOT_MAX) ?
- 1.0f : (idot_axis < TW_AXIS_DOT_MIN) ?
- 0.0f : ((idot_axis - TW_AXIS_DOT_MIN) / (TW_AXIS_DOT_MAX - TW_AXIS_DOT_MIN));
- }
- else {
+ 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 = manipulator_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:
@@ -585,7 +601,6 @@ int ED_transform_calc_manipulator_stats(
const struct TransformCalcParams *params,
struct TransformBounds *tbounds)
{
- const Depsgraph *depsgraph = CTX_data_depsgraph(C);
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
@@ -595,8 +610,6 @@ int ED_transform_calc_manipulator_stats(
RegionView3D *rv3d = ar->regiondata;
Base *base;
Object *ob = OBACT(view_layer);
- const Object *ob_eval = NULL;
- const Object *obedit_eval = NULL;
bGPdata *gpd = CTX_data_gpencil_data(C);
const bool is_gp_edit = ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE));
int a, totsel = 0;
@@ -611,9 +624,6 @@ int ED_transform_calc_manipulator_stats(
rv3d->twdrawflag = 0xFFFF;
- ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- obedit_eval = DEG_get_evaluated_object(depsgraph, obedit);
-
/* global, local or normal orientation?
* if we could check 'totsel' now, this should be skipped with no selection. */
if (ob && !is_gp_edit) {
@@ -658,7 +668,7 @@ int ED_transform_calc_manipulator_stats(
copy_m4_m3(rv3d->twmat, mat);
break;
}
- copy_m4_m4(rv3d->twmat, ob_eval->obmat);
+ copy_m4_m4(rv3d->twmat, ob->obmat);
normalize_m4(rv3d->twmat);
break;
}
@@ -698,7 +708,7 @@ int ED_transform_calc_manipulator_stats(
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_eval->obmat);
+ copy_m3_m4(diff_mat, ob->obmat);
normalize_m3(diff_mat);
invert_m3(diff_mat);
mul_m3_m3m3(tbounds->axis, tbounds->axis, diff_mat);
@@ -761,7 +771,6 @@ int ED_transform_calc_manipulator_stats(
}
else if (obedit) {
ob = obedit;
- ob_eval = obedit_eval;
if (obedit->type == OB_MESH) {
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMEditSelection ese;
@@ -936,9 +945,9 @@ int ED_transform_calc_manipulator_stats(
/* selection center */
if (totsel) {
mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid!
- mul_m4_v3(obedit_eval->obmat, tbounds->center);
- mul_m4_v3(obedit_eval->obmat, tbounds->min);
- mul_m4_v3(obedit_eval->obmat, tbounds->max);
+ 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)) {
@@ -957,7 +966,7 @@ int ED_transform_calc_manipulator_stats(
}
}
else {
- totsel = count_set_pose_transflags(&mode, 0, ob);
+ totsel = count_set_pose_transflags(ob, mode, V3D_AROUND_CENTER_BOUNDS, NULL);
if (totsel) {
/* use channels to get stats */
@@ -974,9 +983,9 @@ int ED_transform_calc_manipulator_stats(
if (ok) {
mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid!
- mul_m4_v3(ob_eval->obmat, tbounds->center);
- mul_m4_v3(ob_eval->obmat, tbounds->min);
- mul_m4_v3(ob_eval->obmat, tbounds->max);
+ 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)) {
@@ -1017,18 +1026,16 @@ int ED_transform_calc_manipulator_stats(
if (!TESTBASELIB(base)) {
continue;
}
- const Object *base_object_eval = DEG_get_evaluated_object(depsgraph, base->object);
if (ob == NULL) {
ob = base->object;
- ob_eval = base_object_eval;
}
- if (params->use_only_center || base_object_eval->bb == NULL) {
- calc_tw_center(tbounds, base_object_eval->obmat[3]);
+ if (params->use_only_center || base->object->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_eval->obmat, base_object_eval->bb->vec[j]);
+ mul_v3_m4v3(co, base->object->obmat, base->object->bb->vec[j]);
calc_tw_center(tbounds, co);
}
}
@@ -1112,15 +1119,15 @@ static void manipulator_line_range(const int twtype, const short axis_type, floa
switch (axis_type) {
case MAN_AXES_TRANSLATE:
- if (twtype & V3D_MANIP_SCALE) {
+ if (twtype & SCE_MANIP_SCALE) {
*r_start = *r_len - ofs + 0.075f;
}
- if (twtype & V3D_MANIP_ROTATE) {
+ if (twtype & SCE_MANIP_ROTATE) {
*r_len += ofs;
}
break;
case MAN_AXES_SCALE:
- if (twtype & (V3D_MANIP_TRANSLATE | V3D_MANIP_ROTATE)) {
+ if (twtype & (SCE_MANIP_TRANSLATE | SCE_MANIP_ROTATE)) {
*r_len -= ofs + 0.025f;
}
break;
@@ -1131,7 +1138,7 @@ static void manipulator_line_range(const int twtype, const short axis_type, floa
static void manipulator_xform_message_subscribe(
wmManipulatorGroup *mgroup, struct wmMsgBus *mbus,
- Scene *scene, bScreen *screen, ScrArea *sa, ARegion *ar, const void *type_fn)
+ Scene *scene, bScreen *UNUSED(screen), ScrArea *UNUSED(sa), ARegion *ar, const void *type_fn)
{
/* Subscribe to view properties */
wmMsgSubscribeValue msg_sub_value_mpr_tag_refresh = {
@@ -1157,16 +1164,18 @@ static void manipulator_xform_message_subscribe(
}
}
- PointerRNA space_ptr;
- RNA_pointer_create(&screen->id, &RNA_SpaceView3D, sa->spacedata.first, &space_ptr);
+ PointerRNA toolsettings_ptr;
+ RNA_pointer_create(&scene->id, &RNA_ToolSettings, scene->toolsettings, &toolsettings_ptr);
if (type_fn == TRANSFORM_WGT_manipulator) {
extern PropertyRNA rna_ToolSettings_transform_pivot_point;
+ extern PropertyRNA rna_ToolSettings_use_manipulator_mode;
const PropertyRNA *props[] = {
- &rna_ToolSettings_transform_pivot_point
+ &rna_ToolSettings_transform_pivot_point,
+ &rna_ToolSettings_use_manipulator_mode,
};
for (int i = 0; i < ARRAY_SIZE(props); i++) {
- WM_msg_subscribe_rna(mbus, &space_ptr, props[i], &msg_sub_value_mpr_tag_refresh, __func__);
+ WM_msg_subscribe_rna(mbus, &toolsettings_ptr, props[i], &msg_sub_value_mpr_tag_refresh, __func__);
}
}
else if (type_fn == VIEW3D_WGT_xform_cage) {
@@ -1246,9 +1255,14 @@ static ManipulatorGroup *manipulatorgroup_init(wmManipulatorGroup *mgroup)
* Custom handler for manipulator widgets
*/
static int manipulator_modal(
- bContext *C, wmManipulator *widget, const wmEvent *UNUSED(event),
+ bContext *C, wmManipulator *widget, const wmEvent *event,
eWM_ManipulatorTweak UNUSED(tweak_flag))
{
+ /* Avoid unnecessary updates, partially address: T55458. */
+ if (ELEM(event->type, TIMER, INBETWEEN_MOUSEMOVE)) {
+ return OPERATOR_RUNNING_MODAL;
+ }
+
const ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
View3D *v3d = sa->spacedata.first;
@@ -1270,41 +1284,12 @@ static int manipulator_modal(
return OPERATOR_RUNNING_MODAL;
}
-static void WIDGETGROUP_manipulator_setup(const bContext *C, wmManipulatorGroup *mgroup)
+static void manipulatorgroup_init_properties_from_twtype(wmManipulatorGroup *mgroup)
{
- ManipulatorGroup *man = manipulatorgroup_init(mgroup);
struct {
wmOperatorType *translate, *rotate, *trackball, *resize;
} ot_store = {NULL};
-
- mgroup->customdata = man;
-
- {
- /* TODO: support mixing modes again? - it's supported but tool system makes it unobvious. */
- man->twtype = 0;
- WorkSpace *workspace = CTX_wm_workspace(C);
- ScrArea *sa = CTX_wm_area(C);
- wmKeyMap *km = WM_keymap_find_all(C, workspace->tool.keymap, sa->spacetype, RGN_TYPE_WINDOW);
- /* Weak, check first event */
- wmKeyMapItem *kmi = km ? km->items.first : NULL;
-
- if (kmi == NULL) {
- man->twtype |= V3D_MANIP_TRANSLATE | V3D_MANIP_ROTATE | V3D_MANIP_SCALE;
- }
- else if (STREQ(kmi->idname, "TRANSFORM_OT_translate")) {
- man->twtype |= V3D_MANIP_TRANSLATE;
- }
- else if (STREQ(kmi->idname, "TRANSFORM_OT_rotate")) {
- man->twtype |= V3D_MANIP_ROTATE;
- }
- else if (STREQ(kmi->idname, "TRANSFORM_OT_resize")) {
- man->twtype |= V3D_MANIP_SCALE;
- }
- BLI_assert(man->twtype != 0);
- }
-
- /* *** set properties for axes *** */
-
+ ManipulatorGroup *man = mgroup->customdata;
MAN_ITER_AXES_BEGIN(axis, axis_idx)
{
const short axis_type = manipulator_get_axis_type(axis_idx);
@@ -1323,6 +1308,14 @@ static void WIDGETGROUP_manipulator_setup(const bContext *C, wmManipulatorGroup
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 ((man->twtype & (SCE_MANIP_ROTATE | SCE_MANIP_SCALE)) == 0) {
+ draw_options |= ED_MANIPULATOR_ARROW_DRAW_FLAG_STEM;
+ }
+ RNA_enum_set(axis->ptr, "draw_options", draw_options);
+ }
+
WM_manipulator_set_line_width(axis, MANIPULATOR_AXIS_LINE_WIDTH);
break;
case MAN_AXIS_ROT_X:
@@ -1356,6 +1349,7 @@ static void WIDGETGROUP_manipulator_setup(const bContext *C, wmManipulatorGroup
}
else if (axis_idx == MAN_AXIS_ROT_C) {
WM_manipulator_set_flag(axis, WM_MANIPULATOR_DRAW_VALUE, true);
+ WM_manipulator_set_scale(axis, 1.2f);
}
else {
WM_manipulator_set_scale(axis, 0.2f);
@@ -1410,6 +1404,39 @@ static void WIDGETGROUP_manipulator_setup(const bContext *C, wmManipulatorGroup
MAN_ITER_AXES_END;
}
+static void WIDGETGROUP_manipulator_setup(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ ManipulatorGroup *man = manipulatorgroup_init(mgroup);
+
+ mgroup->customdata = man;
+
+ {
+ man->twtype = 0;
+ ScrArea *sa = CTX_wm_area(C);
+ const bToolRef *tref = sa->runtime.tool;
+
+ if (tref == NULL || STREQ(tref->idname, "Transform")) {
+ /* Setup all manipulators, they can be toggled via 'ToolSettings.manipulator_flag' */
+ man->twtype = SCE_MANIP_TRANSLATE | SCE_MANIP_ROTATE | SCE_MANIP_SCALE;
+ man->use_twtype_refresh = true;
+ }
+ else if (STREQ(tref->idname, "Move")) {
+ man->twtype |= SCE_MANIP_TRANSLATE;
+ }
+ else if (STREQ(tref->idname, "Rotate")) {
+ man->twtype |= SCE_MANIP_ROTATE;
+ }
+ else if (STREQ(tref->idname, "Scale")) {
+ man->twtype |= SCE_MANIP_SCALE;
+ }
+ BLI_assert(man->twtype != 0);
+ man->twtype_init = man->twtype;
+ }
+
+ /* *** set properties for axes *** */
+ manipulatorgroup_init_properties_from_twtype(mgroup);
+}
+
static void WIDGETGROUP_manipulator_refresh(const bContext *C, wmManipulatorGroup *mgroup)
{
ManipulatorGroup *man = mgroup->customdata;
@@ -1419,6 +1446,15 @@ static void WIDGETGROUP_manipulator_refresh(const bContext *C, wmManipulatorGrou
RegionView3D *rv3d = ar->regiondata;
struct TransformBounds tbounds;
+ if (man->use_twtype_refresh) {
+ Scene *scene = CTX_data_scene(C);
+ man->twtype = scene->toolsettings->manipulator_flag & man->twtype_init;
+ if (man->twtype != man->twtype_prev) {
+ man->twtype_prev = man->twtype;
+ manipulatorgroup_init_properties_from_twtype(mgroup);
+ }
+ }
+
/* skip, we don't draw anything anyway */
if ((man->all_hidden =
(ED_transform_calc_manipulator_stats(
@@ -1455,6 +1491,13 @@ static void WIDGETGROUP_manipulator_refresh(const bContext *C, wmManipulatorGrou
WM_manipulator_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 (man->twtype & SCE_MANIP_ROTATE) {
+ /* Avoid rotate and translate arrows overlap. */
+ start_co[2] += 0.215f;
+ }
+ }
WM_manipulator_set_matrix_offset_location(axis, start_co);
WM_manipulator_set_flag(axis, WM_MANIPULATOR_DRAW_OFFSET_SCALE, true);
break;
@@ -1546,14 +1589,10 @@ static void WIDGETGROUP_manipulator_draw_prepare(const bContext *C, wmManipulato
static bool WIDGETGROUP_manipulator_poll(const struct bContext *C, struct wmManipulatorGroupType *wgt)
{
/* it's a given we only use this in 3D view */
- ScrArea *sa = CTX_wm_area(C);
- View3D *v3d = sa->spacedata.first;
- if (v3d && ((v3d->twflag & V3D_MANIPULATOR_DRAW)) == 0) {
- return false;
- }
-
- WorkSpace *workspace = CTX_wm_workspace(C);
- if (!STREQ(workspace->tool.manipulator_group, "TRANSFORM_WGT_manipulator")) {
+ bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C);
+ if ((tref_rt == NULL) ||
+ !STREQ(wgt->idname, tref_rt->manipulator_group))
+ {
WM_manipulator_group_type_unlink_delayed_ptr(wgt);
return false;
}
@@ -1590,14 +1629,8 @@ struct XFormCageWidgetGroup {
static bool WIDGETGROUP_xform_cage_poll(const bContext *C, wmManipulatorGroupType *wgt)
{
- ScrArea *sa = CTX_wm_area(C);
- View3D *v3d = sa->spacedata.first;
- if (v3d && ((v3d->twflag & V3D_MANIPULATOR_DRAW)) == 0) {
- return false;
- }
-
- WorkSpace *workspace = CTX_wm_workspace(C);
- if (!STREQ(wgt->idname, workspace->tool.manipulator_group)) {
+ bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C);
+ if (!STREQ(wgt->idname, tref_rt->manipulator_group)) {
WM_manipulator_group_type_unlink_delayed_ptr(wgt);
return false;
}
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 36c444a0ca3..61a82d26b2b 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -45,6 +45,7 @@
#include "RNA_enum_types.h"
#include "WM_api.h"
+#include "WM_message.h"
#include "WM_types.h"
#include "UI_interface.h"
@@ -167,6 +168,9 @@ static int select_orientation_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ WM_msg_publish_rna_prop(mbus, &scene->id, scene, Scene, transform_orientation);
+
return OPERATOR_FINISHED;
}
@@ -534,7 +538,7 @@ void Transform_Properties(struct wmOperatorType *ot, int flags)
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 Editing Falloff", "Falloff type for proportional editing mode");
+ "Proportional Falloff", "Falloff type for proportional editing mode");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
RNA_def_float(ot->srna, "proportional_size", 1, T_PROP_SIZE_MIN, T_PROP_SIZE_MAX,
"Proportional Size", "", 0.001f, 100.0f);
@@ -560,17 +564,24 @@ void Transform_Properties(struct wmOperatorType *ot, int flags)
}
if (flags & P_GPENCIL_EDIT) {
- RNA_def_boolean(ot->srna, "gpencil_strokes", 0, "Edit Grease Pencil", "Edit selected Grease Pencil strokes");
+ 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)) {
- RNA_def_boolean(ot->srna, "texture_space", 0, "Edit Texture Space", "Edit Object data texture space");
+ 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);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
if (flags & P_CORRECT_UV) {
- RNA_def_boolean(ot->srna, "correct_uv", 0, "Correct UVs", "Correct UV coordinates when transforming");
+ RNA_def_boolean(ot->srna, "correct_uv", true, "Correct UVs", "Correct UV coordinates when transforming");
}
if (flags & P_CENTER) {
@@ -609,7 +620,10 @@ static void TRANSFORM_OT_translate(struct wmOperatorType *ot)
WM_operatortype_props_advanced_begin(ot);
- Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP | P_OPTIONS | P_GPENCIL_EDIT);
+ Transform_Properties(
+ ot,
+ 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)
@@ -1107,17 +1121,16 @@ void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spac
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", TABKEY, KM_PRESS, KM_SHIFT, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_snap");
- kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", TABKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
- RNA_string_set(kmi->ptr, "data_path", "tool_settings.snap_element");
-
/* Will fall-through to texture-space transform. */
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_transform_axis_target", TKEY, KM_PRESS, KM_SHIFT, 0);
+#ifdef USE_WM_KEYMAP_27X
kmi = WM_keymap_add_item(keymap, OP_TRANSLATION, TKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "texture_space", true);
kmi = WM_keymap_add_item(keymap, OP_RESIZE, TKEY, KM_PRESS, KM_SHIFT | KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "texture_space", true);
+#endif
WM_keymap_add_item(keymap, OP_SKIN_RESIZE, AKEY, KM_PRESS, KM_CTRL, 0);
@@ -1229,4 +1242,3 @@ void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spac
break;
}
}
-
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 681f955087a..48ec664d634 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -50,8 +50,8 @@
#include "BLI_utildefines.h"
#include "GPU_immediate.h"
+#include "GPU_state.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
#include "BKE_object.h"
#include "BKE_anim.h" /* for duplis */
@@ -160,7 +160,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
float imat[4][4];
float size;
- glDisable(GL_DEPTH_TEST);
+ GPU_depth_test(false);
size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
@@ -202,7 +202,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
immUnbindProgram();
if (v3d->zbuf)
- glEnable(GL_DEPTH_TEST);
+ GPU_depth_test(true);
}
}
else if (t->spacetype == SPACE_IMAGE) {
@@ -219,7 +219,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
- glEnable(GL_BLEND);
+ GPU_blend(true);
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -244,7 +244,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
immUnbindProgram();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
}
}
@@ -280,7 +280,6 @@ void applyProject(TransInfo *t)
for (i = 0; i < tc->data_len; i++, td++) {
float iloc[3], loc[3], no[3];
float mval_fl[2];
- float dist_px = TRANSFORM_DIST_MAX_PX;
if (td->flag & TD_NOACTION)
break;
@@ -301,9 +300,15 @@ void applyProject(TransInfo *t)
}
if (ED_view3d_project_float_global(t->ar, iloc, mval_fl, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
- if (snapObjectsTransform(
- t, mval_fl, &dist_px,
- loc, no))
+ 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) {
@@ -346,7 +351,7 @@ void applyGridAbsolute(TransInfo *t)
GearsType grid_action;
int i;
- if (!(activeSnap(t) && (ELEM(t->tsnap.mode, SCE_SNAP_MODE_INCREMENT, SCE_SNAP_MODE_GRID))))
+ if (!(activeSnap(t) && (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID))))
return;
grid_action = BIG_GEARS;
@@ -401,16 +406,19 @@ void applyGridAbsolute(TransInfo *t)
void applySnapping(TransInfo *t, float *vec)
{
- /* project is not applied this way */
- if (t->tsnap.project)
+ if (t->tsnap.project && t->tsnap.mode == SCE_SNAP_MODE_FACE) {
+ /* Each Trans Data already makes the snap to face */
return;
+ }
if (t->tsnap.status & SNAP_FORCED) {
t->tsnap.targetSnap(t);
t->tsnap.applySnap(t, vec);
}
- else if (!ELEM(t->tsnap.mode, SCE_SNAP_MODE_INCREMENT, SCE_SNAP_MODE_GRID) && activeSnap(t)) {
+ 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
@@ -492,6 +500,7 @@ static bool bm_face_is_snap_target(BMFace *f, void *UNUSED(user_data))
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;
@@ -512,7 +521,7 @@ static void initSnappingMode(TransInfo *t)
}
else {
/* force project off when not supported */
- if (ts->snap_mode != SCE_SNAP_MODE_FACE)
+ if ((ts->snap_mode & SCE_SNAP_MODE_FACE) == 0)
t->tsnap.project = 0;
t->tsnap.mode = ts->snap_mode;
@@ -547,7 +556,9 @@ static void initSnappingMode(TransInfo *t)
{
/* 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) != 0) ? SNAP_ALL : SNAP_NOT_SELECTED;
+ t->tsnap.modeSelect = (
+ ((t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR)) != 0) ?
+ SNAP_ALL : SNAP_NOT_SELECTED);
}
else {
/* Grid if snap is not possible */
@@ -577,7 +588,7 @@ static void initSnappingMode(TransInfo *t)
if (t->spacetype == SPACE_VIEW3D) {
if (t->tsnap.object_context == NULL) {
t->tsnap.object_context = ED_transform_snap_object_context_create_view3d(
- G.main, t->scene, t->depsgraph, 0, t->ar, t->view);
+ bmain, t->scene, t->depsgraph, 0, t->ar, t->view);
ED_transform_snap_object_context_set_editmesh_callbacks(
t->tsnap.object_context,
@@ -948,18 +959,22 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
mval[0] = t->mval[0];
mval[1] = t->mval[1];
- if (t->tsnap.mode == SCE_SNAP_MODE_VOLUME) {
- found = peelObjectsTransform(
- t, mval,
- (t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0,
- loc, no, NULL);
- }
- else {
+ 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);
@@ -972,35 +987,38 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
}
}
else if (t->spacetype == SPACE_IMAGE && t->obedit_type == OB_MESH) {
- /* same as above but for UV's */
- Image *ima = ED_space_image(t->sa->spacedata.first);
- float co[2];
+ 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]);
+ UI_view2d_region_to_view(&t->ar->v2d, t->mval[0], t->mval[1], &co[0], &co[1]);
- if (ED_uvedit_nearest_uv(t->scene, TRANS_DATA_CONTAINER_FIRST_EVIL(t)->obedit, ima, co, t->tsnap.snapPoint)) {
- t->tsnap.snapPoint[0] *= t->aspect[0];
- t->tsnap.snapPoint[1] *= t->aspect[1];
+ if (ED_uvedit_nearest_uv(t->scene, TRANS_DATA_CONTAINER_FIRST_EVIL(t)->obedit, ima, co, 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;
+ t->tsnap.status |= POINT_INIT;
+ }
+ else {
+ t->tsnap.status &= ~POINT_INIT;
+ }
}
}
else if (t->spacetype == SPACE_NODE) {
- float loc[2];
- float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here
- char node_border;
+ 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;
+ 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;
+ t->tsnap.status |= POINT_INIT;
+ }
+ else {
+ t->tsnap.status &= ~POINT_INIT;
+ }
}
}
}
@@ -1195,16 +1213,15 @@ bool snapObjectsTransform(
float *dist_px,
float r_loc[3], float r_no[3])
{
- return ED_transform_snap_object_project_view3d_ex(
+ 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, NULL,
- r_loc, r_no, NULL,
- NULL, NULL);
+ mval, dist_px, r_loc, r_no);
}
@@ -1310,15 +1327,14 @@ static bool snapNodeTest(View2D *v2d, bNode *node, eSnapSelect snap_select)
static NodeBorder snapNodeBorder(int snap_node_mode)
{
- switch (snap_node_mode) {
- case SCE_SNAP_MODE_NODE_X:
- return NODE_LEFT | NODE_RIGHT;
- case SCE_SNAP_MODE_NODE_Y:
- return NODE_TOP | NODE_BOTTOM;
- case SCE_SNAP_MODE_NODE_XY:
- return NODE_LEFT | NODE_RIGHT | NODE_TOP | NODE_BOTTOM;
+ 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 0;
+ return flag;
}
static bool snapNode(
@@ -1426,9 +1442,13 @@ void snapGridIncrement(TransInfo *t, float *val)
{
GearsType action;
- /* only do something if using absolute or incremental grid snapping */
- if (!ELEM(t->tsnap.mode, SCE_SNAP_MODE_INCREMENT, SCE_SNAP_MODE_GRID))
+ /* 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))
+ {
return;
+ }
action = activeSnap(t) ? BIG_GEARS : NO_GEARS;
@@ -1468,7 +1488,7 @@ static void applyGridIncrement(TransInfo *t, float *val, int max_index, const fl
const float *asp = use_aspect ? t->aspect : asp_local;
int i;
- BLI_assert(ELEM(t->tsnap.mode, SCE_SNAP_MODE_INCREMENT, SCE_SNAP_MODE_GRID));
+ BLI_assert(t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID));
BLI_assert(max_index <= 2);
/* Early bailing out if no need to snap */
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 00976311887..e19320fa220 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -56,6 +56,7 @@
#include "BKE_tracking.h"
#include "BKE_context.h"
#include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -71,6 +72,8 @@
/** Internal Data Types
* \{ */
+#define MAX_CLIPPLANE_LEN 3
+
enum eViewProj {
VIEW_PROJ_NONE = -1,
VIEW_PROJ_ORTHO = 0,
@@ -78,14 +81,13 @@ enum eViewProj {
};
typedef struct SnapData {
- short snap_to;
+ short snap_to_flag;
float mval[2];
- float ray_start[3];
- float ray_dir[3];
float pmat[4][4]; /* perspective matrix */
float win_size[2];/* win x and y */
enum eViewProj view_proj;
- float depth_range[2];
+ float clip_plane[MAX_CLIPPLANE_LEN][4];
+ short clip_plane_len;
} SnapData;
typedef struct SnapObjectData {
@@ -163,12 +165,14 @@ typedef void(*IterSnapObjsCallback)(SnapObjectContext *sctx, bool is_obedit, Obj
*/
static void iter_snap_objects(
SnapObjectContext *sctx,
- const eSnapSelect snap_select,
- Object *obedit,
+ const struct SnapObjectParams *params,
IterSnapObjsCallback sob_callback,
void *data)
{
ViewLayer *view_layer = DEG_get_evaluated_view_layer(sctx->depsgraph);
+ Object *obedit = params->use_object_edit_cage ? OBEDIT_FROM_VIEW_LAYER(view_layer) : NULL;
+ const eSnapSelect snap_select = params->snap_select;
+
Base *base_act = view_layer->basact;
for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) {
if ((BASE_VISIBLE(base)) && (base->flag_legacy & BA_SNAP_FIX_DEPS_FIASCO) == 0 &&
@@ -194,46 +198,6 @@ static void iter_snap_objects(
}
-/**
- * Generates a struct with the immutable parameters that will be used on all objects.
- *
- * \param snap_to: Element to snap, Vertice, Edge or Face.
- * \param view_proj: ORTHO or PERSP.
- * Currently only works one at a time, but can eventually operate as flag.
- *
- * \param mval: Mouse coords.
- * (When NULL, ray-casting is handled without any projection matrix correction.)
- * \param ray_origin: ray_start before being moved toward the ray_normal at the distance from vew3d clip_min.
- * \param ray_start: ray_origin moved for the start clipping plane (clip_min).
- * \param ray_direction: Unit length direction of the ray.
- * \param depth_range: distances of clipe plane min and clip plane max;
- */
-static void snap_data_set(
- SnapData *snapdata,
- const ARegion *ar, const unsigned short snap_to, const enum eViewProj view_proj,
- const float mval[2], const float ray_start[3], const float ray_direction[3],
- const float depth_range[2])
-{
- copy_m4_m4(snapdata->pmat, ((RegionView3D *)ar->regiondata)->persmat);
- snapdata->win_size[0] = ar->winx;
- snapdata->win_size[1] = ar->winy;
- copy_v2_v2(snapdata->mval, mval);
- snapdata->snap_to = snap_to;
- copy_v3_v3(snapdata->ray_start, ray_start);
- copy_v3_v3(snapdata->ray_dir, ray_direction);
- snapdata->view_proj = view_proj;
- copy_v2_v2(snapdata->depth_range, depth_range);
-}
-
-
-MINLINE float depth_get(const float co[3], const float ray_start[3], const float ray_dir[3])
-{
- float dvec[3];
- sub_v3_v3v3(dvec, co, ray_start);
- return dot_v3v3(dvec, ray_dir);
-}
-
-
static bool walk_parent_bvhroot_cb(const BVHTreeAxisRange *bounds, void *userdata)
{
BVHTreeRay *ray = userdata;
@@ -512,7 +476,7 @@ static bool raycastMesh(
retval = true;
if (r_index) {
- *r_index = hit.index;
+ *r_index = treedata->looptri[hit.index].poly;
}
}
}
@@ -572,6 +536,10 @@ static bool raycastEditMesh(
return retval;
}
}
+ else {
+ /* COW hack: Update pointers */
+ treedata->em = em;
+ }
float imat[4][4];
float timat[3][3]; /* transpose inverse matrix for normals */
@@ -661,7 +629,7 @@ static bool raycastEditMesh(
retval = true;
if (r_index) {
- *r_index = hit.index;
+ *r_index = BM_elem_index_get(em->looptris[hit.index][0]->f);
}
}
}
@@ -680,7 +648,7 @@ 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_obedit, bool use_occlusion_test,
/* read/write args */
float *ray_depth,
/* return args */
@@ -690,32 +658,46 @@ static bool raycastObj(
{
bool retval = false;
- if (ob->type == OB_MESH) {
- if (use_obedit) {
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- retval = raycastEditMesh(
- sctx,
- ray_start, ray_dir,
- ob, em, obmat, ob_index,
- ray_depth, r_loc, r_no, r_index, r_hit_list);
- }
- else {
- retval = raycastMesh(
- sctx,
- ray_start, ray_dir,
- ob, ob->data, obmat, ob_index,
- ray_depth, r_loc, r_no, r_index, r_hit_list);
+ if (use_occlusion_test) {
+ if (use_obedit && sctx->use_v3d &&
+ !(sctx->v3d_data.v3d->flag & V3D_ZBUF_SELECT))
+ {
+ /* Use of occlude geometry in editing mode disabled. */
+ return false;
}
}
+ switch (ob->type) {
+ case OB_MESH:
+ if (use_obedit) {
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ retval = raycastEditMesh(
+ sctx,
+ ray_start, ray_dir,
+ ob, em, obmat, ob_index,
+ ray_depth, r_loc, r_no, r_index, r_hit_list);
+ }
+ else {
+ retval = raycastMesh(
+ sctx,
+ ray_start, ray_dir,
+ ob, ob->data, 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 retval;
+ return false;
}
@@ -732,16 +714,19 @@ struct RaycastObjUserData {
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 is_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++, is_obedit,
+ ob, obmat, dt->ob_index++,
+ is_obedit, dt->use_occlusion_test,
dt->ray_depth,
dt->r_loc, dt->r_no, dt->r_index,
dt->r_ob, dt->r_obmat,
@@ -778,8 +763,8 @@ static void raycast_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob,
*/
static bool raycastObjects(
SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
const float ray_start[3], const float ray_dir[3],
- const eSnapSelect snap_select, const bool use_object_edit_cage,
/* read/write args */
float *ray_depth,
/* return args */
@@ -787,9 +772,6 @@ static bool raycastObjects(
Object **r_ob, float r_obmat[4][4],
ListBase *r_hit_list)
{
- ViewLayer *view_layer = DEG_get_evaluated_view_layer(sctx->depsgraph);
- Object *obedit = use_object_edit_cage ? OBEDIT_FROM_VIEW_LAYER(view_layer) : NULL;
-
struct RaycastObjUserData data = {
.ray_start = ray_start,
.ray_dir = ray_dir,
@@ -801,10 +783,11 @@ static bool raycastObjects(
.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, snap_select, obedit, raycast_obj_cb, &data);
+ iter_snap_objects(sctx, params, raycast_obj_cb, &data);
return data.ret;
}
@@ -896,29 +879,26 @@ static void cb_mlooptri_verts_get(
}
static bool test_projected_vert_dist(
- struct DistProjectedAABBPrecalc *neasrest_precalc,
- const float depth_range[2], const float co[3],
- const bool is_persp,
+ 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])
{
- float w;
- if (is_persp) {
- w = mul_project_m4_v3_zfac(neasrest_precalc->pmat, co);
- if (w < depth_range[0] || w > depth_range[1]) {
- return false;
- }
+ if (!isect_point_planes_v3_negated(clip_plane, clip_plane_len, co)) {
+ return false;
}
float co2d[2] = {
- (dot_m4_v3_row_x(neasrest_precalc->pmat, co) + neasrest_precalc->pmat[3][0]),
- (dot_m4_v3_row_y(neasrest_precalc->pmat, co) + neasrest_precalc->pmat[3][1]),
+ (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(neasrest_precalc->mval, co2d);
+ 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;
@@ -928,21 +908,34 @@ static bool test_projected_vert_dist(
}
static bool test_projected_edge_dist(
- struct DistProjectedAABBPrecalc *neasrest_precalc,
- const float depth_range[2], const bool is_persp,
- const float va[3], const float vb[3],
+ 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 tmp_co[3], dummy_depth;
- dist_squared_ray_to_seg_v3(
- neasrest_precalc->ray_origin,
- neasrest_precalc->ray_direction,
- va, vb, tmp_co, &dummy_depth);
+ 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(
- neasrest_precalc, depth_range,
- tmp_co, is_persp, dist_px_sq, r_co);
+ precalc, clip_plane, clip_plane_len,
+ is_persp, near_co, dist_px_sq, r_co);
}
/** \} */
@@ -958,11 +951,7 @@ 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 {
- struct DistProjectedAABBPrecalc data_precalc;
- bool r_axis_closest[3];
bool is_persp;
- float depth_range[2];
- short snap_to;
void *userdata;
Nearest2DGetVertCoCallback get_vert_co;
@@ -971,116 +960,123 @@ typedef struct Nearest2dUserData {
Nearest2DGetTriEdgesCallback get_tri_edges_index;
Nearest2DCopyVertNoCallback copy_vert_no;
- float dist_px_sq;
- int index;
- float co[3];
- float no[3];
} Nearest2dUserData;
-static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *user_data)
+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)
{
- Nearest2dUserData *data = user_data;
- const float bbmin[3] = {bounds[0].min, bounds[1].min, bounds[2].min};
- const float bbmax[3] = {bounds[0].max, bounds[1].max, bounds[2].max};
- const float rdist = dist_squared_to_projected_aabb(
- &data->data_precalc, bbmin, bbmax, data->r_axis_closest);
- return rdist < data->dist_px_sq;
-}
+ struct Nearest2dUserData *data = userdata;
-static bool cb_nearest_walk_order(
- const BVHTreeAxisRange *UNUSED(bounds), char axis, void *userdata)
-{
- const bool *r_axis_closest = ((struct Nearest2dUserData *)userdata)->r_axis_closest;
- return r_axis_closest[axis];
+ 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 bool cb_walk_leaf_snap_vert(
- const BVHTreeAxisRange *UNUSED(bounds), int index, void *userdata)
+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;
- const float *co;
- data->get_vert_co(index, &co, data->userdata);
+ int vindex[2];
+ data->get_edge_verts_index(index, vindex, data->userdata);
- if (test_projected_vert_dist(
- &data->data_precalc,
- data->depth_range, co,
+ 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,
- &data->dist_px_sq,
- data->co))
+ v_pair[0], v_pair[1],
+ &nearest->dist_sq,
+ nearest->co))
{
- data->copy_vert_no(index, data->no, data->userdata);
- data->index = index;
+ sub_v3_v3v3(nearest->no, v_pair[0], v_pair[1]);
+ nearest->index = index;
}
- return true;
}
-static bool cb_walk_leaf_snap_edge(
- const BVHTreeAxisRange *UNUSED(bounds), int index, void *userdata)
+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);
- if (data->snap_to == SCE_SNAP_MODE_EDGE) {
- 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(
- &data->data_precalc,
- data->depth_range,
- data->is_persp,
- v_pair[0], v_pair[1],
- &data->dist_px_sq,
- data->co))
- {
- sub_v3_v3v3(data->no, v_pair[0], v_pair[1]);
- data->index = index;
+ for (int i = 2; i--;) {
+ if (vindex[i] == nearest->index) {
+ continue;
}
+ cb_snap_vert(
+ userdata, vindex[i], precalc,
+ clip_plane, clip_plane_len, nearest);
}
- else {
- for (int i = 0; i < 2; i++) {
- if (vindex[i] == data->index) {
+}
+
+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_walk_leaf_snap_vert(NULL, vindex[i], userdata);
+ cb_snap_edge(
+ userdata, eindex[i], precalc,
+ clip_plane, clip_plane_len, nearest);
}
}
-
- return true;
}
-static bool cb_walk_leaf_snap_tri(
- const BVHTreeAxisRange *UNUSED(bounds), int index, void *userdata)
+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;
- if (data->snap_to == SCE_SNAP_MODE_EDGE) {
- int eindex[3];
- data->get_tri_edges_index(index, eindex, data->userdata);
- for (int i = 0; i < 3; i++) {
- if (eindex[i] != -1) {
- if (eindex[i] == data->index) {
- continue;
- }
- cb_walk_leaf_snap_edge(NULL, eindex[i], userdata);
- }
- }
- }
- else {
- int vindex[3];
- data->get_tri_verts_index(index, vindex, data->userdata);
- for (int i = 0; i < 3; i++) {
- if (vindex[i] == data->index) {
- continue;
- }
- cb_walk_leaf_snap_vert(NULL, vindex[i], 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);
}
- return true;
}
/** \} */
@@ -1089,17 +1085,246 @@ static bool cb_walk_leaf_snap_tri(
/** \name Internal Object Snapping API
* \{ */
-static bool snapArmature(
+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);
+ 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;
+
+ MPoly *mp = &((Mesh *)ob->data)->mpoly[*r_index];
+ const MLoop *ml;
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ elem = SCE_SNAP_MODE_EDGE;
+ treedata->edge = ((Mesh *)ob->data)->medge;
+ ml = &treedata->loop[mp->loopstart];
+ 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;
+ ml = &treedata->loop[mp->loopstart];
+ 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_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_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);
+ }
+
+ if (r_index) {
+ *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)
+{
+ 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);
+ }
+
+ if (r_index) {
+ *r_index = nearest.index;
+ }
+ }
+
+ return elem;
+}
+
+static short snapArmature(
SnapData *snapdata,
- Object *ob, bArmature *arm, float obmat[4][4],
+ Object *ob, float obmat[4][4], bool use_obedit,
/* read/write args */
- float *ray_depth, float *dist_px,
+ float *dist_px,
/* return args */
- float r_loc[3], float *UNUSED(r_no))
+ float r_loc[3], float *UNUSED(r_no), int *r_index)
{
- bool retval = false;
+ short retval = 0;
- if (snapdata->snap_to == SCE_SNAP_MODE_FACE) { /* Currently only edge and vert */
+ if (snapdata->snap_to_flag == SCE_SNAP_MODE_FACE) { /* Currently only edge and vert */
return retval;
}
@@ -1110,41 +1335,60 @@ static bool snapArmature(
dist_squared_to_projected_aabb_precalc(
&neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
- /* Test BoundBox */
- BoundBox *bb = BKE_armature_boundbox_get(ob);
- if (bb) {
- bool dummy[3];
- /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */
- float bb_dist_px_sq = dist_squared_to_projected_aabb(
- &neasrest_precalc, bb->vec[0], bb->vec[6], dummy);
-
- if (bb_dist_px_sq > dist_px_sq) {
- return retval;
+ if (use_obedit == false) {
+ /* Test BoundBox */
+ BoundBox *bb = BKE_armature_boundbox_get(ob);
+ if (bb) {
+ bool dummy[3];
+ /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */
+ float bb_dist_px_sq = dist_squared_to_projected_aabb(
+ &neasrest_precalc, bb->vec[0], bb->vec[6], dummy);
+
+ if (bb_dist_px_sq > 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) {
- switch (snapdata->snap_to) {
- case SCE_SNAP_MODE_VERTEX:
- retval |= test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
- eBone->head, is_persp, &dist_px_sq, r_loc);
- retval |= test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
- eBone->tail, is_persp, &dist_px_sq, r_loc);
- break;
- case SCE_SNAP_MODE_EDGE:
- retval |= test_projected_edge_dist(
- &neasrest_precalc, snapdata->depth_range,
- is_persp, eBone->head, eBone->tail,
- &dist_px_sq, r_loc);
- break;
+ 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;
+ }
}
}
}
@@ -1155,50 +1399,64 @@ static bool snapArmature(
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;
- switch (snapdata->snap_to) {
- case SCE_SNAP_MODE_VERTEX:
- retval |= test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
- head_vec, is_persp, &dist_px_sq, r_loc);
- retval |= test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
- tail_vec, is_persp, &dist_px_sq, r_loc);
- break;
- case SCE_SNAP_MODE_EDGE:
- retval |= test_projected_edge_dist(
- &neasrest_precalc, snapdata->depth_range,
- is_persp, head_vec, tail_vec,
- &dist_px_sq, r_loc);
- break;
+ 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);
- *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
- return true;
+ if (r_index) {
+ /* Does not support index. */
+ *r_index = -1;
+ }
+ return retval;
}
- return false;
+
+ return 0;
}
-static bool snapCurve(
+static short snapCurve(
SnapData *snapdata,
Object *ob, float obmat[4][4], bool use_obedit,
/* read/write args */
- float *ray_depth, float *dist_px,
+ float *dist_px,
/* return args */
- float r_loc[3], float *UNUSED(r_no))
+ float r_loc[3], float *UNUSED(r_no), int *r_index)
{
- bool retval = false;
+ bool has_snap = false;
/* only vertex snapping mode (eg control points and handles) supported for now) */
- if (snapdata->snap_to != SCE_SNAP_MODE_VERTEX) {
- return retval;
+ if (snapdata->snap_to_flag != SCE_SNAP_MODE_VERTEX) {
+ return 0;
}
Curve *cu = ob->data;
@@ -1211,157 +1469,179 @@ static bool snapCurve(
dist_squared_to_projected_aabb_precalc(
&neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
- /* Test BoundBox */
- BoundBox *bb = BKE_curve_boundbox_get(ob);
- if (bb) {
- bool dummy[3];
- /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */
- float bb_dist_px_sq = dist_squared_to_projected_aabb(
- &neasrest_precalc, bb->vec[0], bb->vec[6], dummy);
-
- if (bb_dist_px_sq > dist_px_sq) {
- return retval;
+ if (use_obedit == false) {
+ /* Test BoundBox */
+ BoundBox *bb = BKE_curve_boundbox_get(ob);
+ if (bb) {
+ bool dummy[3];
+ /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */
+ float bb_dist_px_sq = dist_squared_to_projected_aabb(
+ &neasrest_precalc, bb->vec[0], bb->vec[6], dummy);
+
+ if (bb_dist_px_sq > 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++) {
- switch (snapdata->snap_to) {
- case 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) {
- break;
- }
- retval |= test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
- nu->bezt[u].vec[1], is_persp, &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))
- {
- retval |= test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
- nu->bezt[u].vec[0], is_persp, &dist_px_sq,
- r_loc);
- }
- if (!(nu->bezt[u].f3 & SELECT) &&
- !(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT))
- {
- retval |= test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
- nu->bezt[u].vec[2], is_persp, &dist_px_sq,
- r_loc);
- }
+ 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) {
+ break;
}
- else {
- /* don't snap to selected (moving) or hidden */
- if (nu->bp[u].f1 & SELECT || nu->bp[u].hide != 0) {
- break;
- }
- retval |= test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
- nu->bp[u].vec, is_persp, &dist_px_sq,
+ 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 {
- /* curve is not visible outside editmode if nurb length less than two */
- if (nu->pntsu > 1) {
- if (nu->bezt) {
- retval |= test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
- nu->bezt[u].vec[1], is_persp, &dist_px_sq,
- r_loc);
- }
- else {
- retval |= test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
- nu->bp[u].vec, is_persp, &dist_px_sq,
- r_loc);
- }
+ /* don't snap to selected (moving) or hidden */
+ if (nu->bp[u].f1 & SELECT || nu->bp[u].hide != 0) {
+ break;
+ }
+ 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);
}
}
- break;
}
- default:
- break;
}
}
}
- if (retval) {
+ if (has_snap) {
*dist_px = sqrtf(dist_px_sq);
mul_m4_v3(obmat, r_loc);
- *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
- return true;
+ if (r_index) {
+ /* Does not support index yet. */
+ *r_index = -1;
+ }
+ return SCE_SNAP_MODE_VERTEX;
}
- return false;
+
+ return 0;
}
/* may extend later (for now just snaps to empty center) */
-static bool snapEmpty(
+static short snapEmpty(
SnapData *snapdata,
Object *ob, float obmat[4][4],
/* read/write args */
- float *ray_depth, float *dist_px,
+ float *dist_px,
/* return args */
- float r_loc[3], float *UNUSED(r_no))
+ float r_loc[3], float *UNUSED(r_no), int *r_index)
{
- bool retval = false;
+ short retval = 0;
if (ob->transflag & OB_DUPLI) {
return retval;
}
/* for now only vertex supported */
- switch (snapdata->snap_to) {
- case SCE_SNAP_MODE_VERTEX:
+ 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))
{
- struct DistProjectedAABBPrecalc neasrest_precalc;
- dist_squared_to_projected_aabb_precalc(
- &neasrest_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval);
-
- bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
- float dist_px_sq = SQUARE(*dist_px);
- float tmp_co[3];
- copy_v3_v3(tmp_co, obmat[3]);
- if (test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
- tmp_co, is_persp, &dist_px_sq, r_loc))
- {
- *dist_px = sqrtf(dist_px_sq);
- *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
- retval = true;
- }
- break;
+ *dist_px = sqrtf(dist_px_sq);
+ retval = SCE_SNAP_MODE_VERTEX;
}
- default:
- break;
}
- return retval;
+ if (retval) {
+ if (r_index) {
+ /* Does not support index. */
+ *r_index = -1;
+ }
+ return retval;
+ }
+
+ return 0;
}
-static bool snapCamera(
+static short snapCamera(
const SnapObjectContext *sctx, SnapData *snapdata,
Object *object, float obmat[4][4],
/* read/write args */
- float *ray_depth, float *dist_px,
+ float *dist_px,
/* return args */
- float r_loc[3], float *UNUSED(r_no))
+ float r_loc[3], float *UNUSED(r_no), int *r_index)
{
+ short retval = 0;
+
+ Depsgraph *depsgraph = sctx->depsgraph;
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];
- bool retval = false;
MovieClip *clip = BKE_object_movieclip_get(scene, object, false);
MovieTracking *tracking;
@@ -1372,117 +1652,123 @@ static bool snapCamera(
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);
+ BKE_tracking_get_camera_object_matrix(depsgraph, scene, object, orig_camera_mat);
invert_m4_m4(orig_camera_imat, orig_camera_mat);
invert_m4_m4(imat, obmat);
- switch (snapdata->snap_to) {
- case SCE_SNAP_MODE_VERTEX:
+ 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)
{
- MovieTrackingObject *tracking_object;
- struct DistProjectedAABBPrecalc neasrest_precalc;
- dist_squared_to_projected_aabb_precalc(
- &neasrest_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval);
-
- 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);
- }
+ 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];
- for (track = tracksbase->first; track; track = track->next) {
- float bundle_pos[3];
+ if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) {
+ BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object,
+ CFRA, reconstructed_camera_mat);
- if ((track->flag & TRACK_HAS_BUNDLE) == 0) {
- continue;
- }
+ invert_m4_m4(reconstructed_camera_imat, reconstructed_camera_mat);
+ }
- 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;
- }
+ for (track = tracksbase->first; track; track = track->next) {
+ float bundle_pos[3];
- mul_m4_v3(vertex_obmat, bundle_pos);
- retval |= test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
- bundle_pos, is_persp, &dist_px_sq, r_loc);
+ if ((track->flag & TRACK_HAS_BUNDLE) == 0) {
+ continue;
}
- }
- break;
+ 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;
+ }
+ }
}
- default:
- break;
}
if (retval) {
*dist_px = sqrtf(dist_px_sq);
- *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
- return true;
+ if (r_index) {
+ /* Does not support index. */
+ *r_index = -1;
+ }
+ return retval;
}
- return false;
+
+ return 0;
}
-static bool snapMesh(
+static short snapMesh(
SnapObjectContext *sctx, SnapData *snapdata,
Object *ob, Mesh *me, float obmat[4][4],
/* read/write args */
- float *ray_depth, float *dist_px,
+ float *dist_px,
/* return args */
- float r_loc[3], float r_no[3])
+ float r_loc[3], float r_no[3], int *r_index)
{
- bool retval = false;
+ BLI_assert(snapdata->snap_to_flag != SCE_SNAP_MODE_FACE);
- if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) {
+ if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_EDGE) {
if (me->totedge == 0) {
- return retval;
+ return 0;
}
}
else {
if (me->totvert == 0) {
- return retval;
+ return 0;
}
}
float lpmat[4][4];
mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
- Nearest2dUserData neasrest2d;
- dist_squared_to_projected_aabb_precalc(
- &neasrest2d.data_precalc, lpmat, snapdata->win_size, snapdata->mval);
-
- neasrest2d.r_axis_closest[0] = true;
- neasrest2d.r_axis_closest[1] = true;
- neasrest2d.r_axis_closest[2] = true;
- neasrest2d.dist_px_sq = SQUARE(*dist_px);
+ float dist_px_sq = SQUARE(*dist_px);
/* Test BoundBox */
BoundBox *bb = BKE_mesh_boundbox_get(ob);
if (bb) {
/* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */
- float dist_px_sq = dist_squared_to_projected_aabb(
- &neasrest2d.data_precalc, bb->vec[0], bb->vec[6], neasrest2d.r_axis_closest);
- if (dist_px_sq > neasrest2d.dist_px_sq) {
- return retval;
+ struct DistProjectedAABBPrecalc data_precalc;
+ dist_squared_to_projected_aabb_precalc(
+ &data_precalc, lpmat, snapdata->win_size, snapdata->mval);
+
+ bool dummy[3];
+ float bb_dist_px_sq = dist_squared_to_projected_aabb(
+ &data_precalc, bb->vec[0], bb->vec[6], dummy);
+
+ if (bb_dist_px_sq > dist_px_sq) {
+ return 0;
}
}
@@ -1542,7 +1828,7 @@ static bool snapMesh(
treedata->edge_allocated = dummy_treedata.edge_allocated;
}
}
- if (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) {
+ 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;
@@ -1576,93 +1862,126 @@ static bool snapMesh(
}
}
- /* Warning: the depth_max is currently being used only in perspective view.
- * It is not correct to limit the maximum depth for elements obtained with nearest
- * since this limitation depends on the normal and the size of the occlusion face.
- * And more... ray_depth is being confused with Z-depth here... (varies only the precision) */
- const float ray_depth_max_global = *ray_depth + snapdata->depth_range[0];
-
- neasrest2d.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
-
- neasrest2d.depth_range[0] = snapdata->depth_range[0];
- neasrest2d.depth_range[1] = ray_depth_max_global;
+ 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,
+ };
- neasrest2d.snap_to = snapdata->snap_to;
- neasrest2d.userdata = treedata;
- neasrest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get;
- neasrest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get;
- neasrest2d.get_tri_verts_index = (Nearest2DGetTriVertsCallback)cb_mlooptri_verts_get;
- neasrest2d.get_tri_edges_index = (Nearest2DGetTriEdgesCallback)cb_mlooptri_edges_get;
- neasrest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy;
- neasrest2d.index = -1;
+ 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]) {
+ if (bvhtree[1] && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
/* snap to loose verts */
- BLI_bvhtree_walk_dfs(
- bvhtree[1],
- cb_walk_parent_snap_project, cb_walk_leaf_snap_vert, cb_nearest_walk_order, &neasrest2d);
+ 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 (bvhtree[0]) {
- /* snap to loose edges */
- BLI_bvhtree_walk_dfs(
- bvhtree[0],
- cb_walk_parent_snap_project, cb_walk_leaf_snap_edge, cb_nearest_walk_order, &neasrest2d);
+ 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_walk_dfs(
- treedata->tree,
- cb_walk_parent_snap_project, cb_walk_leaf_snap_tri, cb_nearest_walk_order, &neasrest2d);
+ 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 (neasrest2d.index != -1) {
- float imat[4][4];
- float timat[3][3]; /* transpose inverse matrix for normals */
- invert_m4_m4(imat, obmat);
- transpose_m3_m4(timat, imat);
+ if (nearest.index != -1) {
+ *dist_px = sqrtf(nearest.dist_sq);
- copy_v3_v3(r_loc, neasrest2d.co);
+ copy_v3_v3(r_loc, nearest.co);
mul_m4_v3(obmat, r_loc);
+
if (r_no) {
- copy_v3_v3(r_no, neasrest2d.no);
- mul_m3_v3(timat, 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);
}
- *dist_px = sqrtf(neasrest2d.dist_px_sq);
- *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
+ if (r_index) {
+ *r_index = nearest.index;
+ }
- retval = true;
+ return elem;
}
- return retval;
+ return 0;
}
-static bool snapEditMesh(
+static short snapEditMesh(
SnapObjectContext *sctx, SnapData *snapdata,
Object *ob, BMEditMesh *em, float obmat[4][4],
/* read/write args */
- float *ray_depth, float *dist_px,
+ float *dist_px,
/* return args */
- float r_loc[3], float r_no[3])
+ float r_loc[3], float r_no[3], int *r_index)
{
- bool retval = false;
+ BLI_assert(snapdata->snap_to_flag != SCE_SNAP_MODE_FACE);
- if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) {
+ if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_EDGE) {
if (em->bm->totedge == 0) {
- return retval;
+ return 0;
}
}
else {
if (em->bm->totvert == 0) {
- return retval;
+ return 0;
}
}
SnapObjectData_EditMesh *sod = NULL;
- BVHTreeFromEditMesh *treedata = NULL;
+ BVHTreeFromEditMesh *treedata_vert = NULL, *treedata_edge = NULL;
void **sod_p;
if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
@@ -1673,110 +1992,113 @@ static bool snapEditMesh(
sod->sd.type = SNAP_EDIT_MESH;
}
- int tree_index = -1;
- switch (snapdata->snap_to) {
- case SCE_SNAP_MODE_EDGE:
- tree_index = 1;
- break;
- case SCE_SNAP_MODE_VERTEX:
- tree_index = 0;
- break;
- }
- if (tree_index != -1) {
- if (sod->bvh_trees[tree_index] == NULL) {
- sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata));
+ 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 (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_SAFE_FREE(verts_mask);
}
- treedata = sod->bvh_trees[tree_index];
}
- if (treedata) {
- if (treedata->tree == NULL) {
- BLI_bitmap *elem_mask = NULL;
- switch (snapdata->snap_to) {
- case SCE_SNAP_MODE_EDGE:
- {
- int edges_num_active = -1;
- if (sctx->callbacks.edit_mesh.test_edge_fn) {
- elem_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__);
- edges_num_active = BM_iter_mesh_bitmap_from_filter(
- BM_EDGES_OF_MESH, em->bm, elem_mask,
- (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn,
- sctx->callbacks.edit_mesh.user_data);
- }
- bvhtree_from_editmesh_edges_ex(treedata, em, elem_mask, edges_num_active, 0.0f, 2, 6);
- break;
- }
- case SCE_SNAP_MODE_VERTEX:
- {
- int verts_num_active = -1;
- if (sctx->callbacks.edit_mesh.test_vert_fn) {
- elem_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__);
- verts_num_active = BM_iter_mesh_bitmap_from_filter(
- BM_VERTS_OF_MESH, em->bm, elem_mask,
- (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn,
- sctx->callbacks.edit_mesh.user_data);
- }
- bvhtree_from_editmesh_verts_ex(treedata, em, elem_mask, verts_num_active, 0.0f, 2, 6);
- break;
- }
- }
- if (elem_mask) {
- MEM_freeN(elem_mask);
- }
+ 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));
}
- if (treedata->tree == NULL) {
- return retval;
+ treedata_edge = sod->bvh_trees[1];
+ 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_SAFE_FREE(edges_mask);
}
}
- else {
- return retval;
- }
- Nearest2dUserData neasrest2d = {
- .r_axis_closest = {true, true, true},
+ Nearest2dUserData nearest2d = {
.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
- .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]},
- .snap_to = snapdata->snap_to,
- .userdata = treedata->em,
+ .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,
- .dist_px_sq = SQUARE(*dist_px),
- .index = -1};
+ };
- float lpmat[4][4];
+ BVHTreeNearest nearest = {
+ .index = -1,
+ .dist_sq = SQUARE(*dist_px),
+ };
+ int last_index = nearest.index;
+ short elem = SCE_SNAP_MODE_VERTEX;
+
+ float lpmat[4][4], tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
- dist_squared_to_projected_aabb_precalc(
- &neasrest2d.data_precalc, lpmat, snapdata->win_size, snapdata->mval);
+ transpose_m4_m4(tobmat, obmat);
- BVHTree_WalkLeafCallback cb_walk_leaf =
- (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ?
- cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
+ 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;
+ }
- BLI_bvhtree_walk_dfs(
- treedata->tree,
- cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d);
+ 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 (neasrest2d.index != -1) {
- float imat[4][4];
- float timat[3][3]; /* transpose inverse matrix for normals */
- invert_m4_m4(imat, obmat);
- transpose_m3_m4(timat, imat);
+ if (last_index != nearest.index) {
+ elem = SCE_SNAP_MODE_EDGE;
+ }
+ }
- copy_v3_v3(r_loc, neasrest2d.co);
+ 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) {
- copy_v3_v3(r_no, neasrest2d.no);
- mul_m3_v3(timat, 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);
}
- *dist_px = sqrtf(neasrest2d.dist_px_sq);
- *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
+ if (r_index) {
+ *r_index = nearest.index;
+ }
- retval = true;
+ return elem;
}
- return retval;
+ return 0;
}
/**
@@ -1784,100 +2106,108 @@ static bool snapEditMesh(
*
* \note Duplicate args here are documented at #snapObjectsRay
*/
-static bool snapObject(
+static short snapObject(
SnapObjectContext *sctx, SnapData *snapdata,
- Object *ob, float obmat[4][4],
- bool use_obedit,
+ Object *ob, float obmat[4][4], bool use_obedit,
/* read/write args */
- float *ray_depth, float *dist_px,
+ float *dist_px,
/* return args */
- float r_loc[3], float r_no[3],
+ float r_loc[3], float r_no[3], int *r_index,
Object **r_ob, float r_obmat[4][4])
{
- bool retval = false;
-
- if (ob->type == OB_MESH) {
- BMEditMesh *em;
+ short retval = 0;
+
+ switch (ob->type) {
+ case OB_MESH:
+ if (use_obedit) {
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ retval = snapEditMesh(
+ sctx, snapdata, ob, em, obmat,
+ dist_px,
+ r_loc, r_no, r_index);
+ }
+ else {
+ retval = snapMesh(
+ sctx, snapdata, ob, ob->data, obmat,
+ dist_px,
+ r_loc, r_no, r_index);
+ }
+ break;
- if (use_obedit) {
- em = BKE_editmesh_from_object(ob);
- retval = snapEditMesh(
- sctx, snapdata, ob, em, obmat,
- ray_depth, dist_px,
- r_loc, r_no);
- }
- else {
- retval = snapMesh(
- sctx, snapdata, ob, ob->data, obmat,
- ray_depth, dist_px,
- r_loc, r_no);
- }
- }
- else if (snapdata->snap_to != SCE_SNAP_MODE_FACE) {
- if (ob->type == OB_ARMATURE) {
+ case OB_ARMATURE:
retval = snapArmature(
snapdata,
- ob, ob->data, obmat,
- ray_depth, dist_px,
- r_loc, r_no);
- }
- else if (ob->type == OB_CURVE) {
+ ob, obmat, use_obedit,
+ dist_px,
+ r_loc, r_no, r_index);
+ break;
+
+ case OB_CURVE:
retval = snapCurve(
snapdata,
ob, obmat, use_obedit,
- ray_depth, dist_px,
- r_loc, r_no);
- }
- else if (ob->type == OB_EMPTY) {
+ dist_px,
+ r_loc, r_no, r_index);
+ break;
+
+ case OB_EMPTY:
retval = snapEmpty(
- snapdata,
- ob, obmat,
- ray_depth, dist_px,
- r_loc, r_no);
- }
- else if (ob->type == OB_CAMERA) {
+ snapdata, ob, obmat,
+ dist_px,
+ r_loc, r_no, r_index);
+ break;
+
+ case OB_CAMERA:
retval = snapCamera(
sctx, snapdata, ob, obmat,
- ray_depth, dist_px,
- r_loc, r_no);
- }
+ 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 retval;
+ return 0;
}
struct SnapObjUserData {
SnapData *snapdata;
/* read/write args */
- float *ray_depth;
float *dist_px;
/* return args */
float *r_loc;
float *r_no;
+ int *r_index;
Object **r_ob;
float (*r_obmat)[4];
- bool ret;
+ short ret;
};
static void sanp_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data)
{
struct SnapObjUserData *dt = data;
- dt->ret |= snapObject(
+
+ short elem = snapObject(
sctx, dt->snapdata,
ob, obmat, is_obedit,
/* read/write args */
- dt->ray_depth, dt->dist_px,
+ dt->dist_px,
/* return args */
- dt->r_loc, dt->r_no,
+ dt->r_loc, dt->r_no, dt->r_index,
dt->r_ob, dt->r_obmat);
+
+ if (elem) {
+ dt->ret = elem;
+ }
}
@@ -1909,30 +2239,27 @@ static void sanp_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, flo
* \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances).
*
*/
-static bool snapObjectsRay(
+static short snapObjectsRay(
SnapObjectContext *sctx, SnapData *snapdata,
- const eSnapSelect snap_select, const bool use_object_edit_cage,
+ const struct SnapObjectParams *params,
/* read/write args */
- float *ray_depth, float *dist_px,
+ float *dist_px,
/* return args */
- float r_loc[3], float r_no[3],
+ float r_loc[3], float r_no[3], int *r_index,
Object **r_ob, float r_obmat[4][4])
{
- ViewLayer *view_layer = DEG_get_evaluated_view_layer(sctx->depsgraph);
- Object *obedit = use_object_edit_cage ? OBEDIT_FROM_VIEW_LAYER(view_layer) : NULL;
-
struct SnapObjUserData data = {
.snapdata = snapdata,
- .ray_depth = ray_depth,
.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 = false,
+ .ret = 0,
};
- iter_snap_objects(sctx, snap_select, obedit, sanp_obj_cb, &data);
+ iter_snap_objects(sctx, params, sanp_obj_cb, &data);
return data.ret;
}
@@ -2029,9 +2356,8 @@ bool ED_transform_snap_object_project_ray_ex(
Object **r_ob, float r_obmat[4][4])
{
return raycastObjects(
- sctx,
+ sctx, params,
ray_start, ray_normal,
- params->snap_select, params->use_object_edit_cage,
ray_depth, r_loc, r_no, r_index, r_ob, r_obmat, NULL);
}
@@ -2058,9 +2384,8 @@ bool ED_transform_snap_object_project_ray_all(
#endif
bool retval = raycastObjects(
- sctx,
+ sctx, params,
ray_start, ray_normal,
- params->snap_select, params->use_object_edit_cage,
&ray_depth, NULL, NULL, NULL, NULL, NULL,
r_hit_list);
@@ -2121,61 +2446,156 @@ bool ED_transform_snap_object_project_ray(
r_co, r_no);
}
-static bool transform_snap_context_project_view3d_mixed_impl(
+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,
- bool use_depth,
- float r_co[3], float r_no[3])
+ float r_loc[3], float r_no[3], int *r_index,
+ Object **r_ob, float r_obmat[4][4])
{
- float ray_depth = BVH_RAYCAST_DIST_MAX;
- bool is_hit = false;
+ BLI_assert(
+ (snap_to_flag & (
+ SCE_SNAP_MODE_VERTEX |
+ SCE_SNAP_MODE_EDGE |
+ SCE_SNAP_MODE_FACE)) != 0);
- const int elem_type[3] = {SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE, SCE_SNAP_MODE_FACE};
+ short retval = 0;
+ bool has_hit = false;
+ int index = -1;
- BLI_assert(snap_to_flag != 0);
- BLI_assert((snap_to_flag & ~(1 | 2 | 4)) == 0);
+ float loc[3], no[3], obmat[4][4];
+ Object *ob = NULL;
- if (use_depth) {
- const float dist_px_orig = dist_px ? *dist_px : 0;
- for (int i = 2; i >= 0; i--) {
- if (snap_to_flag & (1 << i)) {
- if (i == 0) {
- BLI_assert(dist_px != NULL);
- *dist_px = dist_px_orig;
- }
- if (ED_transform_snap_object_project_view3d(
- sctx,
- elem_type[i], params,
- mval, dist_px, &ray_depth,
- r_co, r_no))
- {
- /* 0.01 is a random but small value to prioritizing
- * the first elements of the loop */
- ray_depth += 0.01f;
- is_hit = true;
- }
- }
+ const ARegion *ar = sctx->v3d_data.ar;
+ const RegionView3D *rv3d = ar->regiondata;
+
+ bool use_occlusion_test =
+ params->use_occlusion_test &&
+ !(sctx->v3d_data.v3d->shading.flag & V3D_SHADING_XRAY);
+
+ if (snap_to_flag & SCE_SNAP_MODE_FACE || use_occlusion_test) {
+ float ray_start[3], ray_normal[3];
+
+ if (!ED_view3d_win_to_ray_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;
}
}
- else {
- for (int i = 0; i < 3; i++) {
- if (snap_to_flag & (1 << i)) {
- if (ED_transform_snap_object_project_view3d(
- sctx,
- elem_type[i], params,
- mval, dist_px, &ray_depth,
- r_co, r_no))
- {
- is_hit = true;
- break;
- }
+
+ 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);
+ }
+
+ /* 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;
}
- return is_hit;
+ 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])
+{
+ 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;
}
/**
@@ -2186,90 +2606,15 @@ static bool transform_snap_context_project_view3d_mixed_impl(
* \param sctx: Snap context.
* \param mval_fl: Screenspace coordinate.
* \param dist_px: Maximum distance to snap (in pixels).
- * \param use_depth: Snap to the closest element, use when using more than one snap type.
* \param r_co: hit location.
* \param r_no: hit normal (optional).
* \return Snap success
*/
-bool ED_transform_snap_object_project_view3d_mixed(
- SnapObjectContext *sctx,
- const unsigned short snap_to_flag,
- const struct SnapObjectParams *params,
- const float mval_fl[2], float *dist_px,
- bool use_depth,
- float r_co[3], float r_no[3])
-{
- return transform_snap_context_project_view3d_mixed_impl(
- sctx,
- snap_to_flag, params,
- mval_fl, dist_px, use_depth,
- r_co, r_no);
-}
-
-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 *ray_depth,
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4])
-{
- const ARegion *ar = sctx->v3d_data.ar;
- const RegionView3D *rv3d = ar->regiondata;
-
- float ray_origin[3], ray_end[3], ray_start[3], ray_normal[3], depth_range[2];
-
- ED_view3d_win_to_origin(ar, mval, ray_origin);
- ED_view3d_win_to_vector(ar, mval, ray_normal);
-
- ED_view3d_clip_range_get(
- sctx->depsgraph,
- sctx->v3d_data.v3d, sctx->v3d_data.ar->regiondata,
- &depth_range[0], &depth_range[1], false);
-
- madd_v3_v3v3fl(ray_start, ray_origin, ray_normal, depth_range[0]);
- madd_v3_v3v3fl(ray_end, ray_origin, ray_normal, depth_range[1]);
-
- if (!ED_view3d_clip_segment(rv3d, ray_start, ray_end)) {
- return false;
- }
-
- float ray_depth_fallback;
- if (ray_depth == NULL) {
- ray_depth_fallback = BVH_RAYCAST_DIST_MAX;
- ray_depth = &ray_depth_fallback;
- }
-
- if (snap_to == SCE_SNAP_MODE_FACE) {
- return raycastObjects(
- sctx,
- ray_start, ray_normal,
- params->snap_select, params->use_object_edit_cage,
- ray_depth, r_loc, r_no, r_index, r_ob, r_obmat, NULL);
- }
- else {
- SnapData snapdata;
- const enum eViewProj view_proj = rv3d->is_persp ?
- VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO;
-
- snap_data_set(
- &snapdata, ar, snap_to, view_proj, mval,
- ray_start, ray_normal, depth_range);
-
- return snapObjectsRay(
- sctx, &snapdata,
- params->snap_select, params->use_object_edit_cage,
- ray_depth, dist_px, r_loc, r_no, r_ob, r_obmat);
- }
-}
-
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 *ray_depth,
float r_loc[3], float r_no[3])
{
return ED_transform_snap_object_project_view3d_ex(
@@ -2277,7 +2622,6 @@ bool ED_transform_snap_object_project_view3d(
snap_to,
params,
mval, dist_px,
- ray_depth,
r_loc, r_no, NULL,
NULL, NULL);
}
diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c
index 3950b056e89..478e004743d 100644
--- a/source/blender/editors/undo/ed_undo.c
+++ b/source/blender/editors/undo/ed_undo.c
@@ -57,6 +57,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_toolsystem.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -106,7 +107,6 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
CLOG_INFO(&LOG, 1, "name='%s', step=%d", undoname, step);
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
- // Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
/* undo during jobs are running can easily lead to freeing data using by jobs,
@@ -135,6 +135,9 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
WM_event_add_notifier(C, NC_WINDOW, NULL);
WM_event_add_notifier(C, NC_WM | ND_UNDO, NULL);
+ Main *bmain = CTX_data_main(C);
+ WM_toolsystem_refresh_screen_all(bmain);
+
if (win) {
win->addmousemove = true;
}
@@ -145,15 +148,10 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
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);
- if (wm->undo_stack->steps.last) {
- const UndoStep *us = wm->undo_stack->steps.last;
- if (STREQ(str, us->name)) {
- return;
- }
- }
-
+ 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 */
@@ -207,7 +205,7 @@ bool ED_undo_is_valid(const bContext *C, const char *undoname)
*/
UndoStack *ED_undo_stack_get(void)
{
- wmWindowManager *wm = G.main->wm.first;
+ wmWindowManager *wm = G_MAIN->wm.first;
return wm->undo_stack;
}
@@ -304,36 +302,6 @@ void ED_OT_undo_redo(wmOperatorType *ot)
/** \} */
-struct OperatorRepeatContextHandle {
- ScrArea *restore_area;
- ARegion *restore_region;
-};
-
-/**
- * Resets the context to the state \a op was executed in (or at least, was in when registering).
- * #ED_operator_repeat_reset_context should be called when done repeating!
- */
-const OperatorRepeatContextHandle *ED_operator_repeat_prepare_context(bContext *C, wmOperator *op)
-{
- static OperatorRepeatContextHandle context_info;
-
- context_info.restore_area = CTX_wm_area(C);
- context_info.restore_region = CTX_wm_region(C);
-
- CTX_wm_area_set(C, op->execution_area);
- CTX_wm_region_set(C, op->execution_region);
-
- return &context_info;
-}
-/**
- * Resets context to the old state from before #ED_operator_repeat_prepare_context was called.
- */
-void ED_operator_repeat_reset_context(bContext *C, const OperatorRepeatContextHandle *context_info)
-{
- CTX_wm_area_set(C, context_info->restore_area);
- CTX_wm_region_set(C, context_info->restore_region);
-}
-
/* -------------------------------------------------------------------- */
/** \name Operator Repeat
* \{ */
@@ -348,8 +316,13 @@ int ED_undo_operator_repeat(bContext *C, wmOperator *op)
wmWindowManager *wm = CTX_wm_manager(C);
struct Scene *scene = CTX_data_scene(C);
- const OperatorRepeatContextHandle *context_info;
- context_info = ED_operator_repeat_prepare_context(C, op);
+ /* 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)) &&
@@ -395,7 +368,8 @@ int ED_undo_operator_repeat(bContext *C, wmOperator *op)
}
}
- ED_operator_repeat_reset_context(C, context_info);
+ /* set region back */
+ CTX_wm_region_set(C, ar_orig);
}
else {
CLOG_WARN(&LOG, "called with NULL 'op'");
@@ -437,7 +411,7 @@ static const EnumPropertyItem *rna_undo_itemf(bContext *C, int *totitem)
item_tmp.identifier = us->name;
item_tmp.name = IFACE_(us->name);
if (us == wm->undo_stack->step_active) {
- item_tmp.icon = ICON_RESTRICT_VIEW_OFF;
+ item_tmp.icon = ICON_HIDE_OFF;
}
else {
item_tmp.icon = ICON_NONE;
diff --git a/source/blender/editors/undo/undo_intern.h b/source/blender/editors/undo/undo_intern.h
index 671f9637d65..03f9d248ba0 100644
--- a/source/blender/editors/undo/undo_intern.h
+++ b/source/blender/editors/undo/undo_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt
index 24cfde90804..fa21facefc2 100644
--- a/source/blender/editors/util/CMakeLists.txt
+++ b/source/blender/editors/util/CMakeLists.txt
@@ -87,6 +87,7 @@ set(SRC
../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
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 61a70d2da42..10c2f735e0e 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
@@ -76,6 +76,7 @@
#include "ED_util.h"
#include "GPU_immediate.h"
+#include "GPU_state.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -129,7 +130,7 @@ void ED_editors_init(bContext *C)
{
Scene *sce = CTX_data_scene(C);
if (sce) {
- ED_space_image_paint_update(wm, sce);
+ ED_space_image_paint_update(bmain, wm, sce);
}
}
@@ -145,8 +146,8 @@ void ED_editors_exit(bContext *C)
return;
/* frees all editmode undos */
- if (G.main->wm.first) {
- wmWindowManager *wm = G.main->wm.first;
+ if (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);
@@ -210,7 +211,7 @@ bool ED_editors_flush_edits(const bContext *C, bool for_render)
else if (ob->mode & OB_MODE_EDIT) {
/* get editmode results */
has_edited = true;
- ED_object_editmode_load(ob);
+ ED_object_editmode_load(bmain, ob);
}
}
@@ -227,7 +228,7 @@ void apply_keyb_grid(int shift, int ctrl, float *val, float fac1, float fac2, fl
/* 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);
}
@@ -241,6 +242,7 @@ void apply_keyb_grid(int shift, int ctrl, float *val, float fac1, float fac2, fl
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;
@@ -262,7 +264,7 @@ void unpack_menu(bContext *C, const char *opname, const char *id_name, const cha
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(local_name, pf)) {
+ 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);
@@ -295,7 +297,7 @@ void unpack_menu(bContext *C, const char *opname, const char *id_name, const cha
}
}
- switch (checkPackedFile(abs_name, pf)) {
+ 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);
@@ -345,7 +347,7 @@ void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
immUniform1i("num_colors", 0); /* "simple" mode */
diff --git a/source/blender/editors/uvedit/uvedit_buttons.c b/source/blender/editors/uvedit/uvedit_buttons.c
index f037783bd5e..b37703d03dd 100644
--- a/source/blender/editors/uvedit/uvedit_buttons.c
+++ b/source/blender/editors/uvedit/uvedit_buttons.c
@@ -70,7 +70,7 @@ static int uvedit_center(Scene *scene, Object *obedit, BMEditMesh *em, Image *im
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))
@@ -101,7 +101,7 @@ static void uvedit_translate(Scene *scene, Object *obedit, BMEditMesh *em, Image
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;
@@ -131,7 +131,7 @@ static void uvedit_vertex_buttons(const bContext *C, uiBlock *block)
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)) {
@@ -164,7 +164,7 @@ static void uvedit_vertex_buttons(const bContext *C, uiBlock *block)
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, "");
@@ -217,12 +217,12 @@ static int image_panel_uv_poll(const bContext *C, PanelType *UNUSED(pt))
static void image_panel_uv(const bContext *C, Panel *pa)
{
uiBlock *block;
-
+
block = uiLayoutAbsoluteBlock(pa->layout);
UI_block_func_handle_set(block, do_uvedit_vertex, NULL);
uvedit_vertex_buttons(C, block);
-}
+}
void ED_uvedit_buttons_register(ARegionType *art)
{
@@ -235,4 +235,3 @@ void ED_uvedit_buttons_register(ARegionType *art)
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 beaae691e5e..5fb328a922d 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -48,7 +48,7 @@
#include "BLI_buffer.h"
#include "BLI_bitmap.h"
-#include "BKE_DerivedMesh.h"
+#include "BKE_deform.h"
#include "BKE_editmesh.h"
#include "BKE_material.h"
#include "BKE_layer.h"
@@ -64,6 +64,7 @@
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "ED_image.h"
#include "ED_mesh.h"
@@ -87,6 +88,8 @@ void ED_image_draw_cursor(ARegion *ar, const float cursor[2])
x_fac = zoom[0];
y_fac = zoom[1];
+ GPU_line_width(1.0f);
+
gpuTranslate2fv(cursor);
const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -94,7 +97,7 @@ void ED_image_draw_cursor(ARegion *ar, const float cursor[2])
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
immUniform1i("num_colors", 2); /* "advanced" mode */
@@ -194,12 +197,12 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, Object *obedit, BME
BLI_buffer_declare_static(vec2f, tf_uvorig_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
ED_space_image_get_uv_aspect(sima, &aspx, &aspy);
-
+
switch (sima->dt_uvstretch) {
case SI_UVDT_STRETCH_AREA:
{
float totarea = 0.0f, totuvarea = 0.0f, areadiff, uvarea, area;
-
+
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
const int efa_len = efa->len;
float (*tf_uv)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, efa_len);
@@ -214,7 +217,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, Object *obedit, BME
totarea += BM_face_calc_area(efa);
totuvarea += area_poly_v2(tf_uv, efa->len);
-
+
if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
BM_elem_flag_enable(efa, BM_ELEM_TAG);
}
@@ -266,17 +269,17 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, Object *obedit, BME
uv_poly_copy_aspect(tf_uvorig, tf_uv, aspx, aspy, efa->len);
uvarea = area_poly_v2(tf_uv, efa->len) / totuvarea;
-
+
if (area < FLT_EPSILON || uvarea < FLT_EPSILON)
areadiff = 1.0f;
else if (area > uvarea)
areadiff = 1.0f - (uvarea / area);
else
areadiff = 1.0f - (area / uvarea);
-
- weight_to_rgb(col, areadiff);
+
+ BKE_defvert_weight_to_rgb(col, areadiff);
immUniformColor3fv(col);
-
+
/* TODO: use editmesh tessface */
immBegin(GWN_PRIM_TRI_FAN, efa->len);
@@ -354,7 +357,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, Object *obedit, BME
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
a = fabsf(uvang[i] - ang[i]) / (float)M_PI;
- weight_to_rgb(col, 1.0f - pow2f(1.0f - a));
+ BKE_defvert_weight_to_rgb(col, 1.0f - pow2f(1.0f - a));
immAttrib3fv(color, col);
immVertex2fv(pos, luv->uv);
}
@@ -415,10 +418,6 @@ static void draw_uvs_lineloop_bmfaces(BMesh *bm, const int cd_loop_uv_offset, co
}
GWN_batch_program_use_end(loop_batch);
GWN_batch_discard(loop_batch);
-
- immUnbindProgram();
-
- immEnd();
}
static void draw_uvs_lineloop_mpoly(Mesh *me, MPoly *mpoly, unsigned int pos)
@@ -459,7 +458,7 @@ static void draw_uvs_other_mesh(Object *ob, const Image *curimage,
for (a = 0; a < totcol; a++) {
Image *image;
-
+
/* if no materials, assume a default material with no image */
if (ob->totcol)
ED_object_get_active_image(ob, a + 1, &image, NULL, NULL, NULL);
@@ -504,7 +503,7 @@ static void draw_uvs_other(ViewLayer *view_layer, Object *obedit, const Image *c
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
if (((base->flag & BASE_SELECTED) != 0) &&
- ((base->flag & BASE_VISIBLED) != 0))
+ ((base->flag & BASE_VISIBLE) != 0))
{
Object *ob = base->object;
if ((ob->type == OB_MESH) && (ob != obedit) && ((Mesh *)ob->data)->mloopuv) {
@@ -606,7 +605,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
interpedges = (ts->selectmode & SCE_SELECT_VERTEX);
else
interpedges = (ts->uv_selectmode == UV_SELECT_VERTEX);
-
+
/* draw other uvs */
if (sima->flag & SI_DRAW_OTHER) {
Image *curimage;
@@ -622,21 +621,21 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
}
/* 1. draw shadow mesh */
-
+
if (sima->flag & SI_DRAWSHADOW) {
- Object *ob_cage = DEG_get_evaluated_object(depsgraph, obedit);
+ Object *ob_cage_eval = DEG_get_evaluated_object(depsgraph, obedit);
/* XXX TODO: Need to check if shadow mesh is different than original mesh. */
- bool is_cage_like_final_meshes = (ob_cage == obedit);
+ bool is_cage_like_final_meshes = (ob_cage_eval == obedit);
/* 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) == 0) || is_cage_like_final_meshes) {
- draw_uvs_shadow(ob_cage);
+ draw_uvs_shadow(ob_cage_eval);
}
}
/* 2. draw colored faces */
-
+
if (sima->flag & SI_DRAW_STRETCH) {
draw_uvs_stretch(sima, scene, obedit, em, efa_act);
}
@@ -656,8 +655,8 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
/* draw transparent faces */
UI_GetThemeColor4fv(TH_FACE, col1);
UI_GetThemeColor4fv(TH_FACE_SELECT, col2);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
Gwn_VertFormat *format = immVertexFormat();
pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -693,7 +692,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
immUnbindProgram();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
else {
if (efa_act && !uvedit_face_visible_test(scene, obedit, ima, efa_act)) {
@@ -708,9 +707,9 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
/* 4. draw edges */
if (sima->flag & SI_SMOOTH_UV) {
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_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);
}
pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -721,13 +720,13 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
+ GPU_viewport_size_getf(viewport_size);
immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
immUniform1i("num_colors", 2); /* "advanced" mode */
immUniformArray4fv("colors", (float *)(float[][4]){{0.56f, 0.56f, 0.56f, 1.0f}, {0.07f, 0.07f, 0.07f, 1.0f}}, 2);
immUniform1f("dash_width", 4.0f);
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
break;
}
@@ -740,13 +739,13 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
else {
immUniformColor3f(0.0f, 0.0f, 0.0f);
}
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
break;
case SI_UVDT_OUTLINE:
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
imm_cpack(0x0);
- glLineWidth(3.0f);
+ GPU_line_width(3.0f);
break;
}
@@ -782,7 +781,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
if (sima->dt_uv == SI_UVDT_OUTLINE) {
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
UI_GetThemeColor4fv(TH_WIRE_EDIT, col2);
if (me->drawflag & ME_DRAWEDGES) {
@@ -885,8 +884,8 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
GWN_batch_discard(loop_batch);
if (sima->flag & SI_SMOOTH_UV) {
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
+ GPU_line_smooth(false);
+ GPU_blend(false);
}
/* 5. draw face centers */
@@ -902,8 +901,8 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
pointsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
- glPointSize(pointsize);
-
+ GPU_point_size(pointsize);
+
immBeginAtMost(GWN_PRIM_POINTS, bm->totface);
/* unselected faces */
@@ -954,7 +953,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
}
/* 6. draw uv vertices */
-
+
if (drawfaces != 2) { /* 2 means Mesh Face Mode */
pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@@ -963,7 +962,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
/* unselected uvs */
immUniformThemeColor(TH_VERTEX);
pointsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
- glPointSize(pointsize);
+ GPU_point_size(pointsize);
immBeginAtMost(GWN_PRIM_POINTS, bm->totloop);
@@ -979,12 +978,12 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
}
immEnd();
-
+
/* pinned uvs */
/* give odd pointsizes odd pin pointsizes */
- glPointSize(pointsize * 2 + (((int)pointsize % 2) ? (-1) : 0));
+ GPU_point_size(pointsize * 2 + (((int)pointsize % 2) ? (-1) : 0));
imm_cpack(0xFF);
-
+
immBeginAtMost(GWN_PRIM_POINTS, bm->totloop);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
@@ -1000,11 +999,11 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
}
immEnd();
-
+
/* selected uvs */
immUniformThemeColor(TH_VERTEX_SELECT);
- glPointSize(pointsize);
-
+ GPU_point_size(pointsize);
+
immBeginAtMost(GWN_PRIM_POINTS, bm->totloop);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
@@ -1037,10 +1036,10 @@ static void draw_uv_shadows_get(
if ((sima->mode == SI_MODE_PAINT) && obedit && obedit->type == OB_MESH) {
struct BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
+
*show_shadow = EDBM_uv_check(em);
}
-
+
*show_texpaint = (ob && ob->type == OB_MESH && ob->mode == OB_MODE_TEXTURE_PAINT);
}
@@ -1065,7 +1064,7 @@ void ED_uvedit_draw_main(
Object *ob_iter = objects[ob_index];
draw_uvs(sima, scene, view_layer, ob_iter, depsgraph);
}
- MEM_SAFE_FREE(objects);
+ MEM_freeN(objects);
}
else {
draw_uvs_texpaint(sima, scene, view_layer, obact);
@@ -1075,4 +1074,3 @@ void ED_uvedit_draw_main(
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 e3db0162f10..eed9d68f39c 100644
--- a/source/blender/editors/uvedit/uvedit_intern.h
+++ b/source/blender/editors/uvedit/uvedit_intern.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
- *
+ *
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 97075eba61e..f26f4af0622 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -108,13 +108,13 @@ bool ED_uvedit_test(Object *obedit)
if (!obedit)
return 0;
-
+
if (obedit->type != OB_MESH)
return 0;
em = BKE_editmesh_from_object(obedit);
ret = EDBM_uv_check(em);
-
+
return ret;
}
@@ -167,7 +167,7 @@ bool ED_object_get_active_image(
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;
@@ -364,7 +364,7 @@ bool uvedit_edge_select_test(
return BM_elem_flag_test(l->e, BM_ELEM_SELECT);
}
else {
- return BM_elem_flag_test(l->v, BM_ELEM_SELECT) &&
+ return BM_elem_flag_test(l->v, BM_ELEM_SELECT) &&
BM_elem_flag_test(l->next->v, BM_ELEM_SELECT);
}
}
@@ -417,7 +417,7 @@ void uvedit_edge_select_enable(
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;
}
@@ -445,7 +445,7 @@ void uvedit_edge_select_disable(
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;
}
@@ -567,35 +567,45 @@ void uv_poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float as
}
}
-bool ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, 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])
{
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
bool changed = false;
+ INIT_MINMAX2(r_min, r_max);
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects_edit[ob_index];
- INIT_MINMAX2(r_min, r_max);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
- 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;
+ 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)) {
+ 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);
+}
+
/* Be careful when using this, it bypasses all synchronization options */
void ED_uvedit_select_all(BMesh *bm)
{
@@ -614,27 +624,32 @@ void ED_uvedit_select_all(BMesh *bm)
}
}
-static bool ED_uvedit_median(Scene *scene, Image *ima, Object *obedit, float co[2])
+static bool ED_uvedit_median_multi(Scene *scene, Image *ima, Object **objects_edit, uint objects_len, float co[2])
{
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
unsigned int sel = 0;
+ zero_v2(co);
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects_edit[ob_index];
- zero_v2(co);
- 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++;
+ 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);
+
+ 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++;
+ }
}
}
}
@@ -644,19 +659,24 @@ static bool ED_uvedit_median(Scene *scene, Image *ima, Object *obedit, float co[
return (sel != 0);
}
-bool ED_uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2], char mode)
+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);
+}
+
+bool ED_uvedit_center_multi(Scene *scene, Image *ima, Object **objects_edit, uint objects_len, float cent[2], char mode)
{
bool changed = false;
-
+
if (mode == V3D_AROUND_CENTER_BOUNDS) { /* bounding box */
float min[2], max[2];
- if (ED_uvedit_minmax(scene, ima, obedit, min, max)) {
+ 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(scene, ima, obedit, cent)) {
+ if (ED_uvedit_median_multi(scene, ima, objects_edit, objects_len, cent)) {
changed = true;
}
}
@@ -664,6 +684,11 @@ bool ED_uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2], c
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);
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -895,11 +920,11 @@ bool ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, const float
mindist = 1e10f;
copy_v2_v2(r_uv, co);
-
+
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);
dist = len_manhattan_v2v2(co, luv->uv);
@@ -933,7 +958,7 @@ static void uv_select_edgeloop_vertex_loop_flag(UvMapVert *first)
count++;
}
-
+
if (count < 5)
first->flag = 1;
}
@@ -949,7 +974,7 @@ static UvMapVert *uv_select_edgeloop_vertex_map_get(UvVertMap *vmap, BMFace *efa
if (iterv->f == BM_elem_index_get(efa))
return first;
}
-
+
return NULL;
}
@@ -1088,7 +1113,7 @@ static int uv_select_edgeloop(
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);
@@ -1337,7 +1362,7 @@ static int uv_select_more_less(bContext *C, const bool select)
else {
EDBM_select_less(em, true);
}
-
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
}
@@ -1409,6 +1434,7 @@ static int uv_select_more_less(bContext *C, const bool select)
uv_select_flush_from_tag_loop(sima, scene, obedit, select);
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -1699,7 +1725,7 @@ static void UV_OT_align(wmOperatorType *ot)
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;
@@ -1894,7 +1920,7 @@ static void UV_OT_weld(wmOperatorType *ot)
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;
@@ -2033,10 +2059,11 @@ static int uv_select_all_exec(bContext *C, wmOperator *op)
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
- MEM_SAFE_FREE(objects);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -2048,7 +2075,7 @@ static void UV_OT_select_all(wmOperatorType *ot)
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;
@@ -2200,7 +2227,7 @@ static int uv_mouse_select_multi(
hituv[i] = luv->uv;
hitv[i] = BM_elem_index_get(l->v);
}
-
+
hitlen = hit.efa->len;
}
else if (selectmode == UV_SELECT_ISLAND) {
@@ -2305,7 +2332,7 @@ static int uv_mouse_select_multi(
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);
@@ -2346,7 +2373,7 @@ static int uv_mouse_select_multi(
#endif
}
- DEG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED;
@@ -2391,7 +2418,7 @@ static void UV_OT_select(wmOperatorType *ot)
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;
@@ -2440,7 +2467,7 @@ static void UV_OT_select_loop(wmOperatorType *ot)
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;
@@ -2500,7 +2527,7 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent
}
if (!uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit)) {
- MEM_SAFE_FREE(objects);
+ MEM_freeN(objects);
return OPERATOR_CANCELLED;
}
}
@@ -2522,7 +2549,7 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
- DEG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
@@ -2543,7 +2570,7 @@ static void UV_OT_select_linked(wmOperatorType *ot)
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 */
@@ -2750,19 +2777,19 @@ static void uv_select_flush_from_tag_sticky_loc_internal(
*/
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
+ /* 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. */
@@ -2791,19 +2818,19 @@ static void uv_select_flush_from_tag_face(SpaceImage *sima, Scene *scene, Object
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,
@@ -2812,7 +2839,7 @@ static void uv_select_flush_from_tag_face(SpaceImage *sima, Scene *scene, Object
}
}
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) {
@@ -3027,12 +3054,13 @@ static int uv_border_select_exec(bContext *C, wmOperator *op)
uv_select_sync_flush(ts, em, select);
if (ts->uv_flag & UV_SYNC_SELECTION) {
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
}
}
- MEM_SAFE_FREE(objects);
+ MEM_freeN(objects);
return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
@@ -3043,17 +3071,17 @@ static void UV_OT_select_border(wmOperatorType *ot)
ot->name = "Border Select";
ot->description = "Select UV vertices using border selection";
ot->idname = "UV_OT_select_border";
-
+
/* api callbacks */
ot->invoke = WM_gesture_border_invoke;
ot->exec = uv_border_select_exec;
ot->modal = WM_gesture_border_modal;
ot->poll = ED_operator_uvedit_space_image; /* requires space image */;
ot->cancel = WM_gesture_border_cancel;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
RNA_def_boolean(ot->srna, "pinned", 0, "Pinned", "Border select pinned UVs only");
@@ -3112,7 +3140,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
ellipse[1] = height * zoomy / radius;
UI_view2d_region_to_view(&ar->v2d, x, y, &offset[0], &offset[1]);
-
+
/* do selection */
if (use_face_center) {
changed = false;
@@ -3156,6 +3184,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
if (changed) {
uv_select_sync_flush(ts, em, select);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
@@ -3168,14 +3197,14 @@ static void UV_OT_circle_select(wmOperatorType *ot)
ot->name = "Circle Select";
ot->description = "Select UV vertices using circle selection";
ot->idname = "UV_OT_circle_select";
-
+
/* 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_REGISTER | OPTYPE_UNDO;
@@ -3289,6 +3318,7 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo
uv_select_sync_flush(scene->toolsettings, em, select);
if (ts->uv_flag & UV_SYNC_SELECTION) {
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
}
@@ -3357,17 +3387,16 @@ static void uv_snap_cursor_to_pixels(SpaceImage *sima)
uv_snap_to_pixel(sima->cursor, width, height);
}
-static bool uv_snap_cursor_to_selection(Scene *scene, Image *ima, Object *obedit, SpaceImage *sima)
+static bool uv_snap_cursor_to_selection(
+ Scene *scene, Image *ima, Object **objects_edit, uint objects_len, SpaceImage *sima)
{
- return ED_uvedit_center(scene, ima, obedit, 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);
- Scene *scene = CTX_data_scene(C);
- Object *obedit = CTX_data_edit_object(C);
- Image *ima = CTX_data_edit_image(C);
+
bool changed = false;
switch (RNA_enum_get(op->ptr, "target")) {
@@ -3376,13 +3405,23 @@ static int uv_snap_cursor_exec(bContext *C, wmOperator *op)
changed = true;
break;
case 1:
- changed = uv_snap_cursor_to_selection(scene, ima, obedit, sima);
+ {
+ 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, &objects_len);
+ changed = uv_snap_cursor_to_selection(scene, ima, objects, objects_len, sima);
+ MEM_freeN(objects);
break;
+ }
}
if (!changed)
return OPERATOR_CANCELLED;
-
+
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_IMAGE, sima);
return OPERATOR_FINISHED;
@@ -3400,7 +3439,7 @@ static void UV_OT_snap_cursor(wmOperatorType *ot)
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 */;
@@ -3479,7 +3518,7 @@ static bool uv_snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object
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) {
@@ -3541,7 +3580,7 @@ static bool uv_snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit
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;
@@ -3613,7 +3652,7 @@ static void UV_OT_snap_selected(wmOperatorType *ot)
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;
@@ -3639,7 +3678,7 @@ static int uv_pin_exec(bContext *C, wmOperator *op)
BMIter iter, liter;
MLoopUV *luv;
const bool clear = RNA_boolean_get(op->ptr, "clear");
-
+
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) {
@@ -3648,7 +3687,7 @@ static int uv_pin_exec(bContext *C, wmOperator *op)
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-
+
if (!clear) {
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))
luv->flag |= MLOOPUV_PINNED;
@@ -3659,7 +3698,7 @@ static int uv_pin_exec(bContext *C, wmOperator *op)
}
}
}
-
+
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
@@ -3672,7 +3711,7 @@ static void UV_OT_pin(wmOperatorType *ot)
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;
@@ -3697,7 +3736,7 @@ static int uv_select_pinned_exec(bContext *C, wmOperator *UNUSED(op))
BMLoop *l;
BMIter iter, liter;
MLoopUV *luv;
-
+
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) {
@@ -3706,12 +3745,13 @@ static int uv_select_pinned_exec(bContext *C, wmOperator *UNUSED(op))
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);
}
}
-
+
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -3724,7 +3764,7 @@ static void UV_OT_select_pinned(wmOperatorType *ot)
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;
@@ -3778,6 +3818,8 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
if (ts->uv_flag & UV_SYNC_SELECTION) {
EDBM_mesh_hide(em, swap);
+
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -3844,8 +3886,10 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
/* 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, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -3860,7 +3904,7 @@ static void UV_OT_hide(wmOperatorType *ot)
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;
@@ -3899,6 +3943,7 @@ static int uv_reveal_exec(bContext *C, wmOperator *op)
/* call the mesh function if we are in mesh sync sel */
if (ts->uv_flag & UV_SYNC_SELECTION) {
EDBM_mesh_reveal(em, select);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -3927,7 +3972,7 @@ static int uv_reveal_exec(bContext *C, wmOperator *op)
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);
@@ -3984,10 +4029,11 @@ static int uv_reveal_exec(bContext *C, wmOperator *op)
}
}
}
-
+
/* 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, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -4000,7 +4046,7 @@ static void UV_OT_reveal(wmOperatorType *ot)
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;
@@ -4029,9 +4075,9 @@ static int uv_set_2d_cursor_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
RNA_float_get_array(op->ptr, "location", sima->cursor);
-
+
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_IMAGE, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -4061,7 +4107,7 @@ static void UV_OT_cursor_set(wmOperatorType *ot)
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;
@@ -4347,17 +4393,19 @@ void ED_keymap_uvedit(wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
wmKeyMapItem *kmi;
-
+
keymap = WM_keymap_find(keyconf, "UV Editor", 0, 0);
keymap->poll = ED_operator_uvedit_can_uv_sculpt;
+#ifdef USE_WM_KEYMAP_27X
/* Uv sculpt toggle */
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", QKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_uv_sculpt");
+#endif
/* Mark edge seam */
WM_keymap_add_item(keymap, "UV_OT_mark_seam", EKEY, KM_PRESS, KM_CTRL, 0);
-
+
/* pick selection */
RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_select", SELECTMOUSE, KM_PRESS, 0, 0)->ptr, "extend", false);
RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", true);
@@ -4403,7 +4451,7 @@ void ED_keymap_uvedit(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "UV_OT_select_pinned", PKEY, KM_PRESS, KM_SHIFT, 0);
- WM_keymap_add_menu(keymap, "IMAGE_MT_uvs_weldalign", WKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_menu(keymap, "IMAGE_MT_uvs_weldalign", WKEY, KM_PRESS, KM_SHIFT, 0);
/* uv operations */
WM_keymap_add_item(keymap, "UV_OT_stitch", VKEY, KM_PRESS, 0, 0);
@@ -4414,9 +4462,11 @@ void ED_keymap_uvedit(wmKeyConfig *keyconf)
/* unwrap */
WM_keymap_add_item(keymap, "UV_OT_unwrap", EKEY, KM_PRESS, 0, 0);
+#ifdef USE_WM_KEYMAP_27X
WM_keymap_add_item(keymap, "UV_OT_minimize_stretch", VKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "UV_OT_pack_islands", PKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "UV_OT_average_islands_scale", AKEY, KM_PRESS, KM_CTRL, 0);
+#endif
/* hide */
kmi = WM_keymap_add_item(keymap, "UV_OT_hide", HKEY, KM_PRESS, 0, 0);
@@ -4428,7 +4478,7 @@ void ED_keymap_uvedit(wmKeyConfig *keyconf)
/* cursor */
WM_keymap_add_item(keymap, "UV_OT_cursor_set", ACTIONMOUSE, KM_PRESS, 0, 0);
-
+
/* menus */
WM_keymap_add_menu(keymap, "IMAGE_MT_uvs_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_menu(keymap, "IMAGE_MT_uvs_select_mode", TABKEY, KM_PRESS, KM_CTRL, 0);
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
index c510c12ae53..79e804725e5 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -113,7 +113,7 @@ typedef struct PVert {
float uv[2];
unsigned char flag;
-} PVert;
+} PVert;
typedef struct PEdge {
struct PEdge *nextlink;
@@ -242,8 +242,8 @@ 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,
+ 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
};
@@ -294,7 +294,7 @@ static void phash_insert(PHash *ph, PHashLink *link)
link->next = lookup->next;
lookup->next = link;
}
-
+
ph->size++;
if (ph->size > (size * 3)) {
@@ -323,7 +323,7 @@ static PHashLink *phash_lookup(PHash *ph, PHashKey key)
return link;
else if (PHASH_hash(ph, link->key) != hash)
return NULL;
-
+
return link;
}
@@ -336,7 +336,7 @@ static PHashLink *phash_next(PHash *ph, PHashKey key, PHashLink *link)
return link;
else if (PHASH_hash(ph, link->key) != hash)
return NULL;
-
+
return link;
}
@@ -562,7 +562,7 @@ static PEdge *p_wheel_edge_next(PEdge *e)
}
static PEdge *p_wheel_edge_prev(PEdge *e)
-{
+{
return (e->pair) ? e->pair->next : NULL;
}
@@ -619,7 +619,7 @@ static void p_chart_topological_sanity_check(PChart *chart)
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);
@@ -867,7 +867,7 @@ static PBool p_edge_implicit_seam(PEdge *e, PEdge *ep)
ep->flag |= PEDGE_SEAM;
return P_TRUE;
}
-
+
return P_FALSE;
}
@@ -881,7 +881,7 @@ static PBool p_edge_has_pair(PHandle *handle, PEdge *e, PEdge **pair, PBool impl
if (e->flag & PEDGE_SEAM)
return P_FALSE;
-
+
key = PHASH_edge(key1, key2);
pe = (PEdge *)phash_lookup(handle->hash_edges, key);
*pair = NULL;
@@ -999,7 +999,7 @@ static void p_split_vert(PChart *chart, PEdge *e)
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)
@@ -1202,7 +1202,7 @@ static PBool p_quad_split_direction(PHandle *handle, float **co, PHashKey *vkeys
/* Construction: boundary filling */
static void p_chart_boundaries(PChart *chart, int *nboundaries, PEdge **outer)
-{
+{
PEdge *e, *be;
float len, maxlen = -1.0;
@@ -1327,7 +1327,7 @@ static void p_chart_fill_boundary(PChart *chart, PEdge *be, int nedges)
}
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);
}
@@ -1412,7 +1412,7 @@ static void p_polygon_kernel_clip(float (*oldpoints)[2], int noldpoints, float (
newpoints[*nnewpoints][1] = p2[1];
(*nnewpoints)++;
}
-
+
p1in = p2in;
p1 = p2;
}
@@ -1422,7 +1422,7 @@ static void p_polygon_kernel_center(float (*points)[2], int npoints, float *cent
{
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");
@@ -1486,7 +1486,7 @@ static void p_polygon_kernel_center(float (*points)[2], int npoints, float *cent
int NCOLLAPSE = 1;
int NCOLLAPSEX = 0;
-
+
static float p_vert_cotan(float *v1, float *v2, float *v3)
{
float a[3], b[3], c[3], clen;
@@ -1499,10 +1499,10 @@ static float p_vert_cotan(float *v1, float *v2, float *v3)
if (clen == 0.0f)
return 0.0f;
-
+
return dot_v3v3(a, b) / clen;
}
-
+
static PBool p_vert_flipped_wheel_triangle(PVert *v)
{
PEdge *e = v->edge;
@@ -1530,7 +1530,7 @@ static PBool p_vert_map_harmonic_weights(PVert *v)
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);
@@ -1563,7 +1563,7 @@ static PBool p_vert_map_harmonic_weights(PVert *v)
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));
}
@@ -1617,20 +1617,20 @@ static void p_vert_harmonic_insert(PVert *v)
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];
+ 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);
-
+
p_polygon_kernel_center(points, npoints, v->uv);
MEM_freeN(points);
@@ -1653,7 +1653,7 @@ static void p_vert_fix_edge_pointer(PVert *v)
/* 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;
}
@@ -1699,7 +1699,7 @@ static void p_collapse_edge(PEdge *edge, PEdge *pair)
else
keepv->edge = pair->next->pair->next;
}
-
+
/* update pairs and v->edge pointers */
if (edge) {
PEdge *e1 = edge->next, *e2 = e1->next;
@@ -1821,7 +1821,7 @@ static PBool p_collapse_allowed_topologic(PEdge *edge, PEdge *pair)
* the chart) */
else if (!p_vert_interior(oldv) && !p_vert_interior(keepv))
return P_FALSE;
-
+
return P_TRUE;
}
@@ -1868,7 +1868,7 @@ static PBool p_collapse_allowed_geometric(PEdge *edge, PEdge *pair)
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];
@@ -1903,7 +1903,7 @@ static PBool p_collapse_allowed_geometric(PEdge *edge, PEdge *pair)
/* 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))
@@ -1921,7 +1921,7 @@ static PBool p_collapse_allowed(PEdge *edge, PEdge *pair)
if (oldv->flag & PVERT_PIN)
return P_FALSE;
-
+
return (p_collapse_allowed_topologic(edge, pair) &&
p_collapse_allowed_geometric(edge, pair));
}
@@ -2010,7 +2010,7 @@ static float p_collapse_cost(PEdge *edge, PEdge *pair)
return cost;
}
-
+
static void p_collapse_cost_vertex(PVert *vert, float *mincost, PEdge **mine)
{
PEdge *e, *enext, *pair;
@@ -2172,7 +2172,7 @@ static void p_chart_simplify_compute(PChart *chart)
for (v = chart->verts; v; v = v->nextlink) {
float cost;
PEdge *e = NULL;
-
+
p_collapse_cost_vertex(v, &cost, &e);
if (e)
@@ -2237,7 +2237,7 @@ static void p_chart_simplify_compute(PChart *chart)
BLI_heap_remove(heap, v->u.heaplink);
v->u.heaplink = NULL;
}
-
+
p_collapse_cost_vertex(v, &cost, &collapse);
if (collapse)
@@ -2331,7 +2331,7 @@ static void p_abf_setup_system(PAbfSystem *sys)
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;
}
@@ -2649,7 +2649,7 @@ static PBool p_abf_matrix_invert(PAbfSystem *sys, PChart *chart)
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);
@@ -2914,7 +2914,7 @@ static PBool p_chart_symmetry_pins(PChart *chart, PEdge *outer, PVert **pin1, PV
if (!maxe1 || !maxe2 || (maxlen < 0.5f * totlen))
return P_FALSE;
-
+
/* find pin1 in the split vertices */
be1 = maxe1;
be2 = maxe2;
@@ -3212,7 +3212,7 @@ 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.abf_alpha) {
MEM_freeN(chart->u.lscm.abf_alpha);
chart->u.lscm.abf_alpha = NULL;
@@ -3250,7 +3250,7 @@ static float p_face_stretch(PFace *f)
if (area <= 0.0f) /* flipped face -> infinite stretch */
return 1e10f;
-
+
w = 1.0f / (2.0f * area);
/* compute derivatives */
@@ -3682,7 +3682,7 @@ static SmoothNode *p_node_new(MemArena *arena, SmoothTriangle **tri, int ntri, f
if (ntri <= 10 || depth >= 15)
return node;
-
+
t1 = MEM_mallocN(sizeof(*t1) * ntri, "PNodeTri1");
t2 = MEM_mallocN(sizeof(*t2) * ntri, "PNodeTri1");
@@ -3707,7 +3707,7 @@ static SmoothNode *p_node_new(MemArena *arena, SmoothTriangle **tri, int ntri, f
MEM_freeN(t2);
return node;
}
-
+
node->tri = NULL;
node->ntri = 0;
MEM_freeN(tri);
@@ -3782,7 +3782,7 @@ static float p_smooth_median_edge_length(PChart *chart)
/* 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);
median = lengths[i / 2];
@@ -3876,7 +3876,7 @@ static void p_smooth(PChart *chart)
if ((gridx <= 2) || (gridy <= 2))
return;
-
+
edgesx = gridx - 1;
edgesy = gridy - 1;
nsize = gridx * gridy;
@@ -3936,7 +3936,7 @@ static void p_smooth(PChart *chart)
float p[2], b[3];
i = x + y * gridx;
-
+
p[0] = nodesx[i];
p[1] = nodesy[i];
@@ -3979,7 +3979,7 @@ static void p_smooth(PChart *chart)
for (it2 = 0; it2 < maxiter2; it2++) {
d = 0.0f;
totiter += 1;
-
+
memcpy(oldnodesx, nodesx, sizeof(float) * nsize);
memcpy(oldnodesy, nodesy, sizeof(float) * nsize);
@@ -4011,7 +4011,7 @@ static void p_smooth(PChart *chart)
sum1 += vedges[j] * oldnodesy[i + gridx];
nodesy[i] = sum1 / sum2;
-
+
p[0] = nodesx[i];
p[1] = nodesy[i];
@@ -4089,8 +4089,8 @@ static void p_smooth(PChart *chart)
t2->co3[0] = t->co3[0]; t2->co3[1] = t->co3[1];
t2->oco3[0] = t->oco3[0]; t2->oco3[1] = t->oco3[1];
- *trip = t; trip++; t++;
- *trip = t; trip++; t++;
+ *trip = t; trip++; t++;
+ *trip = t; trip++; t++;
}
}
@@ -4107,7 +4107,7 @@ static void p_smooth(PChart *chart)
p_node_delete(root);
BLI_memarena_free(arena);
-
+
MEM_freeN(triangles);
}
@@ -4149,7 +4149,7 @@ void param_delete(ParamHandle *handle)
for (i = 0; i < phandle->ncharts; i++)
p_chart_delete(phandle->charts[i]);
-
+
if (phandle->charts)
MEM_freeN(phandle->charts);
@@ -4496,24 +4496,24 @@ static void param_pack_rotate(ParamHandle *handle)
}
void param_pack(ParamHandle *handle, float margin, bool do_rotate)
-{
+{
/* 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;
-
+
PHandle *phandle = (PHandle *)handle;
-
+
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);
@@ -4521,33 +4521,33 @@ void param_pack(ParamHandle *handle, float margin, bool do_rotate)
/* 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];
-
+
if (chart->flag & PCHART_NOPACK) {
unpacked++;
continue;
}
-
+
box = boxarray + (i - unpacked);
-
+
p_chart_uv_bbox(chart, trans, chart->u.pack.size);
-
+
trans[0] = -trans[0];
trans[1] = -trans[1];
-
+
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_NOPACK boxes */
-
+
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.
@@ -4556,12 +4556,12 @@ void param_pack(ParamHandle *handle, float margin, bool do_rotate)
unpacked = 0;
for (i = 0; i < phandle->ncharts; i++) {
chart = phandle->charts[i];
-
+
if (chart->flag & PCHART_NOPACK) {
unpacked++;
continue;
}
-
+
box = boxarray + (i - unpacked);
trans[0] = margin;
trans[1] = margin;
@@ -4570,19 +4570,19 @@ void param_pack(ParamHandle *handle, float margin, bool do_rotate)
box->h += margin * 2;
}
}
-
+
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;
-
+
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);
@@ -4601,54 +4601,54 @@ void param_average(ParamHandle *handle)
float tot_fac, fac;
float minv[2], maxv[2], trans[2];
PHandle *phandle = (PHandle *)handle;
-
+
if (phandle->ncharts == 0)
return;
-
+
for (i = 0; i < phandle->ncharts; i++) {
PFace *f;
chart = phandle->charts[i];
if (chart->flag & PCHART_NOPACK)
continue;
-
+
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));
}
-
+
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;
}
-
+
tot_fac = tot_facearea / tot_uvarea;
-
+
for (i = 0; i < phandle->ncharts; i++) {
chart = phandle->charts[i];
if (chart->flag & PCHART_NOPACK)
continue;
-
+
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;
-
+
/* 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];
@@ -4702,4 +4702,3 @@ void param_flush_restore(ParamHandle *handle)
p_face_restore_uvs(f);
}
}
-
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.h b/source/blender/editors/uvedit/uvedit_parametrizer.h
index eaea781971d..2714bc33769 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.h
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.h
@@ -30,7 +30,7 @@
#ifdef __cplusplus
extern "C" {
#endif
-
+
#include "BLI_sys_types.h" // for intptr_t support
typedef void ParamHandle; /* handle to a set of charts */
@@ -77,7 +77,7 @@ void param_delete(ParamHandle *chart);
* - lscm is divided in three steps:
* - begin: compute matrix and it's factorization (expensive)
* - solve using pinned coordinates (cheap)
- * - end: clean up
+ * - end: clean up
* - uv coordinates are allowed to change within begin/end, for
* quick re-solving
*/
@@ -120,4 +120,3 @@ void param_flush_restore(ParamHandle *handle);
#endif
#endif /*__UVEDIT_PARAMETRIZER_H__*/
-
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index 4c205818329..9091f3eff0b 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -65,6 +65,7 @@
#include "ED_space_api.h"
#include "GPU_batch.h"
+#include "GPU_state.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -291,7 +292,7 @@ static void stitch_update_header(StitchState *state, bContext *C)
state->limit_dist,
WM_bool_as_string(state->use_limit));
- ED_area_headerprint(sa, msg);
+ ED_workspace_status_text(C, msg);
}
}
@@ -1570,7 +1571,7 @@ static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *ar
pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
}
- glEnable(GL_BLEND);
+ GPU_blend(true);
/* Static Tris */
UI_GetThemeColor4fv(TH_STITCH_PREVIEW_ACTIVE, col);
@@ -1623,12 +1624,12 @@ static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *ar
UI_GetThemeColor4fv(TH_STITCH_PREVIEW_EDGE, col);
stitch_draw_vbo(vbo_line, GWN_PRIM_LINES, col);
- glDisable(GL_BLEND);
+ GPU_blend(false);
/* draw stitch vert/lines preview */
if (state->mode == STITCH_VERT) {
- glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) * 2.0f);
+ GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE) * 2.0f);
UI_GetThemeColor4fv(TH_STITCH_PREVIEW_STITCHABLE, col);
vbo = GWN_vertbuf_create_with_format(&format);
@@ -2089,7 +2090,7 @@ static void stitch_exit(bContext *C, wmOperator *op, int finished)
}
if (sa)
- ED_area_headerprint(sa, NULL);
+ ED_workspace_status_text(C, NULL);
ED_region_draw_cb_exit(CTX_wm_region(C)->type, state->draw_handle);
@@ -2334,7 +2335,7 @@ void UV_OT_stitch(wmOperatorType *ot)
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;
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 8029759551d..eb14ca9ae2d 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -147,7 +147,7 @@ static bool ED_uvedit_ensure_uvs(bContext *C, Scene *UNUSED(scene), Object *obed
}
}
}
-
+
/* select new UV's (ignore UV_SYNC_SELECTION in this case) */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BMIter liter;
@@ -170,7 +170,7 @@ static bool uvedit_have_selection(Scene *scene, BMEditMesh *em, bool implicit)
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);
}
@@ -184,15 +184,15 @@ static bool uvedit_have_selection(Scene *scene, BMEditMesh *em, bool implicit)
}
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 (implicit && !l)
continue;
-
+
return true;
}
@@ -277,7 +277,7 @@ static ParamHandle *construct_param_handle(
BMEdge *eed;
BMIter iter, liter;
int i;
-
+
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
handle = param_construct_begin();
@@ -290,10 +290,10 @@ static ParamHandle *construct_param_handle(
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)) || (sel && BM_elem_flag_test(efa, BM_ELEM_SELECT) == 0)) {
@@ -494,9 +494,9 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B
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,
+ derivedMesh = subsurf_make_derived_from_derived(initialDerived, &smd, scene,
NULL, SUBSURF_IN_EDIT_MODE);
initialDerived->release(initialDerived);
@@ -563,7 +563,7 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B
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);
@@ -656,9 +656,9 @@ static void minimize_stretch_iteration(bContext *C, wmOperator *op, bool interac
param_flush(ms->handle);
if (sa) {
- BLI_snprintf(str, sizeof(str),
- IFACE_("Minimize Stretch. Blend %.2f (Press + and -, or scroll wheel to set)"), ms->blend);
- ED_area_headerprint(sa, str);
+ 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();
@@ -673,8 +673,9 @@ static void minimize_stretch_exit(bContext *C, wmOperator *op, bool cancel)
MinStretch *ms = op->customdata;
ScrArea *sa = CTX_wm_area(C);
- if (sa)
- ED_area_headerprint(sa, 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);
@@ -791,7 +792,7 @@ void UV_OT_minimize_stretch(wmOperatorType *ot)
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;
@@ -839,7 +840,7 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(view_layer, &objects_len);
if (!uvedit_have_selection_multi(scene, objects, objects_len, true)) {
- MEM_SAFE_FREE(objects);
+ MEM_freeN(objects);
return OPERATOR_CANCELLED;
}
@@ -856,7 +857,7 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
}
- MEM_SAFE_FREE(objects);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -869,7 +870,7 @@ void UV_OT_pack_islands(wmOperatorType *ot)
ot->description = "Transform all islands so that they fill up the UV space as much as possible";
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* api callbacks */
ot->exec = pack_islands_exec;
ot->poll = ED_operator_uvedit;
@@ -897,7 +898,7 @@ static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op))
param_average(handle);
param_flush(handle);
param_delete(handle);
-
+
DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
@@ -912,7 +913,7 @@ void UV_OT_average_islands_scale(wmOperatorType *ot)
ot->description = "Average the size of separate UV islands, based on their area in 3D space";
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* api callbacks */
ot->exec = average_islands_scale_exec;
ot->poll = ED_operator_uvedit;
@@ -950,7 +951,7 @@ void ED_uvedit_live_unwrap_re_solve(void)
param_flush(liveHandle);
}
}
-
+
void ED_uvedit_live_unwrap_end(short cancel)
{
if (liveHandle) {
@@ -1139,7 +1140,7 @@ static void uv_map_transform(bContext *C, wmOperator *op, float rotmat[4][4])
/* be compatible to the "old" sphere/cylinder mode */
if (direction == ALIGN_TO_OBJECT)
unit_m4(rotmat);
- else
+ else
uv_map_rotation_matrix(rotmat, rv3d, obedit, upangledeg, sideangledeg, radius);
}
@@ -1174,21 +1175,21 @@ static void correct_uv_aspect(Scene *scene, Object *ob, BMEditMesh *em)
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;
@@ -1201,7 +1202,7 @@ static void correct_uv_aspect(Scene *scene, Object *ob, BMEditMesh *em)
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;
@@ -1222,7 +1223,7 @@ static void uv_map_clip_correct_properties(wmOperatorType *ot)
"Scale UV coordinates to bounds after unwrapping");
}
-static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOperator *op)
+static void uv_map_clip_correct_multi(Scene *scene, Object **objects, uint objects_len, wmOperator *op)
{
BMFace *efa;
BMLoop *l;
@@ -1233,25 +1234,46 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOper
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");
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+ INIT_MINMAX2(min, max);
- /* correct for image aspect ratio */
- if (correct_aspect)
- correct_uv_aspect(scene, ob, em);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
- if (scale_to_bounds) {
- INIT_MINMAX2(min, max);
+ 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;
+ /* correct for image aspect ratio */
+ if (correct_aspect)
+ correct_uv_aspect(scene, ob, em);
- 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);
+ 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]);
@@ -1261,33 +1283,32 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOper
if (dy > 0.0f)
dy = 1.0f / dy;
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
- continue;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- luv->uv[0] = (luv->uv[0] - min[0]) * dx;
- luv->uv[1] = (luv->uv[1] - min[1]) * dy;
- }
- }
- }
- 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_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);
+ 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);
+}
+
/* ******************** Unwrap operator **************** */
/* assumes UV Map is checked, doesn't run update funcs */
@@ -1337,7 +1358,7 @@ static int unwrap_exec(bContext *C, wmOperator *op)
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
if (!uvedit_have_selection_multi(scene, objects, objects_len, implicit)) {
- MEM_SAFE_FREE(objects);
+ MEM_freeN(objects);
return OPERATOR_CANCELLED;
}
@@ -1398,7 +1419,7 @@ static int unwrap_exec(bContext *C, wmOperator *op)
ED_uvedit_pack_islands_multi(scene, objects, objects_len, true, true, true);
- MEM_SAFE_FREE(objects);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -1416,7 +1437,7 @@ void UV_OT_unwrap(wmOperatorType *ot)
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;
@@ -1466,9 +1487,9 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
float rotmat[4][4];
bool changed_multi = false;
+ /* 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, &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);
@@ -1534,13 +1555,21 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
if (changed) {
changed_multi = true;
- uv_map_clip_correct(scene, obedit, em, op);
-
DEG_id_tag_update(obedit->data, 0);
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;
+ }
}
- MEM_SAFE_FREE(objects);
+
+ if (changed_multi) {
+ uv_map_clip_correct_multi(scene, objects, objects_len, op);
+ }
+
+ MEM_freeN(objects);
if (changed_multi) {
return OPERATOR_FINISHED;
@@ -1568,7 +1597,7 @@ void UV_OT_project_from_view(wmOperatorType *ot)
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;
@@ -1623,7 +1652,7 @@ void UV_OT_reset(wmOperatorType *ot)
ot->description = "Reset UV projection";
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* api callbacks */
ot->exec = reset_exec;
ot->poll = ED_operator_uvmap;
@@ -1642,7 +1671,7 @@ static void uv_sphere_project(float target[2], float source[3], float center[3],
/* split line is always zero */
if (target[0] >= 1.0f)
- target[0] -= 1.0f;
+ target[0] -= 1.0f;
}
static void uv_map_mirror(BMEditMesh *em, BMFace *efa)
@@ -1718,7 +1747,7 @@ static int sphere_project_exec(bContext *C, wmOperator *op)
uv_map_mirror(em, efa);
}
- uv_map_clip_correct(scene, obedit, em, op);
+ uv_map_clip_correct(scene, obedit, op);
DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
@@ -1736,7 +1765,7 @@ void UV_OT_sphere_project(wmOperatorType *ot)
ot->description = "Project the UV vertices of the mesh over the curved surface of a sphere";
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* api callbacks */
ot->exec = sphere_project_exec;
ot->poll = ED_operator_uvmap;
@@ -1759,7 +1788,7 @@ static void uv_cylinder_project(float target[2], float source[3], float center[3
/* split line is always zero */
if (target[0] >= 1.0f)
- target[0] -= 1.0f;
+ target[0] -= 1.0f;
}
static int cylinder_project_exec(bContext *C, wmOperator *op)
@@ -1806,7 +1835,7 @@ static int cylinder_project_exec(bContext *C, wmOperator *op)
uv_map_mirror(em, efa);
}
- uv_map_clip_correct(scene, obedit, em, op);
+ uv_map_clip_correct(scene, obedit, op);
DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
@@ -1824,7 +1853,7 @@ void UV_OT_cylinder_project(wmOperatorType *ot)
ot->description = "Project the UV vertices of the mesh over the curved wall of a cylinder";
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* api callbacks */
ot->exec = cylinder_project_exec;
ot->poll = ED_operator_uvmap;
@@ -1923,7 +1952,7 @@ static int cube_project_exec(bContext *C, wmOperator *op)
ED_uvedit_unwrap_cube_project(em->bm, cube_size, true, center);
- uv_map_clip_correct(scene, obedit, em, op);
+ uv_map_clip_correct(scene, obedit, op);
DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
@@ -1941,7 +1970,7 @@ void UV_OT_cube_project(wmOperatorType *ot)
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;