implemented base transition support

While very much incomplete, transitions can now be created and will render
correctly.
This commit is contained in:
itsmattkc
2019-12-12 15:21:39 +11:00
parent 7b92b21df2
commit 76c0399b75
14 changed files with 267 additions and 84 deletions
+1 -1
View File
@@ -60,7 +60,7 @@ TimelineWidget::TimelineWidget(QWidget *parent) :
tools_.replace(olive::tool::kSlide, std::make_shared<SlideTool>(this));
tools_.replace(olive::tool::kHand, std::make_shared<HandTool>(this));
tools_.replace(olive::tool::kZoom, std::make_shared<ZoomTool>(this));
//tools_.replace(olive::tool::kTransition, new (this)); FIXME: Implement
tools_.replace(olive::tool::kTransition, std::make_shared<TransitionTool>(this));
//tools_.replace(olive::tool::kRecord, new PointerTool(this)); FIXME: Implement
tools_.replace(olive::tool::kAdd, std::make_shared<AddTool>(this));
+28 -23
View File
@@ -206,9 +206,9 @@ private:
public:
RazorTool(TimelineWidget* parent);
virtual void MousePress(TimelineViewMouseEvent *event);
virtual void MouseMove(TimelineViewMouseEvent *event);
virtual void MouseRelease(TimelineViewMouseEvent *event);
virtual void MousePress(TimelineViewMouseEvent *event) override;
virtual void MouseMove(TimelineViewMouseEvent *event) override;
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
private:
QVector<TrackReference> split_tracks_;
@@ -269,9 +269,9 @@ private:
public:
HandTool(TimelineWidget* parent);
virtual void MousePress(TimelineViewMouseEvent *event);
virtual void MouseMove(TimelineViewMouseEvent *event);
virtual void MouseRelease(TimelineViewMouseEvent *event);
virtual void MousePress(TimelineViewMouseEvent *event) override;
virtual void MouseMove(TimelineViewMouseEvent *event) override;
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
private:
QPoint screen_drag_start_;
QPoint scrollbar_start_;
@@ -282,19 +282,9 @@ private:
public:
ZoomTool(TimelineWidget* parent);
virtual void MousePress(TimelineViewMouseEvent *event);
virtual void MouseMove(TimelineViewMouseEvent *event);
virtual void MouseRelease(TimelineViewMouseEvent *event);
};
class TransitionTool : public Tool
{
public:
TransitionTool(TimelineWidget* parent);
virtual void MousePress(TimelineViewMouseEvent *event);
virtual void MouseMove(TimelineViewMouseEvent *event);
virtual void MouseRelease(TimelineViewMouseEvent *event);
virtual void MousePress(TimelineViewMouseEvent *event) override;
virtual void MouseMove(TimelineViewMouseEvent *event) override;
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
};
class AddTool : public Tool
@@ -302,12 +292,27 @@ private:
public:
AddTool(TimelineWidget* parent);
virtual void MousePress(TimelineViewMouseEvent *event);
virtual void MouseMove(TimelineViewMouseEvent *event);
virtual void MouseRelease(TimelineViewMouseEvent *event);
virtual void MousePress(TimelineViewMouseEvent *event) override;
virtual void MouseMove(TimelineViewMouseEvent *event) override;
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
protected:
void MouseMoveInternal(const rational& cursor_frame, bool outwards);
private:
TimelineViewGhostItem* ghost_;
rational drag_start_point_;
};
class TransitionTool : public AddTool
{
public:
TransitionTool(TimelineWidget* parent);
virtual void MousePress(TimelineViewMouseEvent *event) override;
virtual void MouseMove(TimelineViewMouseEvent *event) override;
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
protected:
};
void SetBlockLinksSelected(Block *block, bool selected);
+42 -25
View File
@@ -17,42 +17,25 @@ void TimelineWidget::AddTool::MousePress(TimelineViewMouseEvent *event)
return;
}
drag_start_point_ = event->GetCoordinates().GetFrame();
ghost_ = new TimelineViewGhostItem();
ghost_->SetIn(event->GetCoordinates().GetFrame());
ghost_->SetOut(event->GetCoordinates().GetFrame());
ghost_->SetIn(drag_start_point_);
ghost_->SetOut(drag_start_point_);
ghost_->SetTrack(track);
ghost_->SetYCoords(parent()->GetTrackY(track), parent()->GetTrackHeight(track));
parent()->AddGhost(ghost_);
snap_points_.append(event->GetCoordinates().GetFrame());
snap_points_.append(drag_start_point_);
}
void TimelineWidget::AddTool::MouseMove(TimelineViewMouseEvent *event)
{
const rational& cursor_frame = event->GetCoordinates().GetFrame();
// Calculate movement
rational movement = cursor_frame - ghost_->Out();
// Snap movement
SnapPoint(snap_points_, &movement);
// Validation: Ensure in point never goes below 0
if (movement < -ghost_->In()) {
movement = -ghost_->In();
if (!ghost_) {
return;
}
// Make adjustment
if (!movement) {
ghost_->SetInAdjustment(0);
ghost_->SetOutAdjustment(0);
} else if (movement > 0) {
ghost_->SetInAdjustment(0);
ghost_->SetOutAdjustment(movement);
} else if (movement < 0) {
ghost_->SetInAdjustment(movement);
ghost_->SetOutAdjustment(0);
}
MouseMoveInternal(event->GetCoordinates().GetFrame(), event->GetModifiers() & Qt::AltModifier);
}
void TimelineWidget::AddTool::MouseRelease(TimelineViewMouseEvent *event)
@@ -76,3 +59,37 @@ void TimelineWidget::AddTool::MouseRelease(TimelineViewMouseEvent *event)
ghost_ = nullptr;
}
}
void TimelineWidget::AddTool::MouseMoveInternal(const rational &cursor_frame, bool outwards)
{
// Calculate movement
rational movement = cursor_frame - drag_start_point_;
// Snap movement
bool snapped = SnapPoint(snap_points_, &movement);
// If alt is held, our movement goes both ways (outwards)
if (!snapped && outwards) {
// Snap backwards too
movement = -movement;
SnapPoint(snap_points_, &movement);
// We don't need to un-neg here because outwards means all future processing will be done both pos and neg
}
// Validation: Ensure in point never goes below 0
if (movement < -ghost_->In() || (outwards && -movement < -ghost_->In())) {
movement = -ghost_->In();
}
// Make adjustment
if (!movement) {
ghost_->SetInAdjustment(0);
ghost_->SetOutAdjustment(0);
} else if (movement > 0) {
ghost_->SetInAdjustment(outwards ? -movement : 0);
ghost_->SetOutAdjustment(movement);
} else if (movement < 0) {
ghost_->SetInAdjustment(movement);
ghost_->SetOutAdjustment(outwards ? -movement : 0);
}
}
+84 -9
View File
@@ -1,29 +1,104 @@
#include "widget/timelinewidget/timelinewidget.h"
#include "node/block/transition/crossdissolve/crossdissolve.h"
#include "widget/nodeview/nodeviewundo.h"
TimelineWidget::TransitionTool::TransitionTool(TimelineWidget *parent) :
Tool(parent)
AddTool(parent)
{
}
void TimelineWidget::TransitionTool::MousePress(TimelineViewMouseEvent *event)
{
TimelineViewBlockItem* item = GetItemAtScenePos(event->GetCoordinates());
const TrackReference& track = event->GetCoordinates().GetTrack();
TrackOutput* t = parent()->GetTrackFromReference(track);
rational cursor_frame = event->GetCoordinates().GetFrame();
bool selectable_item = (item != nullptr
&& item->flags() & QGraphicsItem::ItemIsSelectable
&& !parent()->GetTrackFromReference(item->Track())->IsLocked());
if (!selectable_item) {
if (!t || t->IsLocked()) {
return;
}
Block* block_at_time = t->BlockAtTime(event->GetCoordinates().GetFrame());
if (!block_at_time || block_at_time->type() != Block::kClip) {
return;
}
// Determine which side of the clip the transition belongs to
rational transition_start_point;
olive::timeline::MovementMode trim_mode;
rational halfway_point = block_at_time->in() + block_at_time->length() / 2;
if (cursor_frame < halfway_point) {
transition_start_point = block_at_time->in();
trim_mode = olive::timeline::kTrimIn;
} else {
transition_start_point = block_at_time->out();
trim_mode = olive::timeline::kTrimOut;
}
// Create ghost
ghost_ = new TimelineViewGhostItem();
ghost_->SetTrack(track);
ghost_->SetYCoords(parent()->GetTrackY(track), parent()->GetTrackHeight(track));
ghost_->SetIn(transition_start_point);
ghost_->SetOut(transition_start_point);
ghost_->SetMode(trim_mode);
ghost_->setData(TimelineViewGhostItem::kAttachedBlock, Node::PtrToValue(block_at_time));
parent()->AddGhost(ghost_);
snap_points_.append(transition_start_point);
// Set the drag start point
drag_start_point_ = cursor_frame;
}
void TimelineWidget::TransitionTool::MouseMove(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
if (!ghost_) {
return;
}
MouseMoveInternal(event->GetCoordinates().GetFrame(), false);
}
void TimelineWidget::TransitionTool::MouseRelease(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
MouseMove(event);
const TrackReference& track = ghost_->Track();
if (ghost_) {
if (!ghost_->AdjustedLength().isNull()) {
Block* block_to_transition = Node::ValueToPtr<Block>(ghost_->data(TimelineViewGhostItem::kAttachedBlock));
CrossDissolveTransition* transition = new CrossDissolveTransition();
NodeInput* transition_input_to_connect;
if (ghost_->mode() == olive::timeline::kTrimIn) {
transition->set_in_and_out_offset(ghost_->AdjustedLength(), 0);
transition_input_to_connect = transition->in_block_input();
} else {
transition->set_in_and_out_offset(0, ghost_->AdjustedLength());
transition_input_to_connect = transition->out_block_input();
}
QUndoCommand* command = new QUndoCommand();
// Place transition in place
new TrackPlaceBlockCommand(parent()->timeline_node_->track_list(track.type()),
track.index(),
transition,
ghost_->GetAdjustedIn(),
command);
// Connect block to transition
new NodeEdgeAddCommand(block_to_transition->output(),
transition_input_to_connect,
command);
olive::undo_stack.push(command);
}
parent()->ClearGhosts();
snap_points_.clear();
ghost_ = nullptr;
}
}
@@ -28,6 +28,7 @@
#include <QStyleOptionGraphicsItem>
#include "common/qtversionabstraction.h"
#include "node/block/transition/transition.h"
TimelineViewBlockItem::TimelineViewBlockItem(QGraphicsItem* parent) :
TimelineViewRect(parent),
@@ -80,14 +81,14 @@ void TimelineViewBlockItem::paint(QPainter *painter, const QStyleOptionGraphicsI
switch (block_->type()) {
case Block::kClip:
case Block::kTransition: // FIXME: Temporary, the transition should have its own UI representation at some point
/*QLinearGradient grad;
{
QLinearGradient grad;
grad.setStart(0, rect().top());
grad.setFinalStop(0, rect().bottom());
grad.setColorAt(0.0, QColor(160, 160, 240));
grad.setColorAt(1.0, QColor(128, 128, 192));
painter->fillRect(rect(), grad);*/
painter->fillRect(rect(), QColor(128, 128, 192));
painter->fillRect(rect(), grad);
//painter->fillRect(rect(), QColor(128, 128, 192));
if (option->state & QStyle::State_Selected) {
painter->fillRect(rect(), QColor(0, 0, 0, 64));
@@ -114,12 +115,39 @@ void TimelineViewBlockItem::paint(QPainter *painter, const QStyleOptionGraphicsI
painter->drawLine(QPointF(rect().left(), rect().bottom() - 1), QPointF(rect().right(), rect().bottom() - 1));
painter->drawLine(QPointF(rect().right(), rect().bottom() - 1), QPointF(rect().right(), rect().top()));
break;
}
case Block::kGap:
if (option->state & QStyle::State_Selected) {
// FIXME: Make this palette or CSS
painter->fillRect(rect(), Qt::white);
}
break;
case Block::kTransition:
{
painter->setBrush(QColor(128, 96, 192));
painter->setPen(QColor(48, 32, 64));
painter->drawRect(rect());
TransitionBlock* t = static_cast<TransitionBlock*>(block_);
if (t->out_block_input()->IsConnected()) {
// Transition fades something out, we'll draw a line
painter->drawLine(rect().topLeft(), rect().bottomRight());
}
if (t->in_block_input()->IsConnected()) {
// Transition fades something in, we'll draw a line
painter->drawLine(rect().bottomLeft(), rect().topRight());
}
if (t->out_block_input()->IsConnected() && t->in_block_input()->IsConnected()) {
// Draw line between out offset and in offset
qreal crossover_line = rect().left();
crossover_line += TimeToScene(t->out_offset());
painter->drawLine(qRound(crossover_line),
qRound(rect().top()),
qRound(crossover_line),
qRound(rect().bottom()));
}
break;
}
case Block::kTrack:
break;
}