improved transition behavior
This is still not complete, but definitely should help a lot
This commit is contained in:
@@ -264,10 +264,30 @@ void PointerTool::InitiateDragInternal(Block *clicked_item,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine if this move is a slide, which is determined by either
|
bool sliding_due_to_transition = false;
|
||||||
bool clips_are_sliding = (slide_instead_of_moving || dynamic_cast<TransitionBlock*>(clicked_item));
|
|
||||||
|
|
||||||
if (clips_are_sliding) {
|
if (!slide_instead_of_moving) {
|
||||||
|
// If the user tries to move a transition without moving the clip it belongs to, we turn
|
||||||
|
// this into a slide
|
||||||
|
foreach (Block* block, clips) {
|
||||||
|
if (TransitionBlock* transit = dynamic_cast<TransitionBlock*>(block)) {
|
||||||
|
if (!CanTransitionMove(transit, clips)) {
|
||||||
|
slide_instead_of_moving = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (ClipBlock *clip = dynamic_cast<ClipBlock*>(block)) {
|
||||||
|
if ((clip->in_transition() && !CanTransitionMove(clip->in_transition(), clips))
|
||||||
|
|| (clip->out_transition() && !CanTransitionMove(clip->out_transition(), clips))) {
|
||||||
|
slide_instead_of_moving = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sliding_due_to_transition = slide_instead_of_moving;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slide_instead_of_moving) {
|
||||||
// This is a slide. What we do here is move clips within their own track, between the clips
|
// This is a slide. What we do here is move clips within their own track, between the clips
|
||||||
// that they're already next to. We don't allow changing tracks or changing the order of
|
// that they're already next to. We don't allow changing tracks or changing the order of
|
||||||
// blocks.
|
// blocks.
|
||||||
@@ -297,17 +317,51 @@ void PointerTool::InitiateDragInternal(Block *clicked_item,
|
|||||||
Block* latest = latest_block_on_track.value(i.key());
|
Block* latest = latest_block_on_track.value(i.key());
|
||||||
|
|
||||||
// First we add the block that's out trimming, the one prior to the earliest
|
// First we add the block that's out trimming, the one prior to the earliest
|
||||||
TimelineViewGhostItem* earliest_ghost;
|
{
|
||||||
if (earliest->previous()) {
|
TimelineViewGhostItem* earliest_ghost;
|
||||||
earliest_ghost = AddGhostFromBlock(earliest->previous(), Timeline::kTrimOut);
|
bool slide_with_earliest_previous = true;
|
||||||
} else {
|
if (sliding_due_to_transition && earliest->previous()) {
|
||||||
earliest_ghost = AddGhostFromNull(earliest->in(), earliest->in(), track->ToReference(), Timeline::kTrimOut);
|
if (TransitionBlock *transit = dynamic_cast<TransitionBlock *>(earliest)) {
|
||||||
|
if (earliest->previous() != transit->connected_out_block()) {
|
||||||
|
slide_with_earliest_previous = false;
|
||||||
|
}
|
||||||
|
} else if (ClipBlock *clip = dynamic_cast<ClipBlock*>(earliest)) {
|
||||||
|
if (earliest->previous() != clip->in_transition()) {
|
||||||
|
slide_with_earliest_previous = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (earliest->previous() && slide_with_earliest_previous) {
|
||||||
|
earliest_ghost = AddGhostFromBlock(earliest->previous(), Timeline::kTrimOut);
|
||||||
|
} else {
|
||||||
|
earliest_ghost = AddGhostFromNull(earliest->in(), earliest->in(), track->ToReference(), Timeline::kTrimOut);
|
||||||
|
}
|
||||||
|
SetGhostToSlideMode(earliest_ghost);
|
||||||
}
|
}
|
||||||
SetGhostToSlideMode(earliest_ghost);
|
|
||||||
|
|
||||||
// Then we add the block that's in trimming, the one after the latest
|
// Then we add the block that's in trimming, the one after the latest
|
||||||
if (latest->next()) {
|
if (latest->next()) {
|
||||||
TimelineViewGhostItem* latest_ghost = AddGhostFromBlock(latest->next(), Timeline::kTrimIn);
|
TimelineViewGhostItem* latest_ghost;
|
||||||
|
|
||||||
|
bool slide_with_latest_next = true;
|
||||||
|
if (sliding_due_to_transition) {
|
||||||
|
if (TransitionBlock *transit = dynamic_cast<TransitionBlock *>(latest)) {
|
||||||
|
if (latest->next() != transit->connected_in_block()) {
|
||||||
|
slide_with_latest_next = false;
|
||||||
|
}
|
||||||
|
} else if (ClipBlock *clip = dynamic_cast<ClipBlock*>(latest)) {
|
||||||
|
if (latest->next() != clip->out_transition()) {
|
||||||
|
slide_with_latest_next = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slide_with_latest_next) {
|
||||||
|
latest_ghost = AddGhostFromBlock(latest->next(), Timeline::kTrimIn);
|
||||||
|
} else {
|
||||||
|
latest_ghost = AddGhostFromNull(latest->out(), latest->out(), track->ToReference(), Timeline::kTrimIn);
|
||||||
|
}
|
||||||
SetGhostToSlideMode(latest_ghost);
|
SetGhostToSlideMode(latest_ghost);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,13 +383,18 @@ void PointerTool::InitiateDragInternal(Block *clicked_item,
|
|||||||
} else {
|
} else {
|
||||||
// Prepare for a standard pointer move by creating ghosts for them and any related blocks
|
// Prepare for a standard pointer move by creating ghosts for them and any related blocks
|
||||||
foreach (Block* block, clips) {
|
foreach (Block* block, clips) {
|
||||||
if (dynamic_cast<GapBlock*>(block) || dynamic_cast<TransitionBlock*>(block)) {
|
|
||||||
// Gaps cannot move, and we handle transitions further down
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create ghost for this block
|
// Create ghost for this block
|
||||||
AddGhostFromBlock(block, trim_mode, true);
|
auto ghost = AddGhostFromBlock(block, trim_mode, true);
|
||||||
|
Q_UNUSED(ghost)
|
||||||
|
|
||||||
|
if (ClipBlock *clip = dynamic_cast<ClipBlock*>(block)) {
|
||||||
|
if (clip->out_transition()) {
|
||||||
|
AddGhostFromBlock(clip->out_transition(), trim_mode, true);
|
||||||
|
}
|
||||||
|
if (clip->in_transition()) {
|
||||||
|
AddGhostFromBlock(clip->in_transition(), trim_mode, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -454,6 +513,18 @@ void PointerTool::InitiateDragInternal(Block *clicked_item,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PointerTool::CanTransitionMove(TransitionBlock *transit, const QVector<Block *> &clips)
|
||||||
|
{
|
||||||
|
Block *out = transit->connected_out_block();
|
||||||
|
Block *in = transit->connected_in_block();
|
||||||
|
|
||||||
|
if ((out && !clips.contains(out)) || (in && !clips.contains(in))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void PointerTool::ProcessDrag(const TimelineCoordinate &mouse_pos)
|
void PointerTool::ProcessDrag(const TimelineCoordinate &mouse_pos)
|
||||||
{
|
{
|
||||||
// Calculate track movement
|
// Calculate track movement
|
||||||
@@ -691,8 +762,7 @@ void PointerTool::FinishDrag(TimelineViewMouseEvent *event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!movement.isNull()) {
|
if (!movement.isNull()) {
|
||||||
QHash<Track::Reference, QList<Block*> >::const_iterator i;
|
for (auto i=slide_info.constBegin(); i!=slide_info.constEnd(); i++) {
|
||||||
for (i=slide_info.constBegin(); i!=slide_info.constEnd(); i++) {
|
|
||||||
command->add_child(new TrackSlideCommand(parent()->GetTrackFromReference(i.key()),
|
command->add_child(new TrackSlideCommand(parent()->GetTrackFromReference(i.key()),
|
||||||
i.value(),
|
i.value(),
|
||||||
in_adjacents.value(i.key()),
|
in_adjacents.value(i.key()),
|
||||||
@@ -737,6 +807,17 @@ void PointerTool::InitiateDrag(Block *clicked_item, Timeline::MovementMode trim_
|
|||||||
InitiateDragInternal(clicked_item, trim_mode, modifiers, false, false, false);
|
InitiateDragInternal(clicked_item, trim_mode, modifiers, false, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TimelineViewGhostItem *PointerTool::GetExistingGhostFromBlock(Block *block)
|
||||||
|
{
|
||||||
|
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
|
||||||
|
if (Node::ValueToPtr<Block>(ghost->GetData(TimelineViewGhostItem::kAttachedBlock)) == block) {
|
||||||
|
return ghost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
//#define HIDE_GAP_GHOSTS
|
//#define HIDE_GAP_GHOSTS
|
||||||
|
|
||||||
TimelineViewGhostItem* PointerTool::AddGhostFromBlock(Block* block, Timeline::MovementMode mode, bool check_if_exists)
|
TimelineViewGhostItem* PointerTool::AddGhostFromBlock(Block* block, Timeline::MovementMode mode, bool check_if_exists)
|
||||||
@@ -747,17 +828,17 @@ TimelineViewGhostItem* PointerTool::AddGhostFromBlock(Block* block, Timeline::Mo
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TimelineViewGhostItem* ghost;
|
||||||
|
|
||||||
// Check if we've already made a ghost for this block
|
// Check if we've already made a ghost for this block
|
||||||
if (check_if_exists) {
|
if (check_if_exists) {
|
||||||
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
|
if ((ghost = GetExistingGhostFromBlock(block))) {
|
||||||
if (Node::ValueToPtr<Block>(ghost->GetData(TimelineViewGhostItem::kAttachedBlock)) == block) {
|
return ghost;
|
||||||
return ghost;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, it's time to make a ghost for this block
|
// Otherwise, it's time to make a ghost for this block
|
||||||
TimelineViewGhostItem* ghost = TimelineViewGhostItem::FromBlock(block);
|
ghost = TimelineViewGhostItem::FromBlock(block);
|
||||||
|
|
||||||
#ifdef HIDE_GAP_GHOSTS
|
#ifdef HIDE_GAP_GHOSTS
|
||||||
if (block->type() == Block::kGap) {
|
if (block->type() == Block::kGap) {
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ protected:
|
|||||||
|
|
||||||
virtual void InitiateDrag(Block* clicked_item, Timeline::MovementMode trim_mode, Qt::KeyboardModifiers modifiers);
|
virtual void InitiateDrag(Block* clicked_item, Timeline::MovementMode trim_mode, Qt::KeyboardModifiers modifiers);
|
||||||
|
|
||||||
|
TimelineViewGhostItem *GetExistingGhostFromBlock(Block *block);
|
||||||
|
|
||||||
TimelineViewGhostItem* AddGhostFromBlock(Block *block, Timeline::MovementMode mode, bool check_if_exists = false);
|
TimelineViewGhostItem* AddGhostFromBlock(Block *block, Timeline::MovementMode mode, bool check_if_exists = false);
|
||||||
|
|
||||||
TimelineViewGhostItem* AddGhostFromNull(const rational& in, const rational& out, const Track::Reference& track, Timeline::MovementMode mode);
|
TimelineViewGhostItem* AddGhostFromNull(const rational& in, const rational& out, const Track::Reference& track, Timeline::MovementMode mode);
|
||||||
@@ -72,6 +74,8 @@ protected:
|
|||||||
const Timeline::MovementMode& drag_movement_mode() const { return drag_movement_mode_; }
|
const Timeline::MovementMode& drag_movement_mode() const { return drag_movement_mode_; }
|
||||||
void set_drag_movement_mode(const Timeline::MovementMode &d) { drag_movement_mode_ = d; }
|
void set_drag_movement_mode(const Timeline::MovementMode &d) { drag_movement_mode_ = d; }
|
||||||
|
|
||||||
|
static bool CanTransitionMove(TransitionBlock *transit, const QVector<Block*> &clips);
|
||||||
|
|
||||||
void SetMovementAllowed(bool e)
|
void SetMovementAllowed(bool e)
|
||||||
{
|
{
|
||||||
movement_allowed_ = e;
|
movement_allowed_ = e;
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ public:
|
|||||||
ghost->can_have_zero_length_ = false;
|
ghost->can_have_zero_length_ = false;
|
||||||
} else if (dynamic_cast<TransitionBlock*>(block)) {
|
} else if (dynamic_cast<TransitionBlock*>(block)) {
|
||||||
ghost->can_have_zero_length_ = false;
|
ghost->can_have_zero_length_ = false;
|
||||||
ghost->SetCanMoveTracks(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ghost;
|
return ghost;
|
||||||
|
|||||||
Reference in New Issue
Block a user