timeline import interaction progress

This commit is contained in:
itsmattkc
2019-08-20 11:40:18 +10:00
parent 44f7c0ab40
commit c8dfd09acc
12 changed files with 270 additions and 119 deletions
+3 -28
View File
@@ -218,13 +218,9 @@ void Core::CreateNewFolder()
}
// FIXME: Test code
#include "node/block/clip/clip.h"
#include "node/block/gap/gap.h"
#include "node/input/media/media.h"
#include "node/output/timeline/timeline.h"
#include "node/output/track/track.h"
#include "node/output/viewer/viewer.h"
#include "node/generator/solid/solid.h"
#include "panel/panelmanager.h"
#include "panel/node/node.h"
#include "panel/viewer/viewer.h"
@@ -272,42 +268,21 @@ void Core::CreateNewSequence()
folder,
new_sequence);
// FIXME: Test code
GapBlock* gb = new GapBlock();
gb->set_length(1);
new_sequence->AddNode(gb);
ClipBlock* cb = new ClipBlock();
cb->set_length(2);
new_sequence->AddNode(cb);
TrackOutput* to = new TrackOutput();
new_sequence->AddNode(to);
ClipBlock* cb2 = new ClipBlock();
cb2->set_length(2);
new_sequence->AddNode(cb2);
TrackOutput* to2 = new TrackOutput();
new_sequence->AddNode(to2);
TimelineOutput* tb = new TimelineOutput();
new_sequence->AddNode(tb);
ViewerOutput* vo = new ViewerOutput();
new_sequence->AddNode(vo);
Block::ConnectBlocks(gb, cb);
Block::ConnectBlocks(cb, to);
Block::ConnectBlocks(cb2, to2);
NodeParam::ConnectEdge(to2->track_output(), to->track_input());
TrackOutput* to = new TrackOutput();
new_sequence->AddNode(to);
NodeParam::ConnectEdge(to->texture_output(), vo->texture_input());
NodeParam::ConnectEdge(to->track_output(), tb->track_input());
vo->AttachViewer(olive::panel_focus_manager->MostRecentlyFocused<ViewerPanel>());
tb->AttachTimeline(olive::panel_focus_manager->MostRecentlyFocused<TimelinePanel>());
olive::panel_focus_manager->MostRecentlyFocused<NodePanel>()->SetGraph(new_sequence.get());
// End test code
olive::undo_stack.push(aic);
}
+26 -7
View File
@@ -59,10 +59,10 @@ QString TimelineOutput::Description()
void TimelineOutput::AttachTimeline(TimelinePanel *timeline)
{
if (attached_timeline_ != nullptr) {
//TimelineView* view = attached_timeline_->view();
TimelineView* view = attached_timeline_->view();
//disconnect(view, SIGNAL(RequestInsertBlockAtIndex(Block*, int)), this, SLOT(InsertBlockAtIndex(Block*, int)));
//disconnect(view, SIGNAL(RequestPlaceBlock(Block*, rational)), this, SLOT(PlaceBlock(Block*, rational)));
disconnect(view, SIGNAL(RequestPlaceBlock(Block*, rational, int)), this, SLOT(PlaceBlock(Block*, rational, int)));
// Remove existing UI objects from TimelinePanel
attached_timeline_->Clear();
@@ -80,10 +80,10 @@ void TimelineOutput::AttachTimeline(TimelinePanel *timeline)
track->GenerateBlockWidgets();
}
//TimelineView* view = attached_timeline_->view();
TimelineView* view = attached_timeline_->view();
//connect(view, SIGNAL(RequestInsertBlockAtIndex(Block*, int)), this, SLOT(InsertBlockAtIndex(Block*, int)));
//connect(view, SIGNAL(RequestPlaceBlock(Block*, rational)), this, SLOT(PlaceBlock(Block*, rational)));
connect(view, SIGNAL(RequestPlaceBlock(Block*, rational, int)), this, SLOT(PlaceBlock(Block*, rational, int)));
}
}
@@ -158,6 +158,18 @@ void TimelineOutput::DetachTrack(TrackOutput *track)
}
}
void TimelineOutput::AddTrack()
{
TrackOutput* track = new TrackOutput();
static_cast<NodeGraph*>(parent())->AddNode(track);
if (track_cache_.isEmpty()) {
NodeParam::ConnectEdge(track->track_output(), track_input());
} else {
NodeParam::ConnectEdge(track->track_output(), track_cache_.last()->track_input());
}
}
void TimelineOutput::TrackConnectionAdded(NodeEdgePtr edge)
{
if (edge->input() != track_input()) {
@@ -189,9 +201,7 @@ void TimelineOutput::TrackConnectionRemoved(NodeEdgePtr edge)
void TimelineOutput::TrackAddedBlock(Block *block)
{
if (attached_timeline_ != nullptr) {
qDebug() << "track index lmao:" << GetTrackIndex(static_cast<TrackOutput*>(sender()));
attached_timeline_->view()->AddBlock(block);
attached_timeline_->view()->AddBlock(block, GetTrackIndex(static_cast<TrackOutput*>(sender())));
}
}
@@ -227,3 +237,12 @@ void TimelineOutput::TrackEdgeRemoved(NodeEdgePtr edge)
DetachTrack(added_track);
}
}
void TimelineOutput::PlaceBlock(Block *block, rational start, int track)
{
while (track >= track_cache_.size()) {
AddTrack();
}
track_cache_.at(track)->PlaceBlock(block, start);
}
+7
View File
@@ -57,6 +57,8 @@ private:
void DetachTrack(TrackOutput* track);
void AddTrack();
TimelinePanel* attached_timeline_;
NodeInput* track_input_;
@@ -97,6 +99,11 @@ private slots:
*/
void TrackEdgeRemoved(NodeEdgePtr edge);
/**
* @brief Forwards a PlaceBlock signal to the requested track
*/
void PlaceBlock(Block* block, rational start, int track);
};
#endif // TIMELINEOUTPUT_H
+45 -43
View File
@@ -56,49 +56,6 @@ public:
NodeOutput* track_output();
signals:
/**
* @brief Signal emitted when a Block is added to this Track
*/
void BlockAdded(Block* block);
/**
* @brief Signal emitted when a Block is removed from this Track
*/
void BlockRemoved(Block* block);
public slots:
virtual void Process(const rational &time) override;
private:
/**
* @brief Sets this Block as the only block in the Timeline (creating essentially a one clip sequence)
*/
void ConnectBlockInternal(Block* block);
/**
* @brief Disconnects t
*/
void RemoveBlockInternal();
/**
* @brief Adds a Block to the parent graph so it can be connected to other Nodes
*
* Also runs through Node's dependencies (the Nodes whose outputs are connected to this Node's inputs)
*/
void AddBlockToGraph(Block* block);
Block* attached_block();
QVector<Block*> block_cache_;
Block* current_block_;
NodeInput* track_input_;
NodeOutput* track_output_;
private slots:
/**
* @brief Adds Block `block` at the very beginning of the Sequence before all other clips
*/
@@ -160,6 +117,51 @@ private slots:
* length
*/
void SpliceBlock(Block* inner, Block* outer, rational inner_in);
signals:
/**
* @brief Signal emitted when a Block is added to this Track
*/
void BlockAdded(Block* block);
/**
* @brief Signal emitted when a Block is removed from this Track
*/
void BlockRemoved(Block* block);
public slots:
virtual void Process(const rational &time) override;
private:
/**
* @brief Sets this Block as the only block in the Timeline (creating essentially a one clip sequence)
*/
void ConnectBlockInternal(Block* block);
/**
* @brief Disconnects t
*/
void RemoveBlockInternal();
/**
* @brief Adds a Block to the parent graph so it can be connected to other Nodes
*
* Also runs through Node's dependencies (the Nodes whose outputs are connected to this Node's inputs)
*/
void AddBlockToGraph(Block* block);
Block* attached_block();
QVector<Block*> block_cache_;
Block* current_block_;
NodeInput* track_input_;
NodeOutput* track_output_;
private slots:
};
#endif // TRACKOUTPUT_H
+82 -10
View File
@@ -41,6 +41,8 @@ TimelineView::TimelineView(QWidget *parent) :
setDragMode(RubberBandDrag);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
connect(&scene_, SIGNAL(changed(const QList<QRectF>&)), this, SLOT(UpdateSceneRect()));
// Create playhead line and ensure it's always on top
playhead_line_ = new TimelineViewPlayheadItem();
playhead_line_->setZValue(100);
@@ -51,7 +53,7 @@ TimelineView::TimelineView(QWidget *parent) :
SetScale(1.0);
}
void TimelineView::AddBlock(Block *block)
void TimelineView::AddBlock(Block *block, int track)
{
switch (block->type()) {
case Block::kClip:
@@ -61,7 +63,10 @@ void TimelineView::AddBlock(Block *block)
// Set up clip with view parameters (clip item will automatically size its rect accordingly)
clip_item->SetClip(clip);
clip_item->SetY(GetTrackY(track));
clip_item->SetHeight(GetTrackHeight(track));
clip_item->SetScale(scale_);
clip_item->SetTrack(track);
// Add to list of clip items that can be iterated through
clip_items_.insert(clip, clip_item);
@@ -119,12 +124,17 @@ void TimelineView::SetTimebase(const rational &timebase)
void TimelineView::Clear()
{
scene_.removeItem(playhead_line_);
QMapIterator<Block*, TimelineViewRect*> iterator(clip_items_);
while (iterator.hasNext()) {
iterator.next();
if (iterator.value() != nullptr) {
delete iterator.value();
}
}
scene_.clear();
clip_items_.clear();
scene_.addItem(playhead_line_);
}
void TimelineView::SetTime(const int64_t time)
@@ -173,11 +183,26 @@ void TimelineView::resizeEvent(QResizeEvent *event)
{
QGraphicsView::resizeEvent(event);
if (scene_.height() < height()) {
QRectF rect = scene_.sceneRect();
rect.setHeight(height() - horizontalScrollBar()->height() - 2);
scene_.setSceneRect(rect);
UpdateSceneRect();
}
int TimelineView::GetTrackY(int track_index)
{
int y = 0;
for (int i=0;i<track_index;i++) {
y += GetTrackHeight(i);
}
return y;
}
int TimelineView::GetTrackHeight(int track_index)
{
// FIXME: Make this adjustable
Q_UNUSED(track_index)
return fontMetrics().height() * 3;
}
void TimelineView::AddGhost(TimelineViewGhostItem *ghost)
@@ -192,7 +217,7 @@ bool TimelineView::HasGhosts()
return !ghost_items_.isEmpty();
}
rational TimelineView::ScreenToTime(const int &x)
rational TimelineView::SceneToTime(const double &x)
{
// Adjust screen point by scale and timebase
int scaled_x_mvmt = qRound(x / scale_ / timebase_dbl_);
@@ -201,6 +226,19 @@ rational TimelineView::ScreenToTime(const int &x)
return rational(scaled_x_mvmt * timebase_.numerator(), timebase_.denominator());
}
int TimelineView::SceneToTrack(const double &y)
{
int track = -1;
int heights = 0;
do {
track++;
heights += GetTrackHeight(track);
} while (y > heights);
return track;
}
void TimelineView::ClearGhosts()
{
if (!ghost_items_.isEmpty()) {
@@ -221,6 +259,30 @@ void TimelineView::BlockChanged()
}
}
void TimelineView::UpdateSceneRect()
{
QRectF bounding_rect = scene_.itemsBoundingRect();
// Ensure the scene left and top are always 0
bounding_rect.setTopLeft(QPointF(0, 0));
// Ensure the scene height is always AT LEAST the height of the view
int minimum_height = height() - horizontalScrollBar()->height() - 2;
if (bounding_rect.height() < minimum_height) {
bounding_rect.setHeight(minimum_height);
}
// Ensure playhead is the correct height
playhead_line_->UpdateRect();
// If the scene is already this rect, do nothing
if (scene_.sceneRect() == bounding_rect) {
return;
}
scene_.setSceneRect(bounding_rect);
}
TimelineView::Tool::Tool(TimelineView *parent) :
dragging_(false),
parent_(parent)
@@ -247,3 +309,13 @@ TimelineView *TimelineView::Tool::parent()
{
return parent_;
}
QPointF TimelineView::Tool::GetScenePos(const QPoint &screen_pos)
{
return parent()->mapToScene(screen_pos);
}
QGraphicsItem *TimelineView::Tool::GetItemAtScenePos(const QPointF &scene_pos)
{
return parent()->scene_.itemAt(scene_pos, parent()->transform());
}
+20 -8
View File
@@ -43,7 +43,7 @@ class TimelineView : public QGraphicsView
public:
TimelineView(QWidget* parent);
void AddBlock(Block* block);
void AddBlock(Block* block, int track);
void RemoveBlock(Block* block);
@@ -59,11 +59,7 @@ public slots:
void SetTime(const int64_t time);
signals:
void RequestInsertBlockAtIndex(Block* block, int index);
void RequestPlaceBlock(Block* block, rational start);
void RequestInsertBlockAtTime(Block* block, rational time);
void RequestPlaceBlock(Block* block, rational start, int track);
protected:
virtual void mousePressEvent(QMouseEvent *event) override;
@@ -97,12 +93,17 @@ private:
TimelineView* parent();
protected:
QPointF GetScenePos(const QPoint& screen_pos);
QGraphicsItem* GetItemAtScenePos(const QPointF& scene_pos);
bool dragging_;
QPoint drag_start_;
QPointF drag_start_;
private:
TimelineView* parent_;
};
class PointerTool : public Tool
@@ -126,6 +127,9 @@ private:
virtual void DragDrop(QDropEvent *event) override;
};
int GetTrackY(int track_index);
int GetTrackHeight(int track_index);
PointerTool pointer_tool_;
ImportTool import_tool_;
@@ -133,7 +137,8 @@ private:
bool HasGhosts();
rational ScreenToTime(const int& x);
rational SceneToTime(const double &x);
int SceneToTrack(const double &y);
void ClearGhosts();
@@ -151,6 +156,8 @@ private:
QVector<TimelineViewGhostItem*> ghost_items_;
QVector<int> track_heights_;
TimelineViewPlayheadItem* playhead_line_;
private slots:
@@ -161,6 +168,11 @@ private slots:
* derivatives.
*/
void BlockChanged();
/**
* @brief Slot called whenever the view resizes or the scene contents change to enforce minimum scene sizes
*/
void UpdateSceneRect();
};
#endif // TIMELINEVIEW_H
@@ -55,7 +55,7 @@ void TimelineViewClipItem::UpdateRect()
double item_left = TimeToScreenCoord(clip_->in());
double item_width = TimeToScreenCoord(clip_->length());
setRect(0, 0, item_width - 1, 64);
setRect(0, y_, item_width - 1, height_ - 1);
setPos(item_left, 0.0);
}
@@ -63,13 +63,13 @@ void TimelineViewClipItem::paint(QPainter *painter, const QStyleOptionGraphicsIt
{
Q_UNUSED(widget)
/*QLinearGradient grad;
grad.setStart(0, 0);
grad.setFinalStop(0, rect().height());
grad.setColorAt(0.0, QColor(192, 192, 255));
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));
@@ -102,7 +102,7 @@ void TimelineViewGhostItem::UpdateRect()
{
rational length = GetAdjustedOut() - GetAdjustedIn();
setRect(0, 0, TimeToScreenCoord(length), 64);
setRect(0, y_, TimeToScreenCoord(length), height_ - 1);
setPos(TimeToScreenCoord(GetAdjustedIn()), 0);
}
+37 -1
View File
@@ -22,11 +22,47 @@
TimelineViewRect::TimelineViewRect(QGraphicsItem* parent) :
QGraphicsRectItem(parent),
scale_(1.0)
scale_(1.0),
y_(0),
height_(0)
{
}
const int &TimelineViewRect::Y()
{
return y_;
}
void TimelineViewRect::SetY(const int &y)
{
y_ = y;
UpdateRect();
}
const int &TimelineViewRect::Height()
{
return height_;
}
void TimelineViewRect::SetHeight(const int &height)
{
height_ = height;
UpdateRect();
}
const int &TimelineViewRect::Track()
{
return track_;
}
void TimelineViewRect::SetTrack(const int &track)
{
track_ = track;
}
void TimelineViewRect::SetScale(const double &scale)
{
scale_ = scale;
@@ -33,6 +33,15 @@ class TimelineViewRect : public QGraphicsRectItem
public:
TimelineViewRect(QGraphicsItem* parent = nullptr);
const int& Y();
void SetY(const int& y);
const int& Height();
void SetHeight(const int& height);
const int& Track();
void SetTrack(const int& track);
void SetScale(const double& scale);
virtual void UpdateRect() = 0;
@@ -41,6 +50,12 @@ protected:
double TimeToScreenCoord(const rational& time);
double scale_;
int y_;
int height_;
int track_;
};
#endif // TIMELINEVIEWRECT_H
+18 -9
View File
@@ -47,8 +47,11 @@ void TimelineView::ImportTool::DragEnter(QDragEnterEvent *event)
quintptr item_ptr;
int r;
// Set drag start position
drag_start_ = GetScenePos(event->pos());
// Set ghosts to start where the cursor entered
rational ghost_start = parent()->ScreenToTime(event->pos().x());
rational ghost_start = parent()->SceneToTime(drag_start_.x());
while (!stream.atEnd()) {
stream >> r >> item_ptr;
@@ -79,8 +82,6 @@ void TimelineView::ImportTool::DragEnter(QDragEnterEvent *event)
}
}
drag_start_ = event->pos();
event->accept();
} else {
// FIXME: Implement dropping from file
@@ -93,12 +94,22 @@ void TimelineView::ImportTool::DragMove(QDragMoveEvent *event)
if (parent()->HasGhosts()) {
// Move ghosts to the mouse cursor
foreach (TimelineViewGhostItem* ghost, parent()->ghost_items_) {
QPoint movement = event->pos() - drag_start_;
QPointF pos = GetScenePos(event->pos());
QPointF movement = pos - drag_start_;
rational time_movement = parent()->ScreenToTime(movement.x());
rational time_movement = parent()->SceneToTime(movement.x());
ghost->SetInAdjustment(time_movement);
ghost->SetOutAdjustment(time_movement);
int ghost_track = parent()->SceneToTrack(pos.y());
ghost->SetTrack(ghost_track);
int ghost_y = parent()->GetTrackY(ghost_track);
int ghost_height = parent()->GetTrackHeight(ghost_track);
ghost->SetY(ghost_y);
ghost->SetHeight(ghost_height);
}
event->accept();
@@ -130,8 +141,6 @@ void TimelineView::ImportTool::DragDrop(QDropEvent *event)
MediaInput* media = new MediaInput();
// Set parents to node_memory_manager in case no TimelineOutput receives this signal
// FIXME: Moving nodes to shared_ptrs might be a better idea, except they all use the QObject system for hierarchy
// already...
clip->setParent(&node_memory_manager);
media->setParent(&node_memory_manager);
@@ -141,9 +150,9 @@ void TimelineView::ImportTool::DragDrop(QDropEvent *event)
NodeParam::ConnectEdge(media->texture_output(), clip->texture_input());
if (event->keyboardModifiers() & Qt::ControlModifier) {
emit parent()->RequestInsertBlockAtTime(clip, ghost->GetAdjustedIn());
//emit parent()->RequestInsertBlockAtTime(clip, ghost->GetAdjustedIn());
} else {
emit parent()->RequestPlaceBlock(clip, ghost->GetAdjustedIn());
emit parent()->RequestPlaceBlock(clip, ghost->GetAdjustedIn(), ghost->Track());
}
}
+9 -5
View File
@@ -52,8 +52,10 @@ void TimelineView::PointerTool::MouseMove(QMouseEvent *event)
if (!dragging_) {
drag_start_ = GetScenePos(event->pos());
// Let's see if there's anything selected to drag
if (parent()->itemAt(event->pos()) != nullptr) {
if (GetItemAtScenePos(drag_start_) != nullptr) {
QList<QGraphicsItem*> selected_items = parent()->scene_.selectedItems();
foreach (QGraphicsItem* item, selected_items) {
@@ -62,6 +64,8 @@ void TimelineView::PointerTool::MouseMove(QMouseEvent *event)
ClipBlock* clip = clip_item->clip();
ghost->SetY(clip_item->Y());
ghost->SetHeight(clip_item->Height());
ghost->SetIn(clip->in());
ghost->SetOut(clip->out());
ghost->SetScale(parent()->scale_);
@@ -73,16 +77,16 @@ void TimelineView::PointerTool::MouseMove(QMouseEvent *event)
parent()->scene_.addItem(ghost);
}
drag_start_ = event->pos();
}
dragging_ = true;
} else if (!parent()->ghost_items_.isEmpty()) {
QPoint movement = event->pos() - drag_start_;
QPointF scene_pos = GetScenePos(event->pos());
rational time_movement = parent()->ScreenToTime(movement.x());
QPointF movement = scene_pos - drag_start_;
rational time_movement = parent()->SceneToTime(movement.x());
// Validate movement
foreach (TimelineViewGhostItem* ghost, parent()->ghost_items_) {