VSE: Clamp strip handles to video/audio bounds

This initial commit properly clamps handles for video/audio strips, and
provides functionality to enable/disable the behavior for all strip types
(addresses #90280).

Toggling handle clamping is done with "C",
just like with the redesigned slip operator (#137072).

If a strip is not already clamped when you start moving its handles,
then clamping behavior is disabled starting out. This means no abrupt
clamp until you explicitly ask for it.

Transform logic was altered, fixing a few bugs:
- When initializing a transform, `createTransSeqData` would already
  create some clamping data for channels. This patch replaces it with
  `offset_clamp` (for unconditional clamping which cannot be disabled)
  and `handle_xmin/xmax` (for hold offset clamping, which is optional).
    - Collecting this data ahead of time is necessary for the double
      handle tweak case -- `flushTransSeq` only works one strip at a
      time, so we can't clamp post-hoc.
- In `applySeqSlideValue`, we apply `transform_convert_sequencer_clamp`
  before values are printed to the header, but let the unclamped values
  get flushed to the strips themselves. This is so that we can have the
  data later at the individual strip level to recalculate clamps.
  Otherwise, if transform values are clamped preemptively, then we have
  no idea whether strips are clamped vs. merely resting at their
  boundaries.

Note that currently, handle clamping is drawn identically to overlaps.

More information in PR.

Pull Request: https://projects.blender.org/blender/blender/pulls/134319
This commit is contained in:
John Kiril Swenson
2025-07-16 06:16:19 +02:00
committed by John Kiril Swenson
parent 1cb30b9d1e
commit d910fb88b0
19 changed files with 272 additions and 96 deletions

View File

@@ -5981,6 +5981,7 @@ def km_transform_modal_map(params):
("AUTOCONSTRAINPLANE", {"type": 'MIDDLEMOUSE', "value": 'ANY', "shift": True, **alt_without_navigaton}, None),
("PRECISION", {"type": 'LEFT_SHIFT', "value": 'ANY', "any": True}, None),
("PRECISION", {"type": 'RIGHT_SHIFT', "value": 'ANY', "any": True}, None),
("STRIP_CLAMP_TOGGLE", {"type": 'C', "value": 'PRESS', "any": True}, None),
])
if params.use_alt_navigation:
@@ -6601,7 +6602,7 @@ def km_sequencer_slip_modal_map(_params):
("PRECISION_DISABLE", {"type": 'LEFT_SHIFT', "value": 'RELEASE', "any": True}, None),
("PRECISION_ENABLE", {"type": 'RIGHT_SHIFT', "value": 'PRESS', "any": True}, None),
("PRECISION_DISABLE", {"type": 'RIGHT_SHIFT', "value": 'RELEASE', "any": True}, None),
("CLAMP_TOGGLE", {"type": 'C', "value": 'RELEASE', "any": True}, None),
("CLAMP_TOGGLE", {"type": 'C', "value": 'PRESS', "any": True}, None),
])
return keymap

View File

@@ -3611,6 +3611,7 @@ def km_transform_modal_map(_params):
("AUTOCONSTRAINPLANE", {"type": 'MIDDLEMOUSE', "value": 'ANY', "shift": True}, None),
("PRECISION", {"type": 'LEFT_SHIFT', "value": 'ANY', "any": True}, None),
("PRECISION", {"type": 'RIGHT_SHIFT', "value": 'ANY', "any": True}, None),
("STRIP_CLAMP_TOGGLE", {"type": 'C', "value": 'PRESS', "any": True}, None),
])
return keymap