added cut/copy/paste
This commit is contained in:
@@ -8,7 +8,7 @@ extern "C" {
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// init ffmpeg subsystem
|
||||
av_register_all();
|
||||
av_register_all();
|
||||
|
||||
QApplication a(argc, argv);
|
||||
MainWindow w;
|
||||
|
||||
@@ -182,3 +182,24 @@ void MainWindow::on_actionSplit_at_Playhead_triggered()
|
||||
panel_timeline->split_at_playhead();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionCu_t_triggered()
|
||||
{
|
||||
if (panel_timeline->focused()) {
|
||||
panel_timeline->copy(true);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionCop_y_triggered()
|
||||
{
|
||||
if (panel_timeline->focused()) {
|
||||
panel_timeline->copy(false);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Paste_triggered()
|
||||
{
|
||||
if (panel_timeline->focused()) {
|
||||
panel_timeline->paste();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,12 @@ private slots:
|
||||
|
||||
void on_actionSplit_at_Playhead_triggered();
|
||||
|
||||
void on_actionCu_t_triggered();
|
||||
|
||||
void on_actionCop_y_triggered();
|
||||
|
||||
void on_action_Paste_triggered();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
void setup_layout();
|
||||
|
||||
+104
-30
@@ -66,15 +66,17 @@ void Timeline::seek(long p) {
|
||||
|
||||
// reset all clip audio
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
Clip& c = sequence->get_clip(i);
|
||||
c.reset_audio = true;
|
||||
c.frame_sample_index = 0;
|
||||
c.audio_buffer_write = 0;
|
||||
Clip* c = sequence->get_clip(i);
|
||||
c->reset_audio = true;
|
||||
c->frame_sample_index = 0;
|
||||
c->audio_buffer_write = 0;
|
||||
}
|
||||
clear_audio_ibuffer();
|
||||
audio_ibuffer_read = 0;
|
||||
|
||||
playhead = p;
|
||||
|
||||
repaint_timeline();
|
||||
}
|
||||
|
||||
bool Timeline::toggle_play() {
|
||||
@@ -105,9 +107,9 @@ void Timeline::set_sequence(Sequence *s) {
|
||||
if (sequence != NULL) {
|
||||
// clean up - close all open clips
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
Clip& c = sequence->get_clip(i);
|
||||
if (c.open) {
|
||||
close_clip(&c);
|
||||
Clip* c = sequence->get_clip(i);
|
||||
if (c->open) {
|
||||
close_clip(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,6 +141,7 @@ bool Timeline::focused() {
|
||||
|
||||
void Timeline::undo() {
|
||||
if (sequence != NULL) {
|
||||
current_clips.clear();
|
||||
sequence->undo();
|
||||
ui->video_area->redraw_clips();
|
||||
ui->audio_area->redraw_clips();
|
||||
@@ -147,6 +150,7 @@ void Timeline::undo() {
|
||||
|
||||
void Timeline::redo() {
|
||||
if (sequence != NULL) {
|
||||
current_clips.clear();
|
||||
sequence->redo();
|
||||
ui->video_area->redraw_clips();
|
||||
ui->audio_area->redraw_clips();
|
||||
@@ -177,8 +181,8 @@ void Timeline::redraw_all_clips() {
|
||||
void Timeline::select_all() {
|
||||
selections.clear();
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
Clip& c = sequence->get_clip(i);
|
||||
selections.append({c.timeline_in, c.timeline_out, c.track});
|
||||
Clip* c = sequence->get_clip(i);
|
||||
selections.append({c->timeline_in, c->timeline_out, c->track});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,12 +208,12 @@ void Timeline::delete_selection(bool ripple_delete) {
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
// check every clip after and see if it'll collide
|
||||
// NOTE, we could probably re-use the validation code for the ripple tool here for optimization (since it's technically better code I think)
|
||||
Clip& c = sequence->get_clip(i);
|
||||
if (c.timeline_in >= ripple_point) {
|
||||
Clip* c = sequence->get_clip(i);
|
||||
if (c->timeline_in >= ripple_point) {
|
||||
for (int j=0;j<sequence->clip_count();j++) {
|
||||
Clip& cc = sequence->get_clip(j);
|
||||
if (cc.timeline_in < ripple_point) {
|
||||
validator = c.timeline_in - ripple_length - cc.timeline_out;
|
||||
Clip* cc = sequence->get_clip(j);
|
||||
if (cc->timeline_in < ripple_point) {
|
||||
validator = c->timeline_in - ripple_length - cc->timeline_out;
|
||||
if (validator < 0) ripple_length += validator;
|
||||
|
||||
if (ripple_length <= 0) {
|
||||
@@ -239,10 +243,10 @@ void Timeline::zoom_out() {
|
||||
|
||||
void Timeline::ripple(long ripple_point, long ripple_length) {
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
Clip& c = sequence->get_clip(i);
|
||||
if (c.timeline_in >= ripple_point) {
|
||||
c.timeline_in += ripple_length;
|
||||
c.timeline_out += ripple_length;
|
||||
Clip* c = sequence->get_clip(i);
|
||||
if (c->timeline_in >= ripple_point) {
|
||||
c->timeline_in += ripple_length;
|
||||
c->timeline_out += ripple_length;
|
||||
}
|
||||
}
|
||||
for (int i=0;i<selections.size();i++) {
|
||||
@@ -300,10 +304,10 @@ void Timeline::on_pushButton_5_clicked()
|
||||
}
|
||||
|
||||
bool Timeline::is_clip_selected(int clip_index) {
|
||||
Clip& clip = sequence->get_clip(clip_index);
|
||||
Clip* clip = sequence->get_clip(clip_index);
|
||||
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) {
|
||||
if (clip->track == s.track && clip->timeline_in >= s.in && clip->timeline_out <= s.out) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -342,6 +346,85 @@ void Timeline::on_snappingButton_toggled(bool checked)
|
||||
snapping = checked;
|
||||
}
|
||||
|
||||
void Timeline::copy(bool del) {
|
||||
bool cleared = false;
|
||||
bool copied = false;
|
||||
|
||||
long min_in = 0;
|
||||
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
Clip* c = sequence->get_clip(i);
|
||||
for (int j=0;j<selections.size();j++) {
|
||||
const Selection& s = selections.at(j);
|
||||
if (s.track == c->track && !((c->timeline_in < s.in && c->timeline_out < s.in) || (c->timeline_in > s.out && c->timeline_out > s.out))) {
|
||||
if (!cleared) {
|
||||
clip_clipboard.clear();
|
||||
cleared = true;
|
||||
}
|
||||
|
||||
Clip* copied_clip = c->copy();
|
||||
|
||||
if (copied_clip->timeline_in < s.in) {
|
||||
copied_clip->clip_in += (s.in - copied_clip->timeline_in);
|
||||
copied_clip->timeline_in = s.in;
|
||||
}
|
||||
|
||||
if (copied_clip->timeline_out > s.out) {
|
||||
copied_clip->timeline_out = s.out;
|
||||
}
|
||||
|
||||
if (copied) {
|
||||
min_in = qMin(min_in, s.in);
|
||||
} else {
|
||||
min_in = s.in;
|
||||
copied = true;
|
||||
}
|
||||
|
||||
clip_clipboard.append(copied_clip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0;i<clip_clipboard.size();i++) {
|
||||
// initialize all timeline_ins to 0 or offsets of
|
||||
clip_clipboard[i]->timeline_in -= min_in;
|
||||
clip_clipboard[i]->timeline_out -= min_in;
|
||||
}
|
||||
|
||||
if (del && copied) {
|
||||
delete_selection(false);
|
||||
}
|
||||
}
|
||||
|
||||
void Timeline::paste() {
|
||||
if (clip_clipboard.size() > 0) {
|
||||
for (int i=0;i<clip_clipboard.size();i++) {
|
||||
Clip* c = clip_clipboard.at(i);
|
||||
sequence->delete_area(c->timeline_in + playhead, c->timeline_out + playhead, c->track);
|
||||
Clip* cc = c->copy();
|
||||
cc->timeline_in += playhead;
|
||||
cc->timeline_out += playhead;
|
||||
sequence->add_clip(cc);
|
||||
}
|
||||
redraw_all_clips();
|
||||
}
|
||||
}
|
||||
|
||||
bool Timeline::split_selection() {
|
||||
bool split = false;
|
||||
for (int j=0;j<sequence->clip_count();j++) {
|
||||
for (int i=0;i<selections.size();i++) {
|
||||
const Selection& s = selections.at(i);
|
||||
if (s.track == sequence->get_clip(j)->track) {
|
||||
sequence->split_clip(j, s.in);
|
||||
sequence->split_clip(j, s.out);
|
||||
split = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return split;
|
||||
}
|
||||
|
||||
void Timeline::split_at_playhead() {
|
||||
bool split_selected = false;
|
||||
|
||||
@@ -356,16 +439,7 @@ void Timeline::split_at_playhead() {
|
||||
|
||||
// split a selection if not
|
||||
if (!split_selected) {
|
||||
for (int j=0;j<sequence->clip_count();j++) {
|
||||
for (int i=0;i<selections.size();i++) {
|
||||
const Selection& s = selections.at(i);
|
||||
if (s.track == sequence->get_clip(j).track) {
|
||||
sequence->split_clip(j, s.in);
|
||||
sequence->split_clip(j, s.out);
|
||||
split_selected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
split_selected = split_selection();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,9 @@ public:
|
||||
void zoom_out();
|
||||
void undo();
|
||||
void redo();
|
||||
void copy(bool del);
|
||||
void paste();
|
||||
bool split_selection();
|
||||
void split_at_playhead();
|
||||
void set_sequence(Sequence* s);
|
||||
|
||||
@@ -153,6 +156,7 @@ private:
|
||||
void decheck_tool_buttons(QObject* sender);
|
||||
void set_tool(int tool);
|
||||
long last_frame;
|
||||
QVector<Clip*> clip_clipboard;
|
||||
};
|
||||
|
||||
#endif // TIMELINE_H
|
||||
|
||||
+3
-3
@@ -313,14 +313,12 @@ void close_clip_worker(Clip* clip) {
|
||||
|
||||
av_frame_free(&clip->frame);
|
||||
|
||||
clip->reset();
|
||||
|
||||
// remove clip from current_clips
|
||||
cc_lock.lock();
|
||||
bool found = false;
|
||||
for (int i=0;i<current_clips.count();i++) {
|
||||
if (current_clips[i] == clip) {
|
||||
current_clips.erase(current_clips.begin()+i);
|
||||
current_clips.removeAt(i);
|
||||
found = true;
|
||||
i = current_clips.count();
|
||||
}
|
||||
@@ -328,6 +326,8 @@ void close_clip_worker(Clip* clip) {
|
||||
cc_lock.unlock();
|
||||
if (!found) qDebug() << "[WARNING] Could not remove clip from current clips";
|
||||
|
||||
clip->reset();
|
||||
|
||||
qDebug() << "[INFO] Clip closed on track" << clip->track;
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -27,34 +27,34 @@ QMutex cc_lock;
|
||||
|
||||
void handle_media(Sequence* sequence, long playhead, bool multithreaded) {
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
Clip& c = sequence->get_clip(i);
|
||||
Clip* c = sequence->get_clip(i);
|
||||
|
||||
// if clip starts within one second and/or hasn't finished yet
|
||||
if (is_clip_active(&c, playhead)) {
|
||||
if (is_clip_active(c, playhead)) {
|
||||
// if thread is already working, we don't want to touch this,
|
||||
// but we also don't want to hang the UI thread
|
||||
if (!c.open) {
|
||||
if (c.lock.tryLock()) {
|
||||
open_clip(&c, multithreaded);
|
||||
if (!c->open) {
|
||||
if (c->lock.tryLock()) {
|
||||
open_clip(c, multithreaded);
|
||||
|
||||
// add to current_clips, (insertion) sorted by track so composite them in order
|
||||
cc_lock.lock();
|
||||
bool found = false;
|
||||
for (int j=0;j<current_clips.size();j++) {
|
||||
if (current_clips[j]->track < c.track) {
|
||||
current_clips.insert(current_clips.begin()+j, &c);
|
||||
if (current_clips[j]->track < c->track) {
|
||||
current_clips.insert(current_clips.begin()+j, c);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
current_clips.push_back(&c);
|
||||
current_clips.push_back(c);
|
||||
}
|
||||
cc_lock.unlock();
|
||||
}
|
||||
}
|
||||
} else if (c.open) {
|
||||
close_clip(&c);
|
||||
} else if (c->open) {
|
||||
close_clip(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+18
-24
@@ -15,36 +15,30 @@ Clip::Clip() {
|
||||
init();
|
||||
}
|
||||
|
||||
Clip::Clip(const Clip &c) {
|
||||
init();
|
||||
copy(c);
|
||||
}
|
||||
Clip* Clip::copy() {
|
||||
Clip* copy = new Clip();
|
||||
|
||||
Clip& Clip::operator= (const Clip& c) {
|
||||
init();
|
||||
copy(c);
|
||||
return *this;
|
||||
}
|
||||
copy->name = name;
|
||||
copy->clip_in = clip_in;
|
||||
copy->timeline_in = timeline_in;
|
||||
copy->timeline_out = timeline_out;
|
||||
copy->track = track;
|
||||
copy->color_r = color_r;
|
||||
copy->color_g = color_g;
|
||||
copy->color_b = color_b;
|
||||
copy->sequence = sequence;
|
||||
copy->media = media;
|
||||
copy->media_stream = media_stream;
|
||||
|
||||
void Clip::copy(const Clip& c) {
|
||||
name = c.name;
|
||||
clip_in = c.clip_in;
|
||||
timeline_in = c.timeline_in;
|
||||
timeline_out = c.timeline_out;
|
||||
track = c.track;
|
||||
color_r = c.color_r;
|
||||
color_g = c.color_g;
|
||||
color_b = c.color_b;
|
||||
sequence = c.sequence;
|
||||
media = c.media;
|
||||
media_stream = c.media_stream;
|
||||
|
||||
for (int i=0;i<c.effects.size();i++) {
|
||||
effects.append(c.effects.at(i)->copy());
|
||||
for (int i=0;i<effects.size();i++) {
|
||||
copy->effects.append(effects.at(i)->copy());
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
void Clip::init() {
|
||||
qDebug() << "init was called";
|
||||
reset();
|
||||
clip_in = timeline_in = timeline_out = track = undeletable = 0;
|
||||
texture = NULL;
|
||||
|
||||
+1
-3
@@ -32,10 +32,8 @@ struct ClipCache {
|
||||
struct Clip
|
||||
{
|
||||
Clip();
|
||||
Clip(const Clip &c);
|
||||
Clip& operator= (const Clip&); // explicitly defaulted copy assignment
|
||||
~Clip();
|
||||
void copy(const Clip& c);
|
||||
Clip* copy();
|
||||
void init();
|
||||
void reset();
|
||||
bool undeletable;
|
||||
|
||||
+69
-46
@@ -9,24 +9,22 @@ Sequence::Sequence() {
|
||||
}
|
||||
|
||||
Sequence::~Sequence() {
|
||||
// dealloc all clips
|
||||
for (int i=0;i<clips.size();i++) {
|
||||
delete clips.at(i);
|
||||
}
|
||||
}
|
||||
|
||||
Clip& Sequence::new_clip() {
|
||||
clips.append(Clip());
|
||||
return clips[clips.size() - 1];
|
||||
}
|
||||
|
||||
Clip& Sequence::insert_clip(const Clip& c) {
|
||||
clips.append(c);
|
||||
return clips[clips.size() - 1];
|
||||
void Sequence::add_clip(Clip* c) {
|
||||
clips.append(c);
|
||||
}
|
||||
|
||||
int Sequence::clip_count() {
|
||||
return clips.count();
|
||||
return clips.size();
|
||||
}
|
||||
|
||||
Clip& Sequence::get_clip(int i) {
|
||||
return clips[i];
|
||||
Clip* Sequence::get_clip(int i) {
|
||||
return clips.at(i);
|
||||
}
|
||||
|
||||
void Sequence::delete_clip(int i) {
|
||||
@@ -41,15 +39,16 @@ void Sequence::delete_clip(int i) {
|
||||
// }
|
||||
|
||||
// finally remove from vector
|
||||
delete clips.at(i);
|
||||
clips.removeAt(i);
|
||||
}
|
||||
|
||||
long Sequence::getEndFrame() {
|
||||
long end = 0;
|
||||
for (int j=0;j<clip_count();j++) {
|
||||
Clip& c = get_clip(j);
|
||||
if (c.timeline_out > end) {
|
||||
end = c.timeline_out;
|
||||
Clip* c = get_clip(j);
|
||||
if (c->timeline_out > end) {
|
||||
end = c->timeline_out;
|
||||
}
|
||||
}
|
||||
return end;
|
||||
@@ -59,11 +58,11 @@ void Sequence::get_track_limits(int* video_tracks, int* audio_tracks) {
|
||||
int vt = 0;
|
||||
int at = 0;
|
||||
for (int j=0;j<clip_count();j++) {
|
||||
Clip& c = get_clip(j);
|
||||
if (c.track < 0 && c.track < vt) { // video clip
|
||||
vt = c.track;
|
||||
} else if (c.track > at) {
|
||||
at = c.track;
|
||||
Clip* c = get_clip(j);
|
||||
if (c->track < 0 && c->track < vt) { // video clip
|
||||
vt = c->track;
|
||||
} else if (c->track > at) {
|
||||
at = c->track;
|
||||
}
|
||||
}
|
||||
if (video_tracks != NULL) *video_tracks = vt;
|
||||
@@ -72,61 +71,85 @@ void Sequence::get_track_limits(int* video_tracks, int* audio_tracks) {
|
||||
|
||||
void Sequence::delete_area(long in, long out, int track) {
|
||||
for (int i=0;i<clip_count();i++) {
|
||||
Clip& c = get_clip(i);
|
||||
if (c.track == track && !c.undeletable) {
|
||||
if (c.timeline_in >= in && c.timeline_out <= out) {
|
||||
Clip* c = get_clip(i);
|
||||
if (c->track == track && !c->undeletable) {
|
||||
if (c->timeline_in >= in && c->timeline_out <= out) {
|
||||
// clips falls entirely within deletion area
|
||||
delete_clip(i);
|
||||
i--;
|
||||
} else if (c.timeline_in < in && c.timeline_out > out) {
|
||||
// middle of clip is within deletion area
|
||||
clips.append(clips.at(i)); // copy clip
|
||||
} else if (c->timeline_in < in && c->timeline_out > out) {
|
||||
// middle of clip is within deletion area
|
||||
|
||||
Clip& pre = get_clip(i);
|
||||
Clip& post = get_clip(clips.size()-1);
|
||||
// duplicate clip
|
||||
Clip* pre = get_clip(i);
|
||||
Clip* post = pre->copy();
|
||||
|
||||
pre.timeline_out = in;
|
||||
post.timeline_in = out;
|
||||
post.clip_in = pre.clip_in + pre.getLength() + (out - in);
|
||||
} else if (c.timeline_in < in && c.timeline_out > in) {
|
||||
pre->timeline_out = in;
|
||||
post->timeline_in = out;
|
||||
post->clip_in = pre->clip_in + pre->getLength() + (out - in);
|
||||
|
||||
add_clip(post);
|
||||
} else if (c->timeline_in < in && c->timeline_out > in) {
|
||||
// only out point is in deletion area
|
||||
c.timeline_out = in;
|
||||
} else if (c.timeline_in < out && c.timeline_out > out) {
|
||||
c->timeline_out = in;
|
||||
} else if (c->timeline_in < out && c->timeline_out > out) {
|
||||
// only in point is in deletion area
|
||||
c.clip_in += out - c.timeline_in;
|
||||
c.timeline_in = out;
|
||||
c->clip_in += out - c->timeline_in;
|
||||
c->timeline_in = out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sequence::split_clip(int i, long frame) {
|
||||
Clip& pre = get_clip(i);
|
||||
if (pre.timeline_in < frame && pre.timeline_out > frame) { // guard against attempts to split at in/out points
|
||||
clips.append(pre); // copy clip
|
||||
Clip* pre = get_clip(i);
|
||||
if (pre->timeline_in < frame && pre->timeline_out > frame) { // guard against attempts to split at in/out points
|
||||
Clip* post = pre->copy();
|
||||
|
||||
Clip& post = get_clip(clips.size()-1);
|
||||
pre->timeline_out = frame;
|
||||
post->timeline_in = frame;
|
||||
post->clip_in = pre->clip_in + pre->getLength();
|
||||
|
||||
pre.timeline_out = frame;
|
||||
post.timeline_in = frame;
|
||||
post.clip_in = pre.clip_in + pre.getLength();
|
||||
add_clip(post);
|
||||
}
|
||||
}
|
||||
|
||||
void Sequence::undo_add_current() {
|
||||
if (undo_stack.size() == UNDO_LIMIT) {
|
||||
delete undo_stack.at(0);
|
||||
undo_stack.removeFirst();
|
||||
} else {
|
||||
undo_pointer++;
|
||||
undo_stack.resize(undo_pointer);
|
||||
for (int i=undo_stack.size()-1;i>undo_pointer;i--) {
|
||||
delete undo_stack[i];
|
||||
undo_stack.removeLast();
|
||||
}
|
||||
}
|
||||
|
||||
// copy clips
|
||||
QVector<Clip*>* copied_clips = new QVector<Clip*>();
|
||||
for (int i=0;i<clip_count();i++) {
|
||||
copied_clips->append(get_clip(i)->copy());
|
||||
}
|
||||
undo_stack.append(copied_clips);
|
||||
}
|
||||
|
||||
void Sequence::set_undo(int i) {
|
||||
for (int i=0;i<clip_count();i++) {
|
||||
delete clips.at(i);
|
||||
}
|
||||
clips.clear();
|
||||
|
||||
QVector<Clip*>* copy_from_list = undo_stack[undo_pointer];
|
||||
for (int i=0;i<copy_from_list->size();i++) {
|
||||
add_clip(copy_from_list->at(i));
|
||||
}
|
||||
undo_stack.append(clips);
|
||||
}
|
||||
|
||||
void Sequence::undo() {
|
||||
if (undo_pointer > 0) {
|
||||
undo_pointer--;
|
||||
clips = undo_stack[undo_pointer];
|
||||
set_undo(undo_pointer);
|
||||
} else {
|
||||
qDebug() << "[INFO] No more undos";
|
||||
}
|
||||
@@ -136,6 +159,6 @@ void Sequence::redo() {
|
||||
qDebug() << "[INFO] No more redos";
|
||||
} else {
|
||||
undo_pointer++;
|
||||
clips = undo_stack[undo_pointer];
|
||||
set_undo(undo_pointer);
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -12,10 +12,9 @@ public:
|
||||
Sequence();
|
||||
~Sequence();
|
||||
QString name;
|
||||
Clip& new_clip();
|
||||
Clip& insert_clip(const Clip& c);
|
||||
void add_clip(Clip* c);
|
||||
int clip_count();
|
||||
Clip& get_clip(int i);
|
||||
Clip* get_clip(int i);
|
||||
void delete_clip(int i);
|
||||
void delete_area(long in, long out, int track);
|
||||
void split_clip(int i, long frame);
|
||||
@@ -31,9 +30,10 @@ public:
|
||||
void undo();
|
||||
void redo();
|
||||
private:
|
||||
QList<Clip> clips;
|
||||
QVector<Clip*> clips;
|
||||
|
||||
QVector<QList<Clip>> undo_stack;
|
||||
void set_undo(int i);
|
||||
QVector<QVector<Clip*>*> undo_stack;
|
||||
int undo_pointer;
|
||||
int undo_stack_start;
|
||||
};
|
||||
|
||||
+68
-66
@@ -96,27 +96,29 @@ void TimelineWidget::dropEvent(QDropEvent* event) {
|
||||
|
||||
panel_timeline->sequence->delete_area(g.in, g.out, g.track);
|
||||
|
||||
Clip& c = panel_timeline->sequence->new_clip();
|
||||
c.media = g.media;
|
||||
c.media_stream = g.media_stream;
|
||||
c.timeline_in = g.in;
|
||||
c.timeline_out = g.out;
|
||||
c.clip_in = g.clip_in;
|
||||
c.color_r = 128;
|
||||
c.color_g = 128;
|
||||
c.color_b = 192;
|
||||
c.sequence = panel_timeline->sequence;
|
||||
c.track = g.track;
|
||||
c.name = c.media->name;
|
||||
Clip* c = new Clip();
|
||||
c->media = g.media;
|
||||
c->media_stream = g.media_stream;
|
||||
c->timeline_in = g.in;
|
||||
c->timeline_out = g.out;
|
||||
c->clip_in = g.clip_in;
|
||||
c->color_r = 128;
|
||||
c->color_g = 128;
|
||||
c->color_b = 192;
|
||||
c->sequence = panel_timeline->sequence;
|
||||
c->track = g.track;
|
||||
c->name = c->media->name;
|
||||
|
||||
if (c.track < 0) {
|
||||
if (c->track < 0) {
|
||||
// add default video effects
|
||||
c.effects.append(create_effect(VIDEO_TRANSFORM_EFFECT, &c));
|
||||
c->effects.append(create_effect(VIDEO_TRANSFORM_EFFECT, c));
|
||||
} else {
|
||||
// add default audio effects
|
||||
c.effects.append(create_effect(AUDIO_VOLUME_EFFECT, &c));
|
||||
c.effects.append(create_effect(AUDIO_PAN_EFFECT, &c));
|
||||
}
|
||||
c->effects.append(create_effect(AUDIO_VOLUME_EFFECT, c));
|
||||
c->effects.append(create_effect(AUDIO_PAN_EFFECT, c));
|
||||
}
|
||||
|
||||
panel_timeline->sequence->add_clip(c);
|
||||
}
|
||||
|
||||
panel_timeline->ghosts.clear();
|
||||
@@ -154,8 +156,8 @@ void TimelineWidget::mousePressEvent(QMouseEvent *event) {
|
||||
panel_timeline->selections.clear();
|
||||
}
|
||||
|
||||
Clip& clip = panel_timeline->sequence->get_clip(clip_index);
|
||||
panel_timeline->selections.append({clip.timeline_in, clip.timeline_out, clip.track});
|
||||
Clip* clip = panel_timeline->sequence->get_clip(clip_index);
|
||||
panel_timeline->selections.append({clip->timeline_in, clip->timeline_out, clip->track});
|
||||
}
|
||||
panel_timeline->moving_init = true;
|
||||
} else {
|
||||
@@ -166,8 +168,7 @@ void TimelineWidget::mousePressEvent(QMouseEvent *event) {
|
||||
break;
|
||||
case TIMELINE_TOOL_EDIT:
|
||||
panel_timeline->seek(panel_timeline->drag_frame_start);
|
||||
panel_timeline->selecting = true;
|
||||
panel_timeline->repaint_timeline();
|
||||
panel_timeline->selecting = true;
|
||||
break;
|
||||
case TIMELINE_TOOL_RAZOR:
|
||||
{
|
||||
@@ -186,18 +187,17 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
if (event->modifiers() & Qt::AltModifier) { // if holding alt, duplicate rather than move
|
||||
// duplicate clips
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
Ghost& g = panel_timeline->ghosts[i];
|
||||
Clip& c = panel_timeline->sequence->insert_clip(*g.clip);
|
||||
Ghost& g = panel_timeline->ghosts[i];
|
||||
Clip* c = g.clip->copy();
|
||||
|
||||
c.timeline_in = g.in;
|
||||
c.timeline_out = g.out;
|
||||
c.track = g.track;
|
||||
c.undeletable = true;
|
||||
c->timeline_in = g.in;
|
||||
c->timeline_out = g.out;
|
||||
c->track = g.track;
|
||||
|
||||
// step 2 - delete anything that exists in area that clip is moving to
|
||||
panel_timeline->sequence->delete_area(g.in, g.out, g.track);
|
||||
|
||||
c.undeletable = false;
|
||||
panel_timeline->sequence->add_clip(c);
|
||||
}
|
||||
} else {
|
||||
// move clips
|
||||
@@ -284,7 +284,7 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
}
|
||||
}
|
||||
if (single_select) {
|
||||
panel_effect_controls->set_clip(&panel_timeline->sequence->get_clip(selected_clip));
|
||||
panel_effect_controls->set_clip(panel_timeline->sequence->get_clip(selected_clip));
|
||||
} else {
|
||||
panel_effect_controls->set_clip(NULL);
|
||||
}
|
||||
@@ -336,9 +336,9 @@ void validate_snapping(Ghost& g, long* frame_diff) {
|
||||
if (panel_timeline->snapping) {
|
||||
if (!subvalidate_snapping(g, frame_diff, panel_timeline->playhead)) {
|
||||
for (int j=0;j<panel_timeline->sequence->clip_count();j++) {
|
||||
Clip& c = panel_timeline->sequence->get_clip(j);
|
||||
if (!subvalidate_snapping(g, frame_diff, c.timeline_in)) {
|
||||
subvalidate_snapping(g, frame_diff, c.timeline_out);
|
||||
Clip* c = panel_timeline->sequence->get_clip(j);
|
||||
if (!subvalidate_snapping(g, frame_diff, c->timeline_in)) {
|
||||
subvalidate_snapping(g, frame_diff, c->timeline_out);
|
||||
}
|
||||
if (panel_timeline->snapped) break;
|
||||
}
|
||||
@@ -539,7 +539,10 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||
|
||||
if (panel_timeline->tool == TIMELINE_TOOL_EDIT || panel_timeline->tool == TIMELINE_TOOL_RAZOR) {
|
||||
int limit = panel_timeline->getFrameFromScreenPoint(10);
|
||||
if (panel_timeline->snapping && panel_timeline->cursor_frame > panel_timeline->playhead-limit-1 && panel_timeline->cursor_frame < panel_timeline->playhead+limit+1) {
|
||||
if (panel_timeline->snapping &&
|
||||
!panel_timeline->selecting &&
|
||||
panel_timeline->cursor_frame > panel_timeline->playhead-limit-1 &&
|
||||
panel_timeline->cursor_frame < panel_timeline->playhead+limit+1) {
|
||||
panel_timeline->cursor_frame = panel_timeline->playhead;
|
||||
}
|
||||
}
|
||||
@@ -557,8 +560,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||
s->in = qMin(in, out);
|
||||
s->out = qMax(in, out);
|
||||
}
|
||||
panel_timeline->playhead = qMin(panel_timeline->drag_frame_start, panel_timeline->cursor_frame);
|
||||
panel_timeline->repaint_timeline();
|
||||
panel_timeline->seek(qMin(panel_timeline->drag_frame_start, panel_timeline->cursor_frame));
|
||||
} else if (panel_timeline->moving_init) {
|
||||
if (panel_timeline->moving_proc) {
|
||||
update_ghosts((QPoint&) event->pos());
|
||||
@@ -567,8 +569,8 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||
// create ghosts
|
||||
for (int i=0;i<panel_timeline->sequence->clip_count();i++) {
|
||||
if (panel_timeline->is_clip_selected(i)) {
|
||||
Clip& c = panel_timeline->sequence->get_clip(i);
|
||||
panel_timeline->ghosts.append({&c, c.timeline_in, c.timeline_out, c.track, c.clip_in});
|
||||
Clip* c = panel_timeline->sequence->get_clip(i);
|
||||
panel_timeline->ghosts.append({c, c->timeline_in, c->timeline_out, c->track, c->clip_in});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -579,49 +581,49 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||
for (int j=0;j<panel_timeline->sequence->clip_count();j++) {
|
||||
// don't cache any currently selected clips
|
||||
Clip* c = panel_timeline->ghosts.at(i).clip;
|
||||
Clip& cc = panel_timeline->sequence->get_clip(j);
|
||||
Clip* cc = panel_timeline->sequence->get_clip(j);
|
||||
bool is_selected = false;
|
||||
for (int k=0;k<panel_timeline->ghosts.size();k++) {
|
||||
if (panel_timeline->ghosts.at(k).clip == &cc) {
|
||||
if (panel_timeline->ghosts.at(k).clip == cc) {
|
||||
is_selected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_selected) {
|
||||
if (cc.timeline_in < c->timeline_in) {
|
||||
if (cc->timeline_in < c->timeline_in) {
|
||||
// add clip to pre-cache UNLESS there is already a clip on that track closer to the ripple point
|
||||
bool found = false;
|
||||
for (int k=0;k<pre_clips.size();k++) {
|
||||
Clip* ccc = pre_clips.at(k);
|
||||
if (ccc->track == cc.track) {
|
||||
if (ccc->timeline_in < cc.timeline_in) {
|
||||
if (ccc->track == cc->track) {
|
||||
if (ccc->timeline_in < cc->timeline_in) {
|
||||
// clip is closer to ripple point than the one in cache, replace it
|
||||
ccc = &cc;
|
||||
ccc = cc;
|
||||
}
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// no clip from that track in the cache, add it
|
||||
pre_clips.append(&cc);
|
||||
pre_clips.append(cc);
|
||||
}
|
||||
} else {
|
||||
// add clip to post-cache UNLESS there is already a clip on that track closer to the ripple point
|
||||
bool found = false;
|
||||
for (int k=0;k<post_clips.size();k++) {
|
||||
Clip* ccc = post_clips.at(k);
|
||||
if (ccc->track == cc.track) {
|
||||
if (ccc->timeline_in > cc.timeline_in) {
|
||||
if (ccc->track == cc->track) {
|
||||
if (ccc->timeline_in > cc->timeline_in) {
|
||||
// clip is closer to ripple point than the one in cache, replace it
|
||||
ccc = &cc;
|
||||
ccc = cc;
|
||||
}
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// no clip from that track in the cache, add it
|
||||
post_clips.append(&cc);
|
||||
post_clips.append(cc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -641,7 +643,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||
int track = panel_timeline->cursor_track;
|
||||
bool repaint = false;
|
||||
for (int i=0;i<panel_timeline->sequence->clip_count();i++) {
|
||||
if (panel_timeline->sequence->get_clip(i).track == track) {
|
||||
if (panel_timeline->sequence->get_clip(i)->track == track) {
|
||||
panel_timeline->sequence->split_clip(i, panel_timeline->drag_frame_start);
|
||||
repaint = true;
|
||||
}
|
||||
@@ -658,14 +660,14 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||
long mouse_frame_upper = panel_timeline->getFrameFromScreenPoint(pos.x()+lim)+1;
|
||||
bool found = false;
|
||||
for (int i=0;i<panel_timeline->sequence->clip_count();i++) {
|
||||
Clip& c = panel_timeline->sequence->get_clip(i);
|
||||
if (c.track == mouse_track) {
|
||||
if (c.timeline_in > mouse_frame_lower && c.timeline_in < mouse_frame_upper) {
|
||||
Clip* c = panel_timeline->sequence->get_clip(i);
|
||||
if (c->track == mouse_track) {
|
||||
if (c->timeline_in > mouse_frame_lower && c->timeline_in < mouse_frame_upper) {
|
||||
panel_timeline->trim_target = i;
|
||||
panel_timeline->trim_in = true;
|
||||
found = true;
|
||||
break;
|
||||
} else if (c.timeline_out > mouse_frame_lower && c.timeline_out < mouse_frame_upper) {
|
||||
} else if (c->timeline_out > mouse_frame_lower && c->timeline_out < mouse_frame_upper) {
|
||||
panel_timeline->trim_target = i;
|
||||
panel_timeline->trim_in = false;
|
||||
found = true;
|
||||
@@ -706,16 +708,16 @@ void TimelineWidget::redraw_clips() {
|
||||
int video_track_limit = 0;
|
||||
int audio_track_limit = 0;
|
||||
for (int i=0;i<panel_timeline->sequence->clip_count();i++) {
|
||||
Clip& clip = panel_timeline->sequence->get_clip(i);
|
||||
if (is_track_visible(clip.track)) {
|
||||
if (clip.track < 0 && clip.track < video_track_limit) { // video clip
|
||||
video_track_limit = clip.track;
|
||||
} else if (clip.track > audio_track_limit) {
|
||||
audio_track_limit = clip.track;
|
||||
Clip* clip = panel_timeline->sequence->get_clip(i);
|
||||
if (is_track_visible(clip->track)) {
|
||||
if (clip->track < 0 && clip->track < video_track_limit) { // video clip
|
||||
video_track_limit = clip->track;
|
||||
} else if (clip->track > audio_track_limit) {
|
||||
audio_track_limit = clip->track;
|
||||
}
|
||||
|
||||
QRect clip_rect(panel_timeline->getScreenPointFromFrame(clip.timeline_in), getScreenPointFromTrack(clip.track), clip.getLength() * panel_timeline->zoom, track_height);
|
||||
clip_painter.fillRect(clip_rect, QColor(clip.color_r, clip.color_g, clip.color_b));
|
||||
QRect clip_rect(panel_timeline->getScreenPointFromFrame(clip->timeline_in), getScreenPointFromTrack(clip->track), clip->getLength() * panel_timeline->zoom, track_height);
|
||||
clip_painter.fillRect(clip_rect, QColor(clip->color_r, clip->color_g, clip->color_b));
|
||||
clip_painter.setPen(Qt::white);
|
||||
clip_painter.drawLine(clip_rect.bottomLeft(), clip_rect.topLeft());
|
||||
clip_painter.drawLine(clip_rect.topLeft(), clip_rect.topRight());
|
||||
@@ -723,13 +725,13 @@ void TimelineWidget::redraw_clips() {
|
||||
clip_painter.drawLine(clip_rect.bottomLeft(), clip_rect.bottomRight());
|
||||
clip_painter.drawLine(clip_rect.bottomRight(), clip_rect.topRight());
|
||||
|
||||
if (color_brightness(clip.color_r, clip.color_g, clip.color_b) > 160) {
|
||||
if (color_brightness(clip->color_r, clip->color_g, clip->color_b) > 160) {
|
||||
clip_painter.setPen(Qt::black);
|
||||
} else {
|
||||
clip_painter.setPen(Qt::white);
|
||||
}
|
||||
QRect text_rect(clip_rect.left() + CLIP_TEXT_PADDING, clip_rect.top() + CLIP_TEXT_PADDING, clip_rect.width() - CLIP_TEXT_PADDING - CLIP_TEXT_PADDING, clip_rect.height() - CLIP_TEXT_PADDING - CLIP_TEXT_PADDING);
|
||||
clip_painter.drawText(text_rect, 0, clip.name, &text_rect);
|
||||
clip_painter.drawText(text_rect, 0, clip->name, &text_rect);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -853,9 +855,9 @@ int TimelineWidget::getScreenPointFromTrack(int track) {
|
||||
|
||||
int TimelineWidget::getClipIndexFromCoords(long frame, int track) {
|
||||
for (int i=0;i<panel_timeline->sequence->clip_count();i++) {
|
||||
Clip& c = panel_timeline->sequence->get_clip(i);
|
||||
if (c.track == track) {
|
||||
if (frame >= c.timeline_in && frame < c.timeline_out) {
|
||||
Clip* c = panel_timeline->sequence->get_clip(i);
|
||||
if (c->track == track) {
|
||||
if (frame >= c->timeline_in && frame < c->timeline_out) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -66,6 +66,7 @@ void ViewerWidget::paintGL()
|
||||
bool render_audio = (panel_timeline->playing || force_audio);
|
||||
|
||||
cc_lock.lock();
|
||||
|
||||
for (int i=0;i<current_clips.size();i++) {
|
||||
Clip* c = current_clips.at(i);
|
||||
|
||||
@@ -110,7 +111,7 @@ void ViewerWidget::paintGL()
|
||||
glEnd();
|
||||
|
||||
c->texture->release();
|
||||
}
|
||||
}
|
||||
} else if (render_audio &&
|
||||
c->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
|
||||
playhead >= c->timeline_in &&
|
||||
|
||||
Reference in New Issue
Block a user