Ручку затухания можно взять и во второй раз
Зона захвата совпадала с нарисованным квадратиком — девять точек на девять. Пока затухание нулевое, ручка стоит в углу клипа и целиться есть куда; стоит её сдвинуть, она висит посреди клипа сама по себе, и попасть в неё почти нельзя. Зона захвата теперь шире нарисованного: по шесть точек в стороны и семь вниз, внутрь клипа, — рука уводит курсор туда, а не выше клипа. Если на узком клипе зоны обеих ручек налезли друг на друга, берётся та, к которой ближе. Заодно над зоной меняется курсор. Раньше над ручкой он был такой же, как над всем клипом, и где она — узнать было нельзя. Проверено протяжкой мыши на невидимом экране (tests/fadegrab.sh): первый захват за угол даёт затухание 1.387 с, второй — с прицелом на пять точек ниже и четыре в стороне от середины ручки — доводит до 2.261 с. На сборке из прошлого коммита второй захват не делает ничего.
This commit is contained in:
parent
44c0a5de24
commit
e8cb3cc392
3 changed files with 141 additions and 17 deletions
|
|
@ -224,6 +224,13 @@ Ctrl+Shift+R, который схлопывает дыру под курсоро
|
|||
двойной. Ручка стоит посередине именно видимой части, а не всего клипа:
|
||||
до середины часового клипа, уехавшей за край экрана, мышью не дотянуться.
|
||||
|
||||
**Затухания тянутся за ручки в верхних углах клипа.** Взять их можно и
|
||||
промахнувшись: зона захвата шире нарисованного квадратика и уходит внутрь
|
||||
клипа. Пока затухание нулевое, ручка стоит в самом углу и целиться есть
|
||||
куда; стоит её сдвинуть — она висит посреди клипа сама по себе, и попасть
|
||||
в девять точек почти нельзя. Над зоной захвата меняется курсор — по нему
|
||||
и видно, где взять (`tests/fadegrab.sh`).
|
||||
|
||||
Громкость, отличная от обычной, — единственное место, где звук
|
||||
перекодируется: изменить громкость, не тронув сам звук, нельзя. Видео при
|
||||
этом по-прежнему копируется. Проверено: клип с громкостью 30% дал в ролике
|
||||
|
|
|
|||
|
|
@ -211,6 +211,14 @@ type
|
|||
procedure DrawFades(ACanvas: TCanvas; AClip: TClip; const ABody: TRect);
|
||||
{ Ручка затухания. AIn = True — появление (левый угол), иначе уход. }
|
||||
function FadeHandleRect(AClip: TClip; ATop: Integer; AIn: Boolean): TRect;
|
||||
{ Зона, в которой ручку затухания можно взять. Она шире нарисованной
|
||||
ручки: пока затухание нулевое, ручка стоит в углу клипа и целиться
|
||||
есть куда, а после протяжки она висит посреди клипа сама по себе, и
|
||||
попасть в девять точек почти нельзя. }
|
||||
function FadeGrabRect(AClip: TClip; ATop: Integer; AIn: Boolean): TRect;
|
||||
{ Какую из двух ручек затухания берут в этой точке. Пусто — ни одну. }
|
||||
function FadeAtPoint(AClip: TClip; const AX, AY, ATop: Integer;
|
||||
out AIn: Boolean): Boolean;
|
||||
{ Полоса перекрытия двух клипов одной дорожки: там сам собой выходит
|
||||
переход, и это надо видеть. }
|
||||
procedure DrawOverlaps(ACanvas: TCanvas; ATrack: TTrack; ATop: Integer);
|
||||
|
|
@ -1192,6 +1200,52 @@ begin
|
|||
Exit(Rect(0, 0, 0, 0));
|
||||
end;
|
||||
|
||||
function TTimelineControl.FadeGrabRect(AClip: TClip; ATop: Integer;
|
||||
AIn: Boolean): TRect;
|
||||
const
|
||||
{ По сторонам — чтобы не целиться по горизонтали в девять точек. Вниз —
|
||||
потому что ручка сидит на верхней грани клипа, и рука уводит курсор
|
||||
внутрь клипа, а не выше него. }
|
||||
PadX = 6;
|
||||
PadDown = 7;
|
||||
begin
|
||||
Result := FadeHandleRect(AClip, ATop, AIn);
|
||||
if Result.Right <= Result.Left then
|
||||
Exit;
|
||||
Dec(Result.Left, PadX);
|
||||
Inc(Result.Right, PadX);
|
||||
Inc(Result.Bottom, PadDown);
|
||||
if Result.Left < FHeaderWidth then
|
||||
Result.Left := FHeaderWidth;
|
||||
end;
|
||||
|
||||
function TTimelineControl.FadeAtPoint(AClip: TClip; const AX, AY,
|
||||
ATop: Integer; out AIn: Boolean): Boolean;
|
||||
var
|
||||
RIn, ROut: TRect;
|
||||
HitIn, HitOut: Boolean;
|
||||
begin
|
||||
AIn := False;
|
||||
RIn := FadeGrabRect(AClip, ATop, True);
|
||||
ROut := FadeGrabRect(AClip, ATop, False);
|
||||
HitIn := (RIn.Right > RIn.Left) and PtInRect(RIn, Point(AX, AY));
|
||||
HitOut := (ROut.Right > ROut.Left) and PtInRect(ROut, Point(AX, AY));
|
||||
|
||||
{ Зоны расширены, и на коротком клипе они могут налезть друг на друга.
|
||||
Тогда берём ту ручку, к которой ближе: другого разумного ответа нет. }
|
||||
if HitIn and HitOut then
|
||||
HitOut := Abs(AX - (ROut.Left + ROut.Right) div 2) <
|
||||
Abs(AX - (RIn.Left + RIn.Right) div 2);
|
||||
|
||||
if HitOut then
|
||||
begin
|
||||
AIn := False;
|
||||
Exit(True);
|
||||
end;
|
||||
Result := HitIn;
|
||||
AIn := HitIn;
|
||||
end;
|
||||
|
||||
procedure TTimelineControl.DrawFades(ACanvas: TCanvas; AClip: TClip;
|
||||
const ABody: TRect);
|
||||
var
|
||||
|
|
@ -2028,7 +2082,7 @@ var
|
|||
Part: THeaderPart;
|
||||
VolHandle: TRect;
|
||||
CropRect: TRect;
|
||||
FadeHandle: TRect;
|
||||
FadeIsIn: Boolean;
|
||||
begin
|
||||
inherited MouseDown(Button, Shift, X, Y);
|
||||
SetFocus;
|
||||
|
|
@ -2204,23 +2258,12 @@ begin
|
|||
{ Ручки затухания стоят в верхних углах, а там же начинается зона
|
||||
растягивания за край. Приоритет у ручек: они мелкие, промахнуться
|
||||
мимо них легче, а растянуть клип можно, взявшись за край ниже. }
|
||||
FadeHandle := FadeHandleRect(Clip, TrackTop(TrackIndexAt(Y)), True);
|
||||
if (FadeHandle.Right > FadeHandle.Left) and
|
||||
PtInRect(FadeHandle, Point(X, Y)) then
|
||||
if FadeAtPoint(Clip, X, Y, TrackTop(TrackIndexAt(Y)), FadeIsIn) then
|
||||
begin
|
||||
FAction := taFadeIn;
|
||||
FProject.BeginChange;
|
||||
FPressX := X;
|
||||
FPressY := Y;
|
||||
FMovedWhileDown := False;
|
||||
Invalidate;
|
||||
Exit;
|
||||
end;
|
||||
FadeHandle := FadeHandleRect(Clip, TrackTop(TrackIndexAt(Y)), False);
|
||||
if (FadeHandle.Right > FadeHandle.Left) and
|
||||
PtInRect(FadeHandle, Point(X, Y)) then
|
||||
begin
|
||||
FAction := taFadeOut;
|
||||
if FadeIsIn then
|
||||
FAction := taFadeIn
|
||||
else
|
||||
FAction := taFadeOut;
|
||||
FProject.BeginChange;
|
||||
FPressX := X;
|
||||
FPressY := Y;
|
||||
|
|
@ -2278,6 +2321,7 @@ var
|
|||
Clip: TClip;
|
||||
Track, TargetTrack: TTrack;
|
||||
VolHandle: TRect;
|
||||
FadeIsIn: Boolean;
|
||||
begin
|
||||
inherited MouseMove(Shift, X, Y);
|
||||
VolHandle := Rect(0, 0, 0, 0);
|
||||
|
|
@ -2307,6 +2351,12 @@ begin
|
|||
(X >= VolHandle.Left) and (X <= VolHandle.Right) and
|
||||
(Y >= VolHandle.Top - 3) and (Y <= VolHandle.Bottom + 3) then
|
||||
Cursor := crSizeNS
|
||||
{ Ручка затухания мелкая и после протяжки висит посреди клипа, где
|
||||
её ничем не выдать. Пусть выдаёт курсор: он меняется над зоной
|
||||
захвата, и становится видно, где взять. }
|
||||
else if (Clip <> nil) and (Idx >= 0) and
|
||||
FadeAtPoint(Clip, X, Y, TrackTop(Idx), FadeIsIn) then
|
||||
Cursor := crSizeWE
|
||||
else if Edge <> 0 then
|
||||
Cursor := crSizeWE
|
||||
else if Clip <> nil then
|
||||
|
|
|
|||
67
tests/fadegrab.sh
Executable file
67
tests/fadegrab.sh
Executable file
|
|
@ -0,0 +1,67 @@
|
|||
#!/bin/sh
|
||||
# Повторный захват рампы затухания.
|
||||
#
|
||||
# Первый раз ручка стоит в правом верхнем углу клипа — целиться есть куда.
|
||||
# Второй раз она висит посреди клипа сама по себе, и целятся в неё на
|
||||
# глаз: чуть ниже и чуть в стороне от середины. Оба захвата обязаны
|
||||
# сработать.
|
||||
# Запуск (редактор должен собираться в этом дереве, экран :99 поднят):
|
||||
# tests/fadegrab.sh [<путь к nlve>]
|
||||
BIN=${1:-$PWD/nlve}
|
||||
cd "$(dirname "$0")/.."
|
||||
BIN=${1:-$PWD/nlve}
|
||||
PROJ=$PWD/test/поток/рампа.nlve
|
||||
# Монтаж для проверки: два клипа без затуханий. В репозиторий не входит —
|
||||
# ссылается на съёмку, которой здесь нет.
|
||||
[ -f test/поток/пара.nlve ] || { echo "нет монтажа test/поток/пара.nlve"; exit 2; }
|
||||
cp test/поток/пара.nlve "$PROJ"
|
||||
for p in $(pgrep -x nlve); do
|
||||
tr '\0' '\n' < /proc/$p/environ 2>/dev/null | grep -qx "DISPLAY=:99" && kill $p
|
||||
done
|
||||
sleep 1
|
||||
rm -rf test/поток/профиль-рампа; mkdir -p test/поток/профиль-рампа
|
||||
rm -f test/поток/*.autosave
|
||||
SP=$PWD/test/поток/профиль-рампа
|
||||
XDG_CONFIG_HOME=$SP XDG_CACHE_HOME=$SP XDG_DATA_HOME=$SP DISPLAY=:99 \
|
||||
setsid "$BIN" "$PROJ" >/dev/null 2>&1 < /dev/null &
|
||||
sleep 14
|
||||
X="timeout 8 env DISPLAY=:99 xdotool"
|
||||
$X windowmove 2097206 0 0 windowsize 2097206 1500 860 2>/dev/null
|
||||
sleep 2
|
||||
|
||||
fade() {
|
||||
$X key ctrl+s
|
||||
sleep 2
|
||||
python3 -c "
|
||||
import json
|
||||
d=json.load(open('$PROJ'))
|
||||
for t in d['tracks']:
|
||||
for c in t['clips']:
|
||||
if c['kind']=='video' and c['tl_start']<0.001:
|
||||
print('%.3f' % c.get('fade_out',0)); raise SystemExit
|
||||
print('нет клипа')
|
||||
"
|
||||
}
|
||||
|
||||
echo " затухание до правок: $(fade) с"
|
||||
$X mousemove 783 490 mousedown 1; sleep 0.3
|
||||
$X mousemove 745 490; sleep 0.2; $X mousemove 720 490; sleep 0.2
|
||||
$X mouseup 1; sleep 1.5
|
||||
A=$(fade)
|
||||
echo " после первого захвата (ручка в углу): $A с"
|
||||
|
||||
$X mousemove 724 495 mousedown 1; sleep 0.3
|
||||
$X mousemove 700 495; sleep 0.2; $X mousemove 680 495; sleep 0.2
|
||||
$X mouseup 1; sleep 1.5
|
||||
B=$(fade)
|
||||
echo " после второго захвата (ручка посреди клипа, мимо центра): $B с"
|
||||
|
||||
python3 -c "
|
||||
a, b = $A, $B
|
||||
if a <= 0.01:
|
||||
print(' ПЛОХО: не сработал даже первый захват')
|
||||
elif b <= a + 0.01:
|
||||
print(' ПЛОХО: второй захват не сработал')
|
||||
else:
|
||||
print(' ok: обе протяжки сработали')
|
||||
"
|
||||
Loading…
Add table
Add a link
Reference in a new issue