Files
oak-editor/timeline/sequence.cpp
T
2019-03-20 14:29:20 +11:00

238 lines
6.0 KiB
C++

/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include "sequence.h"
#include <QCoreApplication>
#include "panels/panels.h"
#include "global/debug.h"
Sequence::Sequence() :
playhead(0),
using_workarea(false),
workarea_in(0),
workarea_out(0),
wrapper_sequence(false)
{
}
Sequence::~Sequence() {}
SequencePtr Sequence::copy() {
SequencePtr s = std::make_shared<Sequence>();
s->name = QCoreApplication::translate("Sequence", "%1 (copy)").arg(name);
s->width = width;
s->height = height;
s->frame_rate = frame_rate;
s->audio_frequency = audio_frequency;
s->audio_layout = audio_layout;
// deep copy all of the sequence's clips
s->clips.resize(clips.size());
for (int i=0;i<clips.size();i++) {
ClipPtr c = clips.at(i);
if (c == nullptr) {
s->clips[i] = nullptr;
} else {
ClipPtr copy = c->copy(s.get());
copy->linked = c->linked;
s->clips[i] = copy;
}
}
// copy all of the sequence's markers
s->markers = markers;
return s;
}
long Sequence::getEndFrame() {
long end = 0;
for (int j=0;j<clips.size();j++) {
ClipPtr c = clips.at(j);
if (c != nullptr && c->timeline_out() > end) {
end = c->timeline_out();
}
}
return end;
}
void Sequence::RefreshClips(Media *m) {
for (int i=0;i<clips.size();i++) {
ClipPtr c = clips.at(i);
if (c != nullptr
&& (m == nullptr || c->media() == m)) {
c->Close(true);
c->refresh();
}
}
}
QVector<Clip *> Sequence::SelectedClips(bool containing)
{
QVector<Clip*> selected_clips;
for (int i=0;i<clips.size();i++) {
Clip* c = clips.at(i).get();
if (c != nullptr && IsClipSelected(c, containing)) {
selected_clips.append(c);
}
}
return selected_clips;
}
QVector<int> Sequence::SelectedClipIndexes()
{
QVector<int> selected_clips;
for (int i=0;i<clips.size();i++) {
Clip* c = clips.at(i).get();
if (c != nullptr && IsClipSelected(c, true)) {
selected_clips.append(i);
}
}
return selected_clips;
}
Effect *Sequence::GetSelectedGizmo()
{
Effect* gizmo_ptr = nullptr;
for (int i=0;i<clips.size();i++) {
Clip* c = clips.at(i).get();
if (c != nullptr
&& c->IsActiveAt(playhead)
&& IsClipSelected(c, true)) {
// This clip is selected and currently active - we'll use this for gizmos
if (!c->effects.isEmpty()) {
// find which effect has gizmos selected, or default to the first gizmo effect we find if there is
// none selected
for (int j=0;j<c->effects.size();j++) {
Effect* e = c->effects.at(j).get();
// retrieve gizmo data from effect
if (e->are_gizmos_enabled()) {
if (gizmo_ptr == nullptr) {
gizmo_ptr = e;
}
if (panel_effect_controls->IsEffectSelected(e)) {
gizmo_ptr = e;
break;
}
}
}
}
if (gizmo_ptr != nullptr) {
break;
}
}
}
return gizmo_ptr;
}
bool Sequence::IsClipSelected(int clip_index, bool containing)
{
return IsClipSelected(clips.at(clip_index).get(), containing);
}
bool Sequence::IsClipSelected(Clip *clip, bool containing)
{
for (int i=0;i<selections.size();i++) {
const Selection& s = selections.at(i);
if (clip->track() == s.track && ((clip->timeline_in() >= s.in && clip->timeline_out() <= s.out)
|| (!containing && !(clip->timeline_in() < s.in && clip->timeline_out() < s.in)
&& !(clip->timeline_in() > s.in && clip->timeline_out() > s.in)))) {
return true;
}
}
return false;
}
bool Sequence::IsTransitionSelected(Transition *t)
{
if (t == nullptr) {
return false;
}
Clip* c = t->parent_clip;
int transition_track = t->parent_clip->track();
long transition_in_point;
long transition_out_point;
// Get positions of the transition on the timeline
if (t == c->opening_transition.get()) {
transition_in_point = c->timeline_in();
transition_out_point = c->timeline_in() + t->get_true_length();
if (t->secondary_clip != nullptr) {
transition_in_point -= t->get_true_length();
}
} else {
transition_in_point = c->timeline_out() - t->get_true_length();
transition_out_point = c->timeline_out();
if (t->secondary_clip != nullptr) {
transition_out_point += t->get_true_length();
}
}
// See if there's a selection matching this
for (int i=0;i<selections.size();i++) {
if (selections.at(i).in <= transition_in_point
&& selections.at(i).out >= transition_out_point
&& selections.at(i).track == transition_track) {
return true;
}
}
return false;
}
void Sequence::getTrackLimits(int* video_tracks, int* audio_tracks) {
int vt = 0;
int at = 0;
for (int j=0;j<clips.size();j++) {
ClipPtr c = clips.at(j);
if (c != nullptr) {
if (c->track() < 0 && c->track() < vt) { // video clip
vt = c->track();
} else if (c->track() > at) {
at = c->track();
}
}
}
if (video_tracks != nullptr) *video_tracks = vt;
if (audio_tracks != nullptr) *audio_tracks = at;
}
// static variable for the currently active sequence
SequencePtr olive::ActiveSequence = nullptr;