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;
|
||||
}
|
||||
|
||||
// Determine if this move is a slide, which is determined by either
|
||||
bool clips_are_sliding = (slide_instead_of_moving || dynamic_cast<TransitionBlock*>(clicked_item));
|
||||
bool sliding_due_to_transition = false;
|
||||
|
||||
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
|
||||
// that they're already next to. We don't allow changing tracks or changing the order of
|
||||
// blocks.
|
||||
@@ -297,17 +317,51 @@ void PointerTool::InitiateDragInternal(Block *clicked_item,
|
||||
Block* latest = latest_block_on_track.value(i.key());
|
||||
|
||||
// First we add the block that's out trimming, the one prior to the earliest
|
||||
TimelineViewGhostItem* earliest_ghost;
|
||||
if (earliest->previous()) {
|
||||
earliest_ghost = AddGhostFromBlock(earliest->previous(), Timeline::kTrimOut);
|
||||
} else {
|
||||
earliest_ghost = AddGhostFromNull(earliest->in(), earliest->in(), track->ToReference(), Timeline::kTrimOut);
|
||||
{
|
||||
TimelineViewGhostItem* earliest_ghost;
|
||||
bool slide_with_earliest_previous = true;
|
||||
if (sliding_due_to_transition && earliest->previous()) {
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -329,13 +383,18 @@ void PointerTool::InitiateDragInternal(Block *clicked_item,
|
||||
} else {
|
||||
// Prepare for a standard pointer move by creating ghosts for them and any related blocks
|
||||
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
|
||||
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)
|
||||
{
|
||||
// Calculate track movement
|
||||
@@ -691,8 +762,7 @@ void PointerTool::FinishDrag(TimelineViewMouseEvent *event)
|
||||
}
|
||||
|
||||
if (!movement.isNull()) {
|
||||
QHash<Track::Reference, QList<Block*> >::const_iterator i;
|
||||
for (i=slide_info.constBegin(); i!=slide_info.constEnd(); i++) {
|
||||
for (auto i=slide_info.constBegin(); i!=slide_info.constEnd(); i++) {
|
||||
command->add_child(new TrackSlideCommand(parent()->GetTrackFromReference(i.key()),
|
||||
i.value(),
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
TimelineViewGhostItem* ghost;
|
||||
|
||||
// Check if we've already made a ghost for this block
|
||||
if (check_if_exists) {
|
||||
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
|
||||
if (Node::ValueToPtr<Block>(ghost->GetData(TimelineViewGhostItem::kAttachedBlock)) == block) {
|
||||
return ghost;
|
||||
}
|
||||
if ((ghost = GetExistingGhostFromBlock(block))) {
|
||||
return ghost;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, it's time to make a ghost for this block
|
||||
TimelineViewGhostItem* ghost = TimelineViewGhostItem::FromBlock(block);
|
||||
ghost = TimelineViewGhostItem::FromBlock(block);
|
||||
|
||||
#ifdef HIDE_GAP_GHOSTS
|
||||
if (block->type() == Block::kGap) {
|
||||
|
||||
Reference in New Issue
Block a user