add transition rewrite

This commit is contained in:
itsmattkc
2019-02-18 03:13:27 -08:00
parent 886c5f1273
commit d1037d4ffa
6 changed files with 215 additions and 156 deletions
+11 -2
View File
@@ -46,6 +46,7 @@
#include "panels/grapheditor.h"
#include "ui/viewerwidget.h"
#include "io/clipboard.h"
#include "io/config.h"
#include "ui/timelineheader.h"
#include "ui/keyframeview.h"
#include "ui/resizablescrollbar.h"
@@ -103,10 +104,18 @@ void EffectControls::menu_select(QAction* q) {
const EffectMeta* meta = reinterpret_cast<const EffectMeta*>(q->data().value<quintptr>());
if (effect_menu_type == EFFECT_TYPE_TRANSITION) {
if (c->opening_transition == nullptr) {
ca->append(new AddTransitionCommand(c, nullptr, nullptr, meta, kTransitionOpening, 30));
ca->append(new AddTransitionCommand(c,
nullptr,
nullptr,
meta,
olive::CurrentConfig.default_transition_length));
}
if (c->closing_transition == nullptr) {
ca->append(new AddTransitionCommand(c, nullptr, nullptr, meta, kTransitionClosing, 30));
ca->append(new AddTransitionCommand(nullptr,
c,
nullptr,
meta,
olive::CurrentConfig.default_transition_length));
}
} else {
ca->append(new AddEffectCommand(c, nullptr, meta));
+30 -8
View File
@@ -78,8 +78,8 @@ Timeline::Timeline(QWidget *parent) :
creating(false),
transition_tool_init(false),
transition_tool_proc(false),
transition_tool_pre_clip(-1),
transition_tool_post_clip(-1),
transition_tool_open_clip(-1),
transition_tool_close_clip(-1),
hand_moving(false),
block_repaints(false),
scroll(0)
@@ -379,11 +379,19 @@ void Timeline::add_transition() {
if (c != nullptr && is_clip_selected(c, true)) {
int transition_to_add = (c->track < 0) ? TRANSITION_INTERNAL_CROSSDISSOLVE : TRANSITION_INTERNAL_LINEARFADE;
if (c->get_opening_transition() == nullptr) {
ca->append(new AddTransitionCommand(c, nullptr, nullptr, get_internal_meta(transition_to_add, EFFECT_TYPE_TRANSITION), kTransitionOpening, 30));
ca->append(new AddTransitionCommand(c,
nullptr,
nullptr,
get_internal_meta(transition_to_add, EFFECT_TYPE_TRANSITION),
olive::CurrentConfig.default_transition_length));
adding = true;
}
if (c->get_closing_transition() == nullptr) {
ca->append(new AddTransitionCommand(c, nullptr, nullptr, get_internal_meta(transition_to_add, EFFECT_TYPE_TRANSITION), kTransitionClosing, 30));
ca->append(new AddTransitionCommand(nullptr,
c,
nullptr,
get_internal_meta(transition_to_add, EFFECT_TYPE_TRANSITION),
olive::CurrentConfig.default_transition_length));
adding = true;
}
}
@@ -2047,16 +2055,30 @@ void move_clip(ComboAction* ca, ClipPtr c, long iin, long iout, long iclip_in, i
ca->append(new MoveClipAction(c, iin, iout, iclip_in, itrack, relative));
if (verify_transitions) {
if (c->get_opening_transition() != nullptr && c->get_opening_transition()->secondary_clip != nullptr && c->get_opening_transition()->secondary_clip->timeline_out != iin) {
// if this is a shared transition, and the corresponding clip will be moved away somehow
if (c->get_opening_transition() != nullptr
&& c->get_opening_transition()->secondary_clip != nullptr
&& c->get_opening_transition()->secondary_clip->timeline_out != iin) {
// separate transition
ca->append(new SetPointer(reinterpret_cast<void**>(&c->get_opening_transition()->secondary_clip), nullptr));
ca->append(new AddTransitionCommand(c->get_opening_transition()->secondary_clip, nullptr, c->get_opening_transition(), nullptr, kTransitionClosing, 0));
ca->append(new AddTransitionCommand(nullptr,
c->get_opening_transition()->secondary_clip,
c->get_opening_transition(),
nullptr,
0));
}
if (c->get_closing_transition() != nullptr && c->get_closing_transition()->secondary_clip != nullptr && c->get_closing_transition()->parent_clip->timeline_in != iout) {
if (c->get_closing_transition() != nullptr
&& c->get_closing_transition()->secondary_clip != nullptr
&& c->get_closing_transition()->parent_clip->timeline_in != iout) {
// separate transition
ca->append(new SetPointer(reinterpret_cast<void**>(&c->get_closing_transition()->secondary_clip), nullptr));
ca->append(new AddTransitionCommand(c, nullptr, c->get_closing_transition(), nullptr, kTransitionClosing, 0));
ca->append(new AddTransitionCommand(nullptr,
c,
c->get_closing_transition(),
nullptr,
0));
}
}
}
+2 -3
View File
@@ -177,9 +177,8 @@ public:
// transition variables
bool transition_tool_init;
bool transition_tool_proc;
int transition_tool_pre_clip;
int transition_tool_post_clip;
int transition_tool_type;
int transition_tool_open_clip;
int transition_tool_close_clip;
const EffectMeta* transition_tool_meta;
int transition_tool_side;
+40 -31
View File
@@ -220,55 +220,64 @@ void AddEffectCommand::doRedo() {
done = true;
}
AddTransitionCommand::AddTransitionCommand(ClipPtr c,
ClipPtr s,
AddTransitionCommand::AddTransitionCommand(ClipPtr iopen,
ClipPtr iclose,
TransitionPtr copy,
const EffectMeta *itransition,
int itype,
int ilength) {
primary = c;
secondary = s;
transition_to_copy = copy;
open_ = iopen;
close_ = iclose;
transition_to_copy_ = copy;
transition_meta_ = itransition;
type = itype;
length = ilength;
length_ = ilength;
new_transition_ref_ = nullptr;
}
void AddTransitionCommand::doUndo() {
if (type == kTransitionOpening) {
primary->opening_transition = old_ptransition;
if (secondary != nullptr) secondary->closing_transition = old_stransition;
} else {
primary->closing_transition = old_ptransition;
if (secondary != nullptr) secondary->opening_transition = old_stransition;
if (open_ != nullptr) {
open_->opening_transition = old_open_transition_;
}
if (close_ != nullptr) {
close_->closing_transition = old_close_transition_;
}
}
void AddTransitionCommand::doRedo() {
// store old transition of primary clip
old_ptransition = primary->opening_transition;
// create new transition object
TransitionPtr new_transition;
if (transition_to_copy == nullptr) {
new_transition = get_transition_from_meta(primary, secondary, transition_meta_);
} else {
new_transition = transition_to_copy->copy(primary, nullptr);
// convert open/close clips to primary/secondary for transition object
ClipPtr primary = open_;
ClipPtr secondary = close_;
if (primary == nullptr) {
primary = secondary;
secondary = nullptr;
}
primary->opening_transition = new_transition;
// create new transition object
if (new_transition_ref_ == nullptr) {
if (transition_to_copy_ == nullptr) {
new_transition_ref_ = get_transition_from_meta(primary, secondary, transition_meta_);
} else {
new_transition_ref_ = transition_to_copy_->copy(primary, nullptr);
}
}
if (secondary != nullptr) {
// store old secondary transition
old_stransition = secondary->closing_transition;
// set opening clip's opening transition to this and store the old one
if (open_ != nullptr) {
old_open_transition_ = open_->opening_transition;
// set secondary transition to the same transition
secondary->closing_transition = new_transition;
open_->opening_transition = new_transition_ref_;
}
// set closing clip's closing transition to this and store the old one
if (close_ != nullptr) {
old_close_transition_ = close_->closing_transition;
close_->closing_transition = new_transition_ref_;
}
// if a length was specified, set it now
if (length > 0) {
new_transition->set_length(length);
if (length_ > 0) {
new_transition_ref_->set_length(length_);
}
}
+8 -8
View File
@@ -138,18 +138,18 @@ private:
class AddTransitionCommand : public OliveAction {
public:
AddTransitionCommand(ClipPtr c, ClipPtr s, TransitionPtr copy, const EffectMeta* itransition, int itype, int ilength);
AddTransitionCommand(ClipPtr iopen, ClipPtr iclose, TransitionPtr copy, const EffectMeta* itransition, int ilength);
virtual void doUndo() override;
virtual void doRedo() override;
private:
ClipPtr primary;
ClipPtr secondary;
TransitionPtr transition_to_copy;
ClipPtr open_;
ClipPtr close_;
TransitionPtr transition_to_copy_;
const EffectMeta* transition_meta_;
int type;
int length;
TransitionPtr old_ptransition;
TransitionPtr old_stransition;
int length_;
TransitionPtr old_open_transition_;
TransitionPtr old_close_transition_;
TransitionPtr new_transition_ref_;
};
class ModifyTransitionCommand : public OliveAction {
+124 -104
View File
@@ -836,7 +836,8 @@ void TimelineWidget::mousePressEvent(QMouseEvent *event) {
{
// if there is a clip to run the transition tool on, initiate the transition tool
if (panel_timeline->transition_tool_pre_clip > -1) {
if (panel_timeline->transition_tool_open_clip > -1
|| panel_timeline->transition_tool_close_clip > -1) {
panel_timeline->transition_tool_init = true;
}
@@ -1167,75 +1168,85 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
long transition_start = qMin(g.in, g.out);
long transition_end = qMax(g.in, g.out);
ClipPtr open = (panel_timeline->transition_tool_open_clip > -1)
? olive::ActiveSequence->clips.at(panel_timeline->transition_tool_open_clip)
: nullptr;
ClipPtr pre = olive::ActiveSequence->clips.at(g.clip);
ClipPtr post = pre;
ClipPtr close = (panel_timeline->transition_tool_close_clip > -1)
? olive::ActiveSequence->clips.at(panel_timeline->transition_tool_close_clip)
: nullptr;
make_room_for_transition(ca, pre, panel_timeline->transition_tool_type, transition_start, transition_end, true);
bool shared_transition = (open != nullptr && close != nullptr);
if (panel_timeline->transition_tool_post_clip > -1) {
// post_clip == -1 means this will be just one transition on one clip rather than a shared transition
// between two clips
if (open != nullptr) {
open->undeletable = true;
}
if (close != nullptr) {
close->undeletable = true;
}
post = olive::ActiveSequence->clips.at(panel_timeline->transition_tool_post_clip);
// delete everything under this new transition
QVector<Selection> areas;
Selection s;
s.in = transition_start;
s.out = transition_end;
s.track = g.track;
areas.append(s);
panel_timeline->delete_areas_and_relink(ca, areas, false);
// get opposite transition type
int opposite_type = (panel_timeline->transition_tool_type == kTransitionOpening) ?
kTransitionClosing : kTransitionOpening;
if (open != nullptr) {
open->undeletable = false;
}
if (close != nullptr) {
close->undeletable = false;
}
make_room_for_transition(
ca,
post,
opposite_type,
transition_start,
transition_end,
true
);
if (panel_timeline->transition_tool_type == kTransitionClosing) {
// swap
ClipPtr temp = pre;
pre = post;
post = temp;
if (open != nullptr) {
make_room_for_transition(ca, open, kTransitionOpening, transition_start, transition_end, true);
if (transition_start < open->timeline_in || transition_end > open->timeline_out) {
// long effective_out = (close != nullptr) ? close->timeline_out : open->timeline_out;
long new_in = qMin(transition_start, open->timeline_in);
long new_out = qMax(transition_end, open->timeline_out);
move_clip(ca,
open,
new_in,
new_out,
open->clip_in - (open->timeline_in - new_in),
open->track);
}
}
if (transition_start < post->timeline_in || transition_end > pre->timeline_out) {
// if the user extended the transition beyond the clip's boundaries, delete the content there and extend
// the clip to fill these new boundaries
if (close != nullptr) {
make_room_for_transition(ca, close, kTransitionClosing, transition_start, transition_end, true);
QVector<Selection> areas;
Selection s;
s.track = post->track;
if (transition_start < close->timeline_in || transition_end > close->timeline_out) {
// long effective_in = (open != nullptr) ? open->timeline_in : close->timeline_in;
long new_in = qMin(transition_start, close->timeline_in);
long new_out = qMax(transition_end, close->timeline_out);
bool move_post = false;
bool move_pre = false;
if (transition_start < post->timeline_in) {
s.in = transition_start;
s.out = post->timeline_in;
areas.append(s);
move_post = true;
move_clip(ca,
close,
new_in,
new_out,
close->clip_in - (close->timeline_in - new_in),
close->track);
}
if (transition_end > pre->timeline_out) {
s.in = pre->timeline_out;
s.out = transition_end;
areas.append(s);
move_pre = true;
}
panel_timeline->delete_areas_and_relink(ca, areas, false);
if (move_post) move_clip(ca, post, qMin(transition_start, post->timeline_in), post->timeline_out, post->clip_in - (post->timeline_in - transition_start), post->track);
if (move_pre) move_clip(ca, pre, pre->timeline_in, qMax(transition_end, pre->timeline_out), pre->clip_in, pre->track);
}
if (panel_timeline->transition_tool_post_clip > -1) {
ca->append(new AddTransitionCommand(pre, post, nullptr, panel_timeline->transition_tool_meta, kTransitionOpening, transition_end - pre->timeline_in));
} else {
ca->append(new AddTransitionCommand(pre, nullptr, nullptr, panel_timeline->transition_tool_meta, panel_timeline->transition_tool_type, transition_end - transition_start));
long transition_length = transition_end - transition_start;
if (shared_transition) {
transition_length /= 2;
}
ca->append(new AddTransitionCommand(open,
close,
nullptr,
panel_timeline->transition_tool_meta,
transition_length));
push_undo = true;
}
} else if (panel_timeline->splitting) {
@@ -1573,13 +1584,14 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) {
}
}
} else if (effective_tool == TIMELINE_TOOL_TRANSITION) {
if (panel_timeline->transition_tool_post_clip == -1) {
validate_transitions(c, panel_timeline->transition_tool_type, frame_diff);
if (panel_timeline->transition_tool_open_clip == -1
|| panel_timeline->transition_tool_close_clip == -1) {
validate_transitions(c, g.media_stream, frame_diff);
} else {
ClipPtr otc = c; // open transition clip
ClipPtr ctc = olive::ActiveSequence->clips.at(panel_timeline->transition_tool_post_clip); // close transition clip
ClipPtr otc = olive::ActiveSequence->clips.at(panel_timeline->transition_tool_open_clip); // open transition clip
ClipPtr ctc = olive::ActiveSequence->clips.at(panel_timeline->transition_tool_close_clip); // close transition clip
if (panel_timeline->transition_tool_type == kTransitionClosing) {
if (g.media_stream == kTransitionClosing) {
// swap
ClipPtr temp = otc;
otc = ctc;
@@ -1658,10 +1670,11 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) {
g.track += track_diff;
}
} else if (effective_tool == TIMELINE_TOOL_TRANSITION) {
if (panel_timeline->transition_tool_post_clip > -1) {
if (panel_timeline->transition_tool_open_clip > -1
&& panel_timeline->transition_tool_close_clip > -1) {
g.in = g.old_in - frame_diff;
g.out = g.old_out + frame_diff;
} else if (panel_timeline->transition_tool_type == kTransitionOpening) {
} else if (panel_timeline->transition_tool_open_clip == g.clip) {
g.out = g.old_out + frame_diff;
} else {
g.in = g.old_in + frame_diff;
@@ -2441,22 +2454,30 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
} else {
// transition tool is being used but ghosts haven't been set up yet, set them up now
ClipPtr c = olive::ActiveSequence->clips.at(panel_timeline->transition_tool_pre_clip);
int primary_type = kTransitionOpening;
int primary = panel_timeline->transition_tool_open_clip;
if (primary == -1) {
primary_type = kTransitionClosing;
primary = panel_timeline->transition_tool_close_clip;
}
ClipPtr c = olive::ActiveSequence->clips.at(primary);
Ghost g;
g.in = g.old_in = g.out = g.old_out = (panel_timeline->transition_tool_type == kTransitionOpening) ?
g.in = g.old_in = g.out = g.old_out = (primary_type == kTransitionOpening) ?
c->timeline_in
: c->timeline_out;
g.track = c->track;
g.clip = panel_timeline->transition_tool_pre_clip;
g.media_stream = panel_timeline->transition_tool_type;
g.clip = primary;
g.media_stream = primary_type;
g.trim_type = TRIM_NONE;
panel_timeline->ghosts.append(g);
panel_timeline->transition_tool_proc = true;
}
} else {
@@ -2467,8 +2488,8 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
int mouse_clip = getClipIndexFromCoords(panel_timeline->cursor_frame, panel_timeline->cursor_track);
// set default transition tool references to no clip
panel_timeline->transition_tool_pre_clip = -1;
panel_timeline->transition_tool_post_clip = -1;
panel_timeline->transition_tool_open_clip = -1;
panel_timeline->transition_tool_close_clip = -1;
if (mouse_clip > -1) {
@@ -2479,35 +2500,28 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
// check if the clip and transition are both the same sign (meaning video/audio are the same)
if (same_sign(c->track, panel_timeline->transition_tool_side)) {
// set "pre" clip to the hovered clip
panel_timeline->transition_tool_pre_clip = mouse_clip;
// set whether the transition is opening or closing based on whether the cursor is on the left half
// or right half of the clip
if (panel_timeline->cursor_frame > (c->timeline_in + (c->getLength()/2))) {
panel_timeline->transition_tool_type = kTransitionClosing;
} else {
panel_timeline->transition_tool_type = kTransitionOpening;
}
// the range within which the transition tool will assume the user wants to make a shared transition
// between two clips rather than just one transition on one clip
long between_range = getFrameFromScreenPoint(panel_timeline->zoom, TRANSITION_BETWEEN_RANGE) + 1;
// if the cursor is within this range, set the post_clip to be the next clip touching
//
// getClipIndexFromCoords() will automatically set to -1 if there's no clip there which means the
// end result will be the same as not setting a clip here at all
if (panel_timeline->cursor_frame < c->timeline_in + between_range) {
// set whether the transition is opening or closing based on whether the cursor is on the left half
// or right half of the clip
if (panel_timeline->cursor_frame > (c->timeline_in + (c->getLength()/2))) {
panel_timeline->transition_tool_close_clip = mouse_clip;
// get clip touching to the left
panel_timeline->transition_tool_post_clip = getClipIndexFromCoords(c->timeline_in-1, c->track);
} else if (panel_timeline->cursor_frame > c->timeline_out - between_range) {
// get clip touching to the right
panel_timeline->transition_tool_post_clip = getClipIndexFromCoords(c->timeline_out+1, c->track);
// if the cursor is within this range, set the post_clip to be the next clip touching
//
// getClipIndexFromCoords() will automatically set to -1 if there's no clip there which means the
// end result will be the same as not setting a clip here at all
if (panel_timeline->cursor_frame > c->timeline_out - between_range) {
panel_timeline->transition_tool_open_clip = getClipIndexFromCoords(c->timeline_out+1, c->track);
}
} else {
panel_timeline->transition_tool_open_clip = mouse_clip;
if (panel_timeline->cursor_frame < c->timeline_in + between_range) {
panel_timeline->transition_tool_close_clip = getClipIndexFromCoords(c->timeline_in-1, c->track);
}
}
}
@@ -2858,27 +2872,33 @@ void TimelineWidget::paintEvent(QPaintEvent*) {
if (clip_rect.bottom() >= 0 && clip_rect.bottom() < height()) p.drawLine(QPoint(qMax(0, clip_rect.left()), clip_rect.bottom()), QPoint(qMin(width(), clip_rect.right()), clip_rect.bottom()));
// draw transition tool
if (panel_timeline->tool == TIMELINE_TOOL_TRANSITION && (panel_timeline->transition_tool_pre_clip == i || panel_timeline->transition_tool_post_clip == i)) {
int type = panel_timeline->transition_tool_type;
if (panel_timeline->transition_tool_post_clip == i) {
// invert transition type
type = (type == kTransitionClosing) ? kTransitionOpening : kTransitionClosing;
}
if (panel_timeline->tool == TIMELINE_TOOL_TRANSITION) {
bool shared_transition = (panel_timeline->transition_tool_open_clip > -1
&& panel_timeline->transition_tool_close_clip > -1);
QRect transition_tool_rect = clip_rect;
if (type == kTransitionClosing) {
if (panel_timeline->transition_tool_post_clip > -1) {
transition_tool_rect.setLeft(transition_tool_rect.right() - TRANSITION_BETWEEN_RANGE);
} else {
transition_tool_rect.setLeft(transition_tool_rect.left() + (3*(transition_tool_rect.width()>>2)));
}
} else {
if (panel_timeline->transition_tool_post_clip > -1) {
bool draw_transition_tool_rect = false;
if (panel_timeline->transition_tool_open_clip == i) {
if (shared_transition) {
transition_tool_rect.setWidth(TRANSITION_BETWEEN_RANGE);
} else {
transition_tool_rect.setWidth(transition_tool_rect.width()>>2);
}
draw_transition_tool_rect = true;
} else if (panel_timeline->transition_tool_close_clip == i) {
if (shared_transition) {
transition_tool_rect.setLeft(transition_tool_rect.right() - TRANSITION_BETWEEN_RANGE);
} else {
transition_tool_rect.setLeft(transition_tool_rect.left() + (3*(transition_tool_rect.width()>>2)));
}
draw_transition_tool_rect = true;
}
if (transition_tool_rect.left() < width() && transition_tool_rect.right() > 0) {
if (draw_transition_tool_rect
&& transition_tool_rect.left() < width()
&& transition_tool_rect.right() > 0) {
if (transition_tool_rect.left() < 0) {
transition_tool_rect.setLeft(0);
}