new undo system
Also enables undoing when working with node input arrays
This commit is contained in:
@@ -26,14 +26,14 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
void XMLConnectNodes(const XMLNodeData &xml_node_data, QUndoCommand *command)
|
||||
void XMLConnectNodes(const XMLNodeData &xml_node_data, MultiUndoCommand *command)
|
||||
{
|
||||
foreach (const XMLNodeData::SerializedConnection& con, xml_node_data.desired_connections) {
|
||||
Node* out = xml_node_data.node_ptrs.value(con.output);
|
||||
|
||||
if (out) {
|
||||
if (command) {
|
||||
new NodeEdgeAddCommand(out, con.input, con.element, command);
|
||||
command->add_child(new NodeEdgeAddCommand(out, con.input, con.element));
|
||||
} else {
|
||||
Node::ConnectEdge(out, con.input, con.element);
|
||||
}
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
#ifndef XMLREADLOOP_H
|
||||
#define XMLREADLOOP_H
|
||||
|
||||
#include <QUndoCommand>
|
||||
#include <QXmlStreamReader>
|
||||
|
||||
#include "project/item/footage/stream.h"
|
||||
#include "undo/undocommand.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
@@ -63,7 +63,7 @@ struct XMLNodeData {
|
||||
|
||||
};
|
||||
|
||||
void XMLConnectNodes(const XMLNodeData& xml_node_data, QUndoCommand* command = nullptr);
|
||||
void XMLConnectNodes(const XMLNodeData& xml_node_data, MultiUndoCommand *command = nullptr);
|
||||
|
||||
bool XMLReadNextStartElement(QXmlStreamReader* reader);
|
||||
|
||||
|
||||
+1
-1
@@ -479,7 +479,7 @@ void Core::ImportTaskComplete(Task* task)
|
||||
{
|
||||
ProjectImportTask* import_task = static_cast<ProjectImportTask*>(task);
|
||||
|
||||
QUndoCommand *command = import_task->GetCommand();
|
||||
MultiUndoCommand *command = import_task->GetCommand();
|
||||
|
||||
if (import_task->HasInvalidFiles()) {
|
||||
ProjectImportErrorDialog d(import_task->GetInvalidFiles(), main_window_);
|
||||
|
||||
@@ -124,21 +124,19 @@ void FootagePropertiesDialog::accept() {
|
||||
}
|
||||
}
|
||||
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
if (footage_->name() != footage_name_field_->text()) {
|
||||
new FootageChangeCommand(footage_,
|
||||
footage_name_field_->text(),
|
||||
command);
|
||||
command->add_child(new FootageChangeCommand(footage_,
|
||||
footage_name_field_->text()));
|
||||
}
|
||||
|
||||
for (int i=0;i<footage_->streams().size();i++) {
|
||||
bool stream_enabled = (track_list->item(i)->checkState() == Qt::Checked);
|
||||
|
||||
if (footage_->stream(i)->enabled() != stream_enabled) {
|
||||
new StreamEnableChangeCommand(footage_->stream(i),
|
||||
stream_enabled,
|
||||
command);
|
||||
command->add_child(new StreamEnableChangeCommand(footage_->stream(i),
|
||||
stream_enabled));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,8 +149,7 @@ void FootagePropertiesDialog::accept() {
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
FootagePropertiesDialog::FootageChangeCommand::FootageChangeCommand(Footage *footage, const QString &name, QUndoCommand* command) :
|
||||
UndoCommand(command),
|
||||
FootagePropertiesDialog::FootageChangeCommand::FootageChangeCommand(Footage *footage, const QString &name) :
|
||||
footage_(footage),
|
||||
new_name_(name)
|
||||
{
|
||||
@@ -163,20 +160,19 @@ Project *FootagePropertiesDialog::FootageChangeCommand::GetRelevantProject() con
|
||||
return footage_->project();
|
||||
}
|
||||
|
||||
void FootagePropertiesDialog::FootageChangeCommand::redo_internal()
|
||||
void FootagePropertiesDialog::FootageChangeCommand::redo()
|
||||
{
|
||||
old_name_ = footage_->name();
|
||||
|
||||
footage_->set_name(new_name_);
|
||||
}
|
||||
|
||||
void FootagePropertiesDialog::FootageChangeCommand::undo_internal()
|
||||
void FootagePropertiesDialog::FootageChangeCommand::undo()
|
||||
{
|
||||
footage_->set_name(old_name_);
|
||||
}
|
||||
|
||||
FootagePropertiesDialog::StreamEnableChangeCommand::StreamEnableChangeCommand(Stream *stream, bool enabled, QUndoCommand *command) :
|
||||
UndoCommand(command),
|
||||
FootagePropertiesDialog::StreamEnableChangeCommand::StreamEnableChangeCommand(Stream *stream, bool enabled) :
|
||||
stream_(stream),
|
||||
old_enabled_(stream->enabled()),
|
||||
new_enabled_(enabled)
|
||||
@@ -188,12 +184,12 @@ Project *FootagePropertiesDialog::StreamEnableChangeCommand::GetRelevantProject(
|
||||
return stream_->footage()->project();
|
||||
}
|
||||
|
||||
void FootagePropertiesDialog::StreamEnableChangeCommand::redo_internal()
|
||||
void FootagePropertiesDialog::StreamEnableChangeCommand::redo()
|
||||
{
|
||||
stream_->set_enabled(new_enabled_);
|
||||
}
|
||||
|
||||
void FootagePropertiesDialog::StreamEnableChangeCommand::undo_internal()
|
||||
void FootagePropertiesDialog::StreamEnableChangeCommand::undo()
|
||||
{
|
||||
stream_->set_enabled(old_enabled_);
|
||||
}
|
||||
|
||||
@@ -59,14 +59,12 @@ private:
|
||||
class FootageChangeCommand : public UndoCommand {
|
||||
public:
|
||||
FootageChangeCommand(Footage* footage,
|
||||
const QString& name,
|
||||
QUndoCommand *command = nullptr);
|
||||
const QString& name);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
Footage* footage_;
|
||||
@@ -78,14 +76,12 @@ private:
|
||||
class StreamEnableChangeCommand : public UndoCommand {
|
||||
public:
|
||||
StreamEnableChangeCommand(Stream* stream,
|
||||
bool enabled,
|
||||
QUndoCommand* command = nullptr);
|
||||
bool enabled);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
Stream* stream_;
|
||||
|
||||
@@ -27,7 +27,7 @@ AudioStreamProperties::AudioStreamProperties(AudioStream *stream) :
|
||||
{
|
||||
}
|
||||
|
||||
void AudioStreamProperties::Accept(QUndoCommand*)
|
||||
void AudioStreamProperties::Accept(MultiUndoCommand*)
|
||||
{
|
||||
Q_UNUSED(stream_)
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ class AudioStreamProperties : public StreamProperties
|
||||
public:
|
||||
AudioStreamProperties(AudioStream* stream);
|
||||
|
||||
virtual void Accept(QUndoCommand* parent) override;
|
||||
virtual void Accept(MultiUndoCommand* parent) override;
|
||||
|
||||
private:
|
||||
AudioStream* stream_;
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
#ifndef STREAMPROPERTIES_H
|
||||
#define STREAMPROPERTIES_H
|
||||
|
||||
#include <QUndoCommand>
|
||||
#include <QWidget>
|
||||
|
||||
#include "common/define.h"
|
||||
#include "undo/undocommand.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
@@ -33,7 +33,7 @@ class StreamProperties : public QWidget
|
||||
public:
|
||||
StreamProperties(QWidget* parent = nullptr);
|
||||
|
||||
virtual void Accept(QUndoCommand*){}
|
||||
virtual void Accept(MultiUndoCommand*){}
|
||||
|
||||
virtual bool SanityCheck(){return true;}
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ VideoStreamProperties::VideoStreamProperties(VideoStream *stream) :
|
||||
}
|
||||
}
|
||||
|
||||
void VideoStreamProperties::Accept(QUndoCommand *parent)
|
||||
void VideoStreamProperties::Accept(MultiUndoCommand *parent)
|
||||
{
|
||||
QString set_colorspace;
|
||||
|
||||
@@ -137,12 +137,11 @@ void VideoStreamProperties::Accept(QUndoCommand *parent)
|
||||
|| static_cast<VideoParams::Interlacing>(video_interlace_combo_->currentIndex()) != stream_->interlacing()
|
||||
|| pixel_aspect_combo_->GetPixelAspectRatio() != stream_->pixel_aspect_ratio()) {
|
||||
|
||||
new VideoStreamChangeCommand(stream_,
|
||||
video_premultiply_alpha_ ? video_premultiply_alpha_->isChecked() : stream_->premultiplied_alpha(),
|
||||
set_colorspace,
|
||||
static_cast<VideoParams::Interlacing>(video_interlace_combo_->currentIndex()),
|
||||
pixel_aspect_combo_->GetPixelAspectRatio(),
|
||||
parent);
|
||||
parent->add_child(new VideoStreamChangeCommand(stream_,
|
||||
video_premultiply_alpha_ ? video_premultiply_alpha_->isChecked() : stream_->premultiplied_alpha(),
|
||||
set_colorspace,
|
||||
static_cast<VideoParams::Interlacing>(video_interlace_combo_->currentIndex()),
|
||||
pixel_aspect_combo_->GetPixelAspectRatio()));
|
||||
}
|
||||
|
||||
if (stream_->video_type() == VideoStream::kVideoTypeImageSequence) {
|
||||
@@ -153,11 +152,10 @@ void VideoStreamProperties::Accept(QUndoCommand *parent)
|
||||
if (video_stream->start_time() != imgseq_start_time_->GetValue()
|
||||
|| video_stream->duration() != new_dur
|
||||
|| video_stream->frame_rate() != imgseq_frame_rate_->GetFrameRate()) {
|
||||
new ImageSequenceChangeCommand(video_stream,
|
||||
imgseq_start_time_->GetValue(),
|
||||
new_dur,
|
||||
imgseq_frame_rate_->GetFrameRate(),
|
||||
parent);
|
||||
parent->add_child(new ImageSequenceChangeCommand(video_stream,
|
||||
imgseq_start_time_->GetValue(),
|
||||
new_dur,
|
||||
imgseq_frame_rate_->GetFrameRate()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -181,9 +179,7 @@ VideoStreamProperties::VideoStreamChangeCommand::VideoStreamChangeCommand(VideoS
|
||||
bool premultiplied,
|
||||
QString colorspace,
|
||||
VideoParams::Interlacing interlacing,
|
||||
const rational &pixel_ar,
|
||||
QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
const rational &pixel_ar) :
|
||||
stream_(stream),
|
||||
new_premultiplied_(premultiplied),
|
||||
new_colorspace_(colorspace),
|
||||
@@ -197,7 +193,7 @@ Project *VideoStreamProperties::VideoStreamChangeCommand::GetRelevantProject() c
|
||||
return stream_->footage()->project();
|
||||
}
|
||||
|
||||
void VideoStreamProperties::VideoStreamChangeCommand::redo_internal()
|
||||
void VideoStreamProperties::VideoStreamChangeCommand::redo()
|
||||
{
|
||||
old_premultiplied_ = stream_->premultiplied_alpha();
|
||||
old_colorspace_ = stream_->colorspace(false);
|
||||
@@ -210,7 +206,7 @@ void VideoStreamProperties::VideoStreamChangeCommand::redo_internal()
|
||||
stream_->set_pixel_aspect_ratio(new_pixel_ar_);
|
||||
}
|
||||
|
||||
void VideoStreamProperties::VideoStreamChangeCommand::undo_internal()
|
||||
void VideoStreamProperties::VideoStreamChangeCommand::undo()
|
||||
{
|
||||
stream_->set_premultiplied_alpha(old_premultiplied_);
|
||||
stream_->set_colorspace(old_colorspace_);
|
||||
@@ -218,8 +214,7 @@ void VideoStreamProperties::VideoStreamChangeCommand::undo_internal()
|
||||
stream_->set_pixel_aspect_ratio(old_pixel_ar_);
|
||||
}
|
||||
|
||||
VideoStreamProperties::ImageSequenceChangeCommand::ImageSequenceChangeCommand(VideoStream *video_stream, int64_t start_index, int64_t duration, const rational &frame_rate, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
VideoStreamProperties::ImageSequenceChangeCommand::ImageSequenceChangeCommand(VideoStream *video_stream, int64_t start_index, int64_t duration, const rational &frame_rate) :
|
||||
video_stream_(video_stream),
|
||||
new_start_index_(start_index),
|
||||
new_duration_(duration),
|
||||
@@ -232,7 +227,7 @@ Project *VideoStreamProperties::ImageSequenceChangeCommand::GetRelevantProject()
|
||||
return video_stream_->footage()->project();
|
||||
}
|
||||
|
||||
void VideoStreamProperties::ImageSequenceChangeCommand::redo_internal()
|
||||
void VideoStreamProperties::ImageSequenceChangeCommand::redo()
|
||||
{
|
||||
old_start_index_ = video_stream_->start_time();
|
||||
video_stream_->set_start_time(new_start_index_);
|
||||
@@ -245,7 +240,7 @@ void VideoStreamProperties::ImageSequenceChangeCommand::redo_internal()
|
||||
video_stream_->set_timebase(new_frame_rate_.flipped());
|
||||
}
|
||||
|
||||
void VideoStreamProperties::ImageSequenceChangeCommand::undo_internal()
|
||||
void VideoStreamProperties::ImageSequenceChangeCommand::undo()
|
||||
{
|
||||
video_stream_->set_start_time(old_start_index_);
|
||||
video_stream_->set_duration(old_duration_);
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
|
||||
#include "project/item/footage/videostream.h"
|
||||
#include "streamproperties.h"
|
||||
#include "undo/undocommand.h"
|
||||
#include "widget/slider/integerslider.h"
|
||||
#include "widget/standardcombos/standardcombos.h"
|
||||
|
||||
@@ -38,7 +37,7 @@ class VideoStreamProperties : public StreamProperties
|
||||
public:
|
||||
VideoStreamProperties(VideoStream* stream);
|
||||
|
||||
virtual void Accept(QUndoCommand* parent) override;
|
||||
virtual void Accept(MultiUndoCommand *parent) override;
|
||||
|
||||
virtual bool SanityCheck() override;
|
||||
|
||||
@@ -89,14 +88,12 @@ private:
|
||||
bool premultiplied,
|
||||
QString colorspace,
|
||||
VideoParams::Interlacing interlacing,
|
||||
const rational& pixel_ar,
|
||||
QUndoCommand* parent = nullptr);
|
||||
const rational& pixel_ar);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
VideoStream* stream_;
|
||||
@@ -118,14 +115,12 @@ private:
|
||||
ImageSequenceChangeCommand(VideoStream* video_stream,
|
||||
int64_t start_index,
|
||||
int64_t duration,
|
||||
const rational& frame_rate,
|
||||
QUndoCommand* parent = nullptr);
|
||||
const rational& frame_rate);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
VideoStream* video_stream_;
|
||||
|
||||
@@ -194,30 +194,28 @@ KeyframePropertiesDialog::KeyframePropertiesDialog(const QVector<NodeKeyframe*>
|
||||
|
||||
void KeyframePropertiesDialog::accept()
|
||||
{
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
rational new_time = Timecode::timestamp_to_time(time_slider_->GetValue(), timebase_);
|
||||
int new_type = type_select_->currentData().toInt();
|
||||
|
||||
foreach (NodeKeyframe* key, keys_) {
|
||||
if (time_slider_->isEnabled() && !time_slider_->IsTristate()) {
|
||||
new NodeParamSetKeyframeTimeCommand(key, new_time, command);
|
||||
command->add_child(new NodeParamSetKeyframeTimeCommand(key, new_time));
|
||||
}
|
||||
|
||||
if (new_type > -1) {
|
||||
new KeyframeSetTypeCommand(key, static_cast<NodeKeyframe::Type>(new_type), command);
|
||||
command->add_child(new KeyframeSetTypeCommand(key, static_cast<NodeKeyframe::Type>(new_type)));
|
||||
}
|
||||
|
||||
if (bezier_group_->isEnabled()) {
|
||||
new KeyframeSetBezierControlPoint(key,
|
||||
NodeKeyframe::kInHandle,
|
||||
QPointF(bezier_in_x_slider_->GetValue(), bezier_in_y_slider_->GetValue()),
|
||||
command);
|
||||
command->add_child(new KeyframeSetBezierControlPoint(key,
|
||||
NodeKeyframe::kInHandle,
|
||||
QPointF(bezier_in_x_slider_->GetValue(), bezier_in_y_slider_->GetValue())));
|
||||
|
||||
new KeyframeSetBezierControlPoint(key,
|
||||
NodeKeyframe::kOutHandle,
|
||||
QPointF(bezier_out_x_slider_->GetValue(), bezier_out_y_slider_->GetValue()),
|
||||
command);
|
||||
command->add_child(new KeyframeSetBezierControlPoint(key,
|
||||
NodeKeyframe::kOutHandle,
|
||||
QPointF(bezier_out_x_slider_->GetValue(), bezier_out_y_slider_->GetValue())));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -139,9 +139,7 @@ void SequenceDialog::accept()
|
||||
SequenceDialog::SequenceParamCommand::SequenceParamCommand(Sequence* s,
|
||||
const VideoParams& video_params,
|
||||
const AudioParams &audio_params,
|
||||
const QString& name,
|
||||
QUndoCommand* parent) :
|
||||
UndoCommand(parent),
|
||||
const QString& name) :
|
||||
sequence_(s),
|
||||
new_video_params_(video_params),
|
||||
new_audio_params_(audio_params),
|
||||
@@ -157,14 +155,14 @@ Project *SequenceDialog::SequenceParamCommand::GetRelevantProject() const
|
||||
return sequence_->project();
|
||||
}
|
||||
|
||||
void SequenceDialog::SequenceParamCommand::redo_internal()
|
||||
void SequenceDialog::SequenceParamCommand::redo()
|
||||
{
|
||||
sequence_->set_video_params(new_video_params_);
|
||||
sequence_->set_audio_params(new_audio_params_);
|
||||
sequence_->set_name(new_name_);
|
||||
}
|
||||
|
||||
void SequenceDialog::SequenceParamCommand::undo_internal()
|
||||
void SequenceDialog::SequenceParamCommand::undo()
|
||||
{
|
||||
sequence_->set_video_params(old_video_params_);
|
||||
sequence_->set_audio_params(old_audio_params_);
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace olive {
|
||||
* This dialog exposes all the parameters of a Sequence to users allowing them to set up a Sequence however they wish.
|
||||
* A Sequence can be sent to this dialog through the constructor. All fields will be filled using that Sequence's
|
||||
* parameters, allowing the user to view and edit them. Accepting the dialog will apply them back to that Sequence,
|
||||
* either directly or using a QUndoCommand (see SetUndoable()).
|
||||
* either directly or using an UndoCommand (see SetUndoable()).
|
||||
*
|
||||
* If creating a new Sequence, the Sequence must still be constructed first before sending it to SequenceDialog.
|
||||
* SequenceDialog does not create any new objects. In most cases when creating a new Sequence, editing its parameters
|
||||
@@ -104,21 +104,19 @@ private:
|
||||
QLineEdit* name_field_;
|
||||
|
||||
/**
|
||||
* @brief A QUndoCommand for setting the parameters on a sequence
|
||||
* @brief An UndoCommand for setting the parameters on a sequence
|
||||
*/
|
||||
class SequenceParamCommand : public UndoCommand {
|
||||
public:
|
||||
SequenceParamCommand(Sequence* s,
|
||||
const VideoParams& video_params,
|
||||
const AudioParams& audio_params,
|
||||
const QString& name,
|
||||
QUndoCommand* parent = nullptr);
|
||||
const QString& name);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
Sequence* sequence_;
|
||||
|
||||
@@ -43,6 +43,7 @@ set(OLIVE_SOURCES
|
||||
node/node.cpp
|
||||
node/nodecopypaste.h
|
||||
node/nodecopypaste.cpp
|
||||
node/splitvalue.h
|
||||
node/traverser.h
|
||||
node/traverser.cpp
|
||||
node/value.h
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace olive {
|
||||
|
||||
PolygonGenerator::PolygonGenerator()
|
||||
{
|
||||
points_input_ = new NodeInput(this, QStringLiteral("points_in"), NodeValue::kVec2);
|
||||
points_input_ = new NodeInput(this, QStringLiteral("points_in"), NodeValue::kVec2, QVector2D(0, 0));
|
||||
points_input_->SetIsArray(true);
|
||||
|
||||
color_input_ = new NodeInput(this, QStringLiteral("color_in"), NodeValue::kColor, QVariant::fromValue(Color(1.0, 1.0, 1.0)));
|
||||
|
||||
+137
-76
@@ -23,14 +23,16 @@
|
||||
#include "common/bezier.h"
|
||||
#include "common/lerp.h"
|
||||
#include "common/xmlutils.h"
|
||||
#include "core.h"
|
||||
#include "node.h"
|
||||
#include "project/item/footage/stream.h"
|
||||
#include "widget/nodeview/nodeviewundo.h"
|
||||
|
||||
#define super NodeConnectable
|
||||
|
||||
namespace olive {
|
||||
|
||||
NodeInput::NodeInput(Node* parent, const QString& id, NodeValue::Type type, const QVector<QVariant> &default_value)
|
||||
NodeInput::NodeInput(Node* parent, const QString& id, NodeValue::Type type, const SplitValue &default_value)
|
||||
{
|
||||
Init(parent, id, type, default_value);
|
||||
}
|
||||
@@ -42,7 +44,7 @@ NodeInput::NodeInput(Node *parent, const QString &id, NodeValue::Type type, cons
|
||||
|
||||
NodeInput::NodeInput(Node* parent, const QString &id, NodeValue::Type type)
|
||||
{
|
||||
Init(parent, id, type, QVector<QVariant>());
|
||||
Init(parent, id, type, SplitValue());
|
||||
}
|
||||
|
||||
NodeInput::~NodeInput()
|
||||
@@ -217,7 +219,16 @@ void NodeInput::childEvent(QChildEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
void NodeInput::Init(Node* parent, const QString &id, NodeValue::Type type, const QVector<QVariant>& default_val)
|
||||
void NodeInput::ClearElement(int index)
|
||||
{
|
||||
GetImmediate(index)->delete_all_keyframes();
|
||||
|
||||
SetIsKeyframing(false, index);
|
||||
|
||||
SetSplitStandardValue(default_value_, index);
|
||||
}
|
||||
|
||||
void NodeInput::Init(Node* parent, const QString &id, NodeValue::Type type, const SplitValue& default_val)
|
||||
{
|
||||
setParent(parent);
|
||||
|
||||
@@ -381,11 +392,25 @@ void NodeInput::SaveImmediate(QXmlStreamWriter* writer, int element) const
|
||||
}
|
||||
}
|
||||
|
||||
void NodeInput::ChangeArraySizeInternal(int size)
|
||||
void NodeInput::ArrayResizeInternal(int size)
|
||||
{
|
||||
array_size_ = size;
|
||||
emit ArraySizeChanged(array_size_);
|
||||
emit ValueChanged(TimeRange(RATIONAL_MIN, RATIONAL_MAX), -1);
|
||||
if (array_size_ != size) {
|
||||
// Update array size
|
||||
if (array_size_ < size) {
|
||||
// Size is larger, create any immediates that don't exist
|
||||
for (int i=subinputs_.size(); i<size; i++) {
|
||||
subinputs_.append(CreateImmediate());
|
||||
}
|
||||
|
||||
// Note that we do not delete any immediates when decreasing size since the user might still
|
||||
// want that data. Therefore it's important to note that array_size_ does NOT necessarily
|
||||
// equal subinputs_.size()
|
||||
}
|
||||
|
||||
array_size_ = size;
|
||||
emit ArraySizeChanged(array_size_);
|
||||
emit ValueChanged(TimeRange(RATIONAL_MIN, RATIONAL_MAX), -1);
|
||||
}
|
||||
}
|
||||
|
||||
NodeInputImmediate *NodeInput::CreateImmediate()
|
||||
@@ -440,79 +465,95 @@ QVector<Node *> NodeInput::GetImmediateDependencies() const
|
||||
return GetDependencies(false, false);
|
||||
}
|
||||
|
||||
void NodeInput::ArrayInsert(int index)
|
||||
void NodeInput::ArrayAppend(bool undoable)
|
||||
{
|
||||
// Add new input
|
||||
subinputs_.insert(index, CreateImmediate());
|
||||
|
||||
ChangeArraySizeInternal(array_size_ + 1);
|
||||
|
||||
// Move connections down
|
||||
std::map<int, Node*> copied_edges = edges();
|
||||
for (auto it=copied_edges.crbegin(); it!=copied_edges.crend(); it++) {
|
||||
if (it->first >= index) {
|
||||
// Disconnect this and reconnect it one element down
|
||||
DisconnectEdge(it->second, this, it->first);
|
||||
ConnectEdge(it->second, this, it->first + 1);
|
||||
}
|
||||
}
|
||||
ArrayResize(ArraySize() + 1, undoable);
|
||||
}
|
||||
|
||||
void NodeInput::ArrayRemove(int index)
|
||||
void NodeInput::ArrayInsert(int index, bool undoable)
|
||||
{
|
||||
// Remove input
|
||||
delete subinputs_.takeAt(index);
|
||||
ChangeArraySizeInternal(array_size_ - 1);
|
||||
if (undoable) {
|
||||
Core::instance()->undo_stack()->push(new ArrayInsertCommand(this, index));
|
||||
} else {
|
||||
// Add new input
|
||||
ArrayResizeInternal(ArraySize() + 1);
|
||||
|
||||
// Move connections up
|
||||
std::map<int, Node*> copied_edges = edges();
|
||||
for (auto it=copied_edges.cbegin(); it!=copied_edges.cend(); it++) {
|
||||
if (it->first >= index) {
|
||||
// Disconnect this and reconnect it one element up if it's not the element being removed
|
||||
DisconnectEdge(it->second, this, it->first);
|
||||
|
||||
if (it->first > index) {
|
||||
ConnectEdge(it->second, this, it->first - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeInput::ArrayPrepend()
|
||||
{
|
||||
ArrayInsert(0);
|
||||
}
|
||||
|
||||
void NodeInput::ArrayResize(int size)
|
||||
{
|
||||
if (array_size_ != size) {
|
||||
// Update array size
|
||||
if (array_size_ < size) {
|
||||
// Size is larger, create any immediates that don't exist
|
||||
for (int i=subinputs_.size(); i<size; i++) {
|
||||
subinputs_.append(CreateImmediate());
|
||||
// Move connections down
|
||||
std::map<int, Node*> copied_edges = edges();
|
||||
for (auto it=copied_edges.crbegin(); it!=copied_edges.crend(); it++) {
|
||||
if (it->first >= index) {
|
||||
// Disconnect this and reconnect it one element down
|
||||
DisconnectEdge(it->second, this, it->first);
|
||||
ConnectEdge(it->second, this, it->first + 1);
|
||||
}
|
||||
}
|
||||
|
||||
ChangeArraySizeInternal(size);
|
||||
|
||||
if (array_size_ > size) {
|
||||
// Decreasing in size, disconnect any extraneous edges
|
||||
for (int i=size; i<array_size_; i++) {
|
||||
try {
|
||||
DisconnectEdge(edges().at(i), this, i);
|
||||
} catch (std::out_of_range&) {}
|
||||
}
|
||||
|
||||
// Note that we do not delete any immediates since the user might still want that data.
|
||||
// Therefore it's important to note that array_size_ does NOT necessarily equal subinputs_.size()
|
||||
// Shift values and keyframes up one element
|
||||
for (int i=ArraySize()-1; i>index; i--) {
|
||||
CopyValuesOfElement(this, this, i-1, i);
|
||||
}
|
||||
|
||||
// Reset value of element we just "inserted"
|
||||
ClearElement(index);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeInput::ArrayRemoveLast()
|
||||
void NodeInput::ArrayRemove(int index, bool undoable)
|
||||
{
|
||||
ArrayResize(ArraySize() - 1);
|
||||
if (undoable) {
|
||||
Core::instance()->undo_stack()->push(new ArrayRemoveCommand(this, index));
|
||||
} else {
|
||||
// Remove input
|
||||
ArrayResizeInternal(ArraySize() - 1);
|
||||
|
||||
// Move connections up
|
||||
std::map<int, Node*> copied_edges = edges();
|
||||
for (auto it=copied_edges.cbegin(); it!=copied_edges.cend(); it++) {
|
||||
if (it->first >= index) {
|
||||
// Disconnect this and reconnect it one element up if it's not the element being removed
|
||||
DisconnectEdge(it->second, this, it->first);
|
||||
|
||||
if (it->first > index) {
|
||||
ConnectEdge(it->second, this, it->first - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shift values and keyframes down one element
|
||||
for (int i=index; i<ArraySize(); i++) {
|
||||
// Copying ArraySize()+1 is actually legal because immediates are never deleted
|
||||
CopyValuesOfElement(this, this, i+1, i);
|
||||
}
|
||||
|
||||
// Reset value of last element
|
||||
ClearElement(ArraySize());
|
||||
}
|
||||
}
|
||||
|
||||
void NodeInput::ArrayPrepend(bool undoable)
|
||||
{
|
||||
ArrayInsert(0, undoable);
|
||||
}
|
||||
|
||||
void NodeInput::ArrayResize(int size, bool undoable)
|
||||
{
|
||||
if (array_size_ == size) {
|
||||
return;
|
||||
}
|
||||
|
||||
ArrayResizeCommand* c = new ArrayResizeCommand(this, size);
|
||||
|
||||
if (undoable) {
|
||||
Core::instance()->undo_stack()->push(c);
|
||||
} else {
|
||||
c->redo();
|
||||
delete c;
|
||||
}
|
||||
}
|
||||
|
||||
void NodeInput::ArrayRemoveLast(bool undoable)
|
||||
{
|
||||
ArrayResize(ArraySize() - 1, undoable);
|
||||
}
|
||||
|
||||
QVariant NodeInput::GetValueAtTime(const rational &time, int element) const
|
||||
@@ -520,9 +561,9 @@ QVariant NodeInput::GetValueAtTime(const rational &time, int element) const
|
||||
return NodeValue::combine_track_values_into_normal_value(data_type_, GetSplitValuesAtTime(time, element));
|
||||
}
|
||||
|
||||
QVector<QVariant> NodeInput::GetSplitValuesAtTime(const rational &time, int element) const
|
||||
SplitValue NodeInput::GetSplitValuesAtTime(const rational &time, int element) const
|
||||
{
|
||||
QVector<QVariant> vals;
|
||||
SplitValue vals;
|
||||
|
||||
int nb_tracks = GetNumberOfKeyframeTracks();
|
||||
|
||||
@@ -669,26 +710,31 @@ void NodeInput::CopyValues(NodeInput *source, NodeInput *dest, bool include_conn
|
||||
}
|
||||
}
|
||||
|
||||
void NodeInput::CopyValuesOfElement(NodeInput *src, NodeInput *dst, int element)
|
||||
void NodeInput::CopyValuesOfElement(NodeInput *src, NodeInput *dst, int src_element, int dst_element)
|
||||
{
|
||||
if (dst_element >= dst->subinputs_.size()) {
|
||||
qDebug() << "Ignored destination element that was out of array bounds";
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy standard value
|
||||
dst->SetSplitStandardValue(src->GetSplitStandardValue(element), element);
|
||||
dst->SetSplitStandardValue(src->GetSplitStandardValue(src_element), dst_element);
|
||||
|
||||
// Copy keyframes
|
||||
dst->GetImmediate(element)->delete_all_keyframes();
|
||||
foreach (const NodeKeyframeTrack& track, src->GetImmediate(element)->keyframe_tracks()) {
|
||||
dst->GetImmediate(dst_element)->delete_all_keyframes();
|
||||
foreach (const NodeKeyframeTrack& track, src->GetImmediate(src_element)->keyframe_tracks()) {
|
||||
foreach (NodeKeyframe* key, track) {
|
||||
key->copy(dst);
|
||||
key->copy(dst_element, dst);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy keyframing state
|
||||
if (src->IsKeyframable()) {
|
||||
dst->SetIsKeyframing(src->IsKeyframing(element), element);
|
||||
dst->SetIsKeyframing(src->IsKeyframing(src_element), dst_element);
|
||||
}
|
||||
|
||||
// If this is the root of an array, copy the array size
|
||||
if (element == -1) {
|
||||
if (src_element == -1 && dst_element == -1) {
|
||||
dst->ArrayResize(src->ArraySize());
|
||||
}
|
||||
}
|
||||
@@ -839,4 +885,19 @@ uint qHash(const NodeInput::KeyframeTrackReference &ref, uint seed)
|
||||
return qHash(ref.input, seed) ^ qHash(ref.element, seed) ^ qHash(ref.track, seed);
|
||||
}
|
||||
|
||||
Project *NodeInput::ArrayRemoveCommand::GetRelevantProject() const
|
||||
{
|
||||
return input_->parent()->parent()->project();
|
||||
}
|
||||
|
||||
Project *NodeInput::ArrayResizeCommand::GetRelevantProject() const
|
||||
{
|
||||
return input_->parent()->parent()->project();
|
||||
}
|
||||
|
||||
Project *NodeInput::ArrayInsertCommand::GetRelevantProject() const
|
||||
{
|
||||
return input_->parent()->parent()->project();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+155
-20
@@ -26,6 +26,8 @@
|
||||
#include "node/connectable.h"
|
||||
#include "node/inputimmediate.h"
|
||||
#include "node/value.h"
|
||||
#include "splitvalue.h"
|
||||
#include "undo/undocommand.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
@@ -47,7 +49,7 @@ public:
|
||||
* saving/loading data from this Node so that parameter order can be changed without issues loading data saved by an
|
||||
* older version. This of course assumes that parameters don't change their ID.
|
||||
*/
|
||||
NodeInput(Node* parent, const QString &id, NodeValue::Type type, const QVector<QVariant>& default_value);
|
||||
NodeInput(Node* parent, const QString &id, NodeValue::Type type, const SplitValue& default_value);
|
||||
NodeInput(Node* parent, const QString &id, NodeValue::Type type, const QVariant& default_value);
|
||||
NodeInput(Node* parent, const QString &id, NodeValue::Type type);
|
||||
|
||||
@@ -176,7 +178,7 @@ public:
|
||||
/**
|
||||
* @brief Get non-keyframed value split into components (the way it's stored)
|
||||
*/
|
||||
const QVector<QVariant>& GetSplitStandardValue(int element = -1) const
|
||||
const SplitValue& GetSplitStandardValue(int element = -1) const
|
||||
{
|
||||
return GetImmediate(element)->get_split_standard_value();
|
||||
}
|
||||
@@ -197,7 +199,7 @@ public:
|
||||
SetSplitStandardValue(NodeValue::split_normal_value_into_track_values(data_type_, value), element);
|
||||
}
|
||||
|
||||
void SetSplitStandardValue(const QVector<QVariant>& value, int element = -1)
|
||||
void SetSplitStandardValue(const SplitValue& value, int element = -1)
|
||||
{
|
||||
GetImmediate(element)->set_split_standard_value(value);
|
||||
|
||||
@@ -231,7 +233,11 @@ public:
|
||||
*/
|
||||
static void CopyValues(NodeInput* source, NodeInput* dest, bool include_connections = true, bool traverse_arrays = true);
|
||||
|
||||
static void CopyValuesOfElement(NodeInput* source, NodeInput* dst, int element);
|
||||
static void CopyValuesOfElement(NodeInput* source, NodeInput* dst, int src_element, int dst_element);
|
||||
static void CopyValuesOfElement(NodeInput* source, NodeInput* dst, int element)
|
||||
{
|
||||
CopyValuesOfElement(source, dst, element, element);
|
||||
}
|
||||
|
||||
QStringList get_combobox_strings() const;
|
||||
|
||||
@@ -244,7 +250,7 @@ public:
|
||||
return NodeValue::combine_track_values_into_normal_value(data_type_, default_value_);
|
||||
}
|
||||
|
||||
const QVector<QVariant>& GetSplitDefaultValue() const
|
||||
const SplitValue& GetSplitDefaultValue() const
|
||||
{
|
||||
return default_value_;
|
||||
}
|
||||
@@ -279,33 +285,36 @@ public:
|
||||
|
||||
void SetIsKeyframing(bool keyframing, int element)
|
||||
{
|
||||
Q_ASSERT(IsKeyframable());
|
||||
if (IsKeyframable()) {
|
||||
qDebug() << "Ignored set keyframing because this input is not keyframable";
|
||||
return;
|
||||
}
|
||||
|
||||
GetImmediate(element)->set_is_keyframing(keyframing);
|
||||
|
||||
emit KeyframeEnableChanged(keyframing, element);
|
||||
}
|
||||
|
||||
void ArrayAppend()
|
||||
{
|
||||
ArrayResize(ArraySize() + 1);
|
||||
}
|
||||
/// Alias for ArrayResize(ArraySize() + 1)
|
||||
void ArrayAppend(bool undoable = false);
|
||||
|
||||
void ArrayInsert(int index);
|
||||
void ArrayInsert(int index, bool undoable = false);
|
||||
|
||||
void ArrayRemove(int index);
|
||||
void ArrayRemove(int index, bool undoable = false);
|
||||
|
||||
void ArrayPrepend();
|
||||
/// Alias for ArrayInsert(0)
|
||||
void ArrayPrepend(bool undoable = false);
|
||||
|
||||
void ArrayResize(int size);
|
||||
void ArrayResize(int size, bool undoable = false);
|
||||
|
||||
/// Alias for ArrayResize(ArraySize() - 1)
|
||||
void ArrayRemoveLast(bool undoable = false);
|
||||
|
||||
int ArraySize() const
|
||||
{
|
||||
return array_size_;
|
||||
}
|
||||
|
||||
void ArrayRemoveLast();
|
||||
|
||||
int GetNumberOfKeyframeTracks() const
|
||||
{
|
||||
return NodeValue::get_number_of_keyframe_tracks(data_type_);
|
||||
@@ -318,7 +327,7 @@ public:
|
||||
*/
|
||||
QVariant GetValueAtTime(const rational& time, int element = -1) const;
|
||||
|
||||
QVector<QVariant> GetSplitValuesAtTime(const rational& time, int element = -1) const;
|
||||
SplitValue GetSplitValuesAtTime(const rational& time, int element = -1) const;
|
||||
|
||||
/**
|
||||
* @brief Calculate the stored value for a specific track
|
||||
@@ -378,13 +387,139 @@ protected:
|
||||
virtual void childEvent(QChildEvent* e) override;
|
||||
|
||||
private:
|
||||
void Init(Node *parent, const QString& id, NodeValue::Type type, const QVector<QVariant> &default_val);
|
||||
class ArrayInsertCommand : public UndoCommand
|
||||
{
|
||||
public:
|
||||
ArrayInsertCommand(NodeInput* input, int index) :
|
||||
input_(input),
|
||||
index_(index)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
virtual void redo() override
|
||||
{
|
||||
input_->ArrayInsert(index_, false);
|
||||
}
|
||||
|
||||
virtual void undo() override
|
||||
{
|
||||
input_->ArrayRemove(index_, false);
|
||||
}
|
||||
|
||||
private:
|
||||
NodeInput* input_;
|
||||
int index_;
|
||||
|
||||
};
|
||||
|
||||
class ArrayRemoveCommand : public UndoCommand
|
||||
{
|
||||
public:
|
||||
ArrayRemoveCommand(NodeInput* input, int index) :
|
||||
input_(input),
|
||||
index_(index)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo() override
|
||||
{
|
||||
// Save immediate data
|
||||
is_keyframing_ = input_->IsKeyframing(index_);
|
||||
standard_value_ = input_->GetSplitStandardValue(index_);
|
||||
keyframes_ = input_->GetImmediate(index_)->keyframe_tracks();
|
||||
input_->GetImmediate(index_)->delete_all_keyframes(&memory_manager_);
|
||||
|
||||
input_->ArrayRemove(index_, false);
|
||||
}
|
||||
|
||||
virtual void undo() override
|
||||
{
|
||||
input_->ArrayInsert(index_, false);
|
||||
|
||||
// Restore keyframes
|
||||
foreach (const NodeKeyframeTrack& track, keyframes_) {
|
||||
foreach (NodeKeyframe* key, track) {
|
||||
key->setParent(input_);
|
||||
}
|
||||
}
|
||||
input_->SetSplitStandardValue(standard_value_, index_);
|
||||
input_->SetIsKeyframing(is_keyframing_, index_);
|
||||
}
|
||||
|
||||
private:
|
||||
NodeInput* input_;
|
||||
int index_;
|
||||
|
||||
SplitValue standard_value_;
|
||||
bool is_keyframing_;
|
||||
QVector<NodeKeyframeTrack> keyframes_;
|
||||
QObject memory_manager_;
|
||||
|
||||
};
|
||||
|
||||
class ArrayResizeCommand : public UndoCommand
|
||||
{
|
||||
public:
|
||||
ArrayResizeCommand(NodeInput* input, int size) :
|
||||
input_(input),
|
||||
size_(size)
|
||||
{}
|
||||
|
||||
virtual void redo() override
|
||||
{
|
||||
old_size_ = input_->array_size_;
|
||||
|
||||
if (old_size_ > size_) {
|
||||
// Decreasing in size, disconnect any extraneous edges
|
||||
for (int i=size_; i<old_size_; i++) {
|
||||
try {
|
||||
Node* output = input_->edges().at(i);
|
||||
|
||||
removed_connections_.insert(i, output);
|
||||
|
||||
DisconnectEdge(output, input_, i);
|
||||
} catch (std::out_of_range&) {}
|
||||
}
|
||||
}
|
||||
|
||||
input_->ArrayResizeInternal(size_);
|
||||
}
|
||||
|
||||
virtual void undo() override
|
||||
{
|
||||
for (auto it=removed_connections_.cbegin(); it!=removed_connections_.cend(); it++) {
|
||||
ConnectEdge(it.value(), input_, it.key());
|
||||
}
|
||||
removed_connections_.clear();
|
||||
|
||||
input_->ArrayResizeInternal(old_size_);
|
||||
}
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
private:
|
||||
NodeInput* input_;
|
||||
int size_;
|
||||
int old_size_;
|
||||
|
||||
QHash<int, Node*> removed_connections_;
|
||||
|
||||
};
|
||||
|
||||
void ClearElement(int index);
|
||||
|
||||
void Init(Node *parent, const QString& id, NodeValue::Type type, const SplitValue &default_val);
|
||||
|
||||
void LoadImmediate(QXmlStreamReader *reader, int element, XMLNodeData& xml_node_data, const QAtomicInt* cancelled);
|
||||
|
||||
void SaveImmediate(QXmlStreamWriter *writer, int element) const;
|
||||
|
||||
void ChangeArraySizeInternal(int size);
|
||||
void ArrayResizeInternal(int size);
|
||||
|
||||
NodeInputImmediate* CreateImmediate();
|
||||
|
||||
@@ -426,7 +561,7 @@ private:
|
||||
|
||||
QVector<NodeInputImmediate*> subinputs_;
|
||||
|
||||
QVector<QVariant> default_value_;
|
||||
SplitValue default_value_;
|
||||
|
||||
/**
|
||||
* @brief Unique identifier of this input within this node
|
||||
|
||||
@@ -106,21 +106,21 @@ void NodeInputDragger::End()
|
||||
return;
|
||||
}
|
||||
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
if (input_->IsKeyframing(element_)) {
|
||||
if (drag_created_key_) {
|
||||
// We created a keyframe in this process
|
||||
new NodeParamInsertKeyframeCommand(input_, dragging_key_, command);
|
||||
command->add_child(new NodeParamInsertKeyframeCommand(input_, dragging_key_));
|
||||
}
|
||||
|
||||
// We just set a keyframe's value
|
||||
// We do this even when inserting a keyframe because we don't actually perform an insert in this undo command
|
||||
// so this will ensure the ValueChanged() signal is sent correctly
|
||||
new NodeParamSetKeyframeValueCommand(dragging_key_, end_value_, start_value_, command);
|
||||
command->add_child(new NodeParamSetKeyframeValueCommand(dragging_key_, end_value_, start_value_));
|
||||
} else {
|
||||
// We just set the standard value
|
||||
new NodeParamSetStandardValueCommand(input_, track_, element_, end_value_, start_value_, command);
|
||||
command->add_child(new NodeParamSetStandardValueCommand(input_, track_, element_, end_value_, start_value_));
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
NodeInputImmediate::NodeInputImmediate(NodeValue::Type type, const QVector<QVariant> &default_val) :
|
||||
NodeInputImmediate::NodeInputImmediate(NodeValue::Type type, const SplitValue &default_val) :
|
||||
keyframing_(false)
|
||||
{
|
||||
int track_size = NodeValue::get_number_of_keyframe_tracks(type);
|
||||
@@ -43,7 +43,7 @@ void NodeInputImmediate::set_standard_value_on_track(const QVariant &value, int
|
||||
standard_value_.replace(track, value);
|
||||
}
|
||||
|
||||
void NodeInputImmediate::set_split_standard_value(const QVector<QVariant> &value)
|
||||
void NodeInputImmediate::set_split_standard_value(const SplitValue &value)
|
||||
{
|
||||
for (int i=0; i<value.size() && i<standard_value_.size(); i++) {
|
||||
standard_value_[i] = value[i];
|
||||
@@ -267,11 +267,15 @@ void NodeInputImmediate::remove_keyframe(NodeKeyframe *key)
|
||||
keyframe_tracks_[key->track()].removeOne(key);
|
||||
}
|
||||
|
||||
void NodeInputImmediate::delete_all_keyframes()
|
||||
void NodeInputImmediate::delete_all_keyframes(QObject* parent)
|
||||
{
|
||||
for (NodeKeyframeTrack& track : keyframe_tracks_) {
|
||||
while (!track.isEmpty()) {
|
||||
delete track.first();
|
||||
if (parent) {
|
||||
track.first()->setParent(parent);
|
||||
} else {
|
||||
delete track.first();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "common/xmlutils.h"
|
||||
#include "node/keyframe.h"
|
||||
#include "node/value.h"
|
||||
#include "splitvalue.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
@@ -33,7 +34,7 @@ class NodeInput;
|
||||
class NodeInputImmediate
|
||||
{
|
||||
public:
|
||||
NodeInputImmediate(NodeValue::Type type, const QVector<QVariant>& default_val);
|
||||
NodeInputImmediate(NodeValue::Type type, const SplitValue& default_val);
|
||||
|
||||
/**
|
||||
* @brief Internal insert function, automatically does an insertion sort based on the keyframe's time
|
||||
@@ -42,19 +43,19 @@ public:
|
||||
|
||||
void remove_keyframe(NodeKeyframe* key);
|
||||
|
||||
void delete_all_keyframes();
|
||||
void delete_all_keyframes(QObject *parent = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Get non-keyframed value split into components (the way it's stored)
|
||||
*/
|
||||
const QVector<QVariant>& get_split_standard_value() const
|
||||
const SplitValue& get_split_standard_value() const
|
||||
{
|
||||
return standard_value_;
|
||||
}
|
||||
|
||||
void set_standard_value_on_track(const QVariant &value, int track = 0);
|
||||
|
||||
void set_split_standard_value(const QVector<QVariant>& value);
|
||||
void set_split_standard_value(const SplitValue& value);
|
||||
|
||||
/**
|
||||
* @brief Retrieve a list of keyframe objects for all tracks at a given time
|
||||
@@ -149,7 +150,7 @@ private:
|
||||
/**
|
||||
* @brief Non-keyframed value
|
||||
*/
|
||||
QVector<QVariant> standard_value_;
|
||||
SplitValue standard_value_;
|
||||
|
||||
/**
|
||||
* @brief Internal keyframe array
|
||||
|
||||
@@ -45,14 +45,19 @@ NodeKeyframe::~NodeKeyframe()
|
||||
setParent(nullptr);
|
||||
}
|
||||
|
||||
NodeKeyframe *NodeKeyframe::copy(QObject* parent) const
|
||||
NodeKeyframe *NodeKeyframe::copy(int element, QObject *parent) const
|
||||
{
|
||||
NodeKeyframe* copy = new NodeKeyframe(time_, value_, type_, track_, element_, parent);
|
||||
NodeKeyframe* copy = new NodeKeyframe(time_, value_, type_, track_, element, parent);
|
||||
copy->bezier_control_in_ = bezier_control_in_;
|
||||
copy->bezier_control_out_ = bezier_control_out_;
|
||||
return copy;
|
||||
}
|
||||
|
||||
NodeKeyframe *NodeKeyframe::copy(QObject* parent) const
|
||||
{
|
||||
return copy(element_, parent);
|
||||
}
|
||||
|
||||
NodeInput *NodeKeyframe::parent() const
|
||||
{
|
||||
return static_cast<NodeInput*>(QObject::parent());
|
||||
|
||||
@@ -65,6 +65,7 @@ public:
|
||||
|
||||
virtual ~NodeKeyframe() override;
|
||||
|
||||
NodeKeyframe* copy(int element, QObject* parent = nullptr) const;
|
||||
NodeKeyframe* copy(QObject* parent = nullptr) const;
|
||||
|
||||
NodeInput* parent() const;
|
||||
|
||||
+4
-4
@@ -247,7 +247,7 @@ TimeRange Node::OutputTimeAdjustment(NodeInput *, int, const TimeRange &input_ti
|
||||
return input_time;
|
||||
}
|
||||
|
||||
QVector<Node *> Node::CopyDependencyGraph(const QVector<Node *> &nodes, QUndoCommand* command)
|
||||
QVector<Node *> Node::CopyDependencyGraph(const QVector<Node *> &nodes, MultiUndoCommand *command)
|
||||
{
|
||||
int nb_nodes = nodes.size();
|
||||
|
||||
@@ -263,7 +263,7 @@ QVector<Node *> Node::CopyDependencyGraph(const QVector<Node *> &nodes, QUndoCom
|
||||
// Add to graph
|
||||
NodeGraph* graph = static_cast<NodeGraph*>(nodes.at(i)->parent());
|
||||
if (command) {
|
||||
new NodeAddCommand(graph, c, command);
|
||||
command->add_child(new NodeAddCommand(graph, c));
|
||||
} else {
|
||||
c->setParent(graph);
|
||||
}
|
||||
@@ -277,7 +277,7 @@ QVector<Node *> Node::CopyDependencyGraph(const QVector<Node *> &nodes, QUndoCom
|
||||
return copies;
|
||||
}
|
||||
|
||||
void Node::CopyDependencyGraph(const QVector<Node *> &src, const QVector<Node *> &dst, QUndoCommand *command)
|
||||
void Node::CopyDependencyGraph(const QVector<Node *> &src, const QVector<Node *> &dst, MultiUndoCommand *command)
|
||||
{
|
||||
for (int i=0; i<src.size(); i++) {
|
||||
foreach (NodeInput* input, src.at(i)->inputs()) {
|
||||
@@ -290,7 +290,7 @@ void Node::CopyDependencyGraph(const QVector<Node *> &src, const QVector<Node *>
|
||||
NodeInput* dst_input = dst.at(i)->GetInputWithID(input->id());
|
||||
|
||||
if (command) {
|
||||
new NodeEdgeAddCommand(dst_output, dst_input, it->first, command);
|
||||
command->add_child(new NodeEdgeAddCommand(dst_output, dst_input, it->first));
|
||||
} else {
|
||||
ConnectEdge(dst_output, dst_input, it->first);
|
||||
}
|
||||
|
||||
+2
-2
@@ -368,8 +368,8 @@ public:
|
||||
/**
|
||||
* @brief Clones a set of nodes and connects the new ones the way the old ones were
|
||||
*/
|
||||
static QVector<Node*> CopyDependencyGraph(const QVector<Node*>& nodes, QUndoCommand *command);
|
||||
static void CopyDependencyGraph(const QVector<Node*>& src, const QVector<Node*>& dst, QUndoCommand *command);
|
||||
static QVector<Node*> CopyDependencyGraph(const QVector<Node*>& nodes, MultiUndoCommand *command);
|
||||
static void CopyDependencyGraph(const QVector<Node*>& src, const QVector<Node*>& dst, MultiUndoCommand *command);
|
||||
|
||||
/**
|
||||
* @brief Return whether this Node can be deleted or not
|
||||
|
||||
@@ -56,7 +56,7 @@ void NodeCopyPasteService::CopyNodesToClipboard(const QVector<Node *> &nodes, vo
|
||||
Core::CopyStringToClipboard(copy_str);
|
||||
}
|
||||
|
||||
QVector<Node *> NodeCopyPasteService::PasteNodesFromClipboard(NodeGraph *graph, QUndoCommand* command, void *userdata)
|
||||
QVector<Node *> NodeCopyPasteService::PasteNodesFromClipboard(NodeGraph *graph, MultiUndoCommand* command, void *userdata)
|
||||
{
|
||||
QString clipboard = Core::PasteStringFromClipboard();
|
||||
|
||||
@@ -121,7 +121,7 @@ QVector<Node *> NodeCopyPasteService::PasteNodesFromClipboard(NodeGraph *graph,
|
||||
|
||||
// Add all nodes to graph
|
||||
foreach (Node* n, pasted_nodes) {
|
||||
new NodeAddCommand(graph, n, command);
|
||||
command->add_child(new NodeAddCommand(graph, n));
|
||||
}
|
||||
|
||||
// Make connections
|
||||
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
protected:
|
||||
void CopyNodesToClipboard(const QVector<Node *> &nodes, void* userdata = nullptr);
|
||||
|
||||
QVector<Node*> PasteNodesFromClipboard(NodeGraph *graph, QUndoCommand *command, void* userdata = nullptr);
|
||||
QVector<Node*> PasteNodesFromClipboard(NodeGraph *graph, MultiUndoCommand *command, void* userdata = nullptr);
|
||||
|
||||
virtual void CopyNodesToClipboardInternal(QXmlStreamWriter *writer, void* userdata);
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2020 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/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef SPLITVALUE_H
|
||||
#define SPLITVALUE_H
|
||||
|
||||
#include <QVariant>
|
||||
#include <QVector>
|
||||
|
||||
namespace olive {
|
||||
|
||||
using SplitValue = QVector<QVariant>;
|
||||
|
||||
}
|
||||
|
||||
#endif // SPLITVALUE_H
|
||||
@@ -330,9 +330,9 @@ bool ProjectViewModel::dropMimeData(const QMimeData *data, Qt::DropAction action
|
||||
quint64 enabled_streams;
|
||||
|
||||
// Loop through all data
|
||||
QUndoCommand* move_command = new QUndoCommand();
|
||||
MultiUndoCommand* move_command = new MultiUndoCommand();
|
||||
|
||||
move_command->setText(tr("Move Items"));
|
||||
move_command->set_name(tr("Move Items"));
|
||||
|
||||
while (!stream.atEnd()) {
|
||||
stream >> enabled_streams >> r >> item_ptr;
|
||||
@@ -343,9 +343,7 @@ bool ProjectViewModel::dropMimeData(const QMimeData *data, Qt::DropAction action
|
||||
// no-op
|
||||
|
||||
if (item != drop_location && item->parent() != drop_location && !ItemIsParentOfChild(item, drop_location)) {
|
||||
MoveItemCommand* mic = new MoveItemCommand(this, item, static_cast<Folder*>(drop_location), move_command);
|
||||
|
||||
Q_UNUSED(mic)
|
||||
move_command->add_child(new MoveItemCommand(this, item, static_cast<Folder*>(drop_location)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -499,16 +497,14 @@ QModelIndex ProjectViewModel::CreateIndexFromItem(Item *item, int column)
|
||||
|
||||
ProjectViewModel::MoveItemCommand::MoveItemCommand(ProjectViewModel *model,
|
||||
Item *item,
|
||||
Folder *destination,
|
||||
QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
Folder *destination) :
|
||||
model_(model),
|
||||
item_(item),
|
||||
destination_(destination)
|
||||
{
|
||||
source_ = static_cast<Folder*>(item->parent());
|
||||
|
||||
setText(QCoreApplication::translate("MoveItemCommand", "Move Item"));
|
||||
set_name(QCoreApplication::translate("MoveItemCommand", "Move Item"));
|
||||
}
|
||||
|
||||
Project *ProjectViewModel::MoveItemCommand::GetRelevantProject() const
|
||||
@@ -516,25 +512,24 @@ Project *ProjectViewModel::MoveItemCommand::GetRelevantProject() const
|
||||
return model_->project();
|
||||
}
|
||||
|
||||
void ProjectViewModel::MoveItemCommand::redo_internal()
|
||||
void ProjectViewModel::MoveItemCommand::redo()
|
||||
{
|
||||
model_->MoveItemInternal(item_, destination_);
|
||||
}
|
||||
|
||||
void ProjectViewModel::MoveItemCommand::undo_internal()
|
||||
void ProjectViewModel::MoveItemCommand::undo()
|
||||
{
|
||||
model_->MoveItemInternal(item_, source_);
|
||||
}
|
||||
|
||||
ProjectViewModel::RenameItemCommand::RenameItemCommand(ProjectViewModel* model, Item *item, const QString &name, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
ProjectViewModel::RenameItemCommand::RenameItemCommand(ProjectViewModel* model, Item *item, const QString &name) :
|
||||
model_(model),
|
||||
item_(item),
|
||||
new_name_(name)
|
||||
{
|
||||
old_name_ = item->name();
|
||||
|
||||
setText(QCoreApplication::translate("RenameItemCommand", "Rename Item"));
|
||||
set_name(QCoreApplication::translate("RenameItemCommand", "Rename Item"));
|
||||
}
|
||||
|
||||
Project *ProjectViewModel::RenameItemCommand::GetRelevantProject() const
|
||||
@@ -542,18 +537,17 @@ Project *ProjectViewModel::RenameItemCommand::GetRelevantProject() const
|
||||
return model_->project();
|
||||
}
|
||||
|
||||
void ProjectViewModel::RenameItemCommand::redo_internal()
|
||||
void ProjectViewModel::RenameItemCommand::redo()
|
||||
{
|
||||
model_->RenameChild(item_, new_name_);
|
||||
}
|
||||
|
||||
void ProjectViewModel::RenameItemCommand::undo_internal()
|
||||
void ProjectViewModel::RenameItemCommand::undo()
|
||||
{
|
||||
model_->RenameChild(item_, old_name_);
|
||||
}
|
||||
|
||||
ProjectViewModel::AddItemCommand::AddItemCommand(ProjectViewModel* model, Item* folder, Item* child, QUndoCommand* parent) :
|
||||
UndoCommand(parent),
|
||||
ProjectViewModel::AddItemCommand::AddItemCommand(ProjectViewModel* model, Item* folder, Item* child) :
|
||||
model_(model),
|
||||
parent_(folder),
|
||||
child_(child)
|
||||
@@ -571,18 +565,17 @@ Project *ProjectViewModel::AddItemCommand::GetRelevantProject() const
|
||||
return model_->project();
|
||||
}
|
||||
|
||||
void ProjectViewModel::AddItemCommand::redo_internal()
|
||||
void ProjectViewModel::AddItemCommand::redo()
|
||||
{
|
||||
model_->AddChild(parent_, child_);
|
||||
}
|
||||
|
||||
void ProjectViewModel::AddItemCommand::undo_internal()
|
||||
void ProjectViewModel::AddItemCommand::undo()
|
||||
{
|
||||
model_->RemoveChild(parent_, child_, &memory_manager_);
|
||||
}
|
||||
|
||||
ProjectViewModel::RemoveItemCommand::RemoveItemCommand(ProjectViewModel *model, Item *item, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
ProjectViewModel::RemoveItemCommand::RemoveItemCommand(ProjectViewModel *model, Item *item) :
|
||||
model_(model),
|
||||
item_(item)
|
||||
{
|
||||
@@ -599,12 +592,12 @@ Project *ProjectViewModel::RemoveItemCommand::GetRelevantProject() const
|
||||
return model_->project();
|
||||
}
|
||||
|
||||
void ProjectViewModel::RemoveItemCommand::redo_internal()
|
||||
void ProjectViewModel::RemoveItemCommand::redo()
|
||||
{
|
||||
model_->RemoveChild(parent_, item_, &memory_manager_);
|
||||
}
|
||||
|
||||
void ProjectViewModel::RemoveItemCommand::undo_internal()
|
||||
void ProjectViewModel::RemoveItemCommand::undo()
|
||||
{
|
||||
model_->AddChild(parent_, item_);
|
||||
}
|
||||
|
||||
@@ -110,18 +110,17 @@ public:
|
||||
QModelIndex CreateIndexFromItem(Item* item, int column = 0);
|
||||
|
||||
/**
|
||||
* @brief A QUndoCommand for moving an item from one folder to another folder
|
||||
* @brief An UndoCommand for moving an item from one folder to another folder
|
||||
*/
|
||||
class MoveItemCommand : public UndoCommand {
|
||||
public:
|
||||
MoveItemCommand(ProjectViewModel* model, Item* item, Folder* destination, QUndoCommand* parent = nullptr);
|
||||
MoveItemCommand(ProjectViewModel* model, Item* item, Folder* destination);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void redo() override;
|
||||
|
||||
virtual void undo_internal() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
ProjectViewModel* model_;
|
||||
@@ -132,18 +131,17 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A QUndoCommand for renaming an item
|
||||
* @brief An UndoCommand for renaming an item
|
||||
*/
|
||||
class RenameItemCommand : public UndoCommand {
|
||||
public:
|
||||
RenameItemCommand(ProjectViewModel* model, Item* item, const QString& name, QUndoCommand* parent = nullptr);
|
||||
RenameItemCommand(ProjectViewModel* model, Item* item, const QString& name);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void redo() override;
|
||||
|
||||
virtual void undo_internal() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
ProjectViewModel* model_;
|
||||
@@ -153,18 +151,17 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A QUndoCommand for adding an item
|
||||
* @brief An UndoCommand for adding an item
|
||||
*/
|
||||
class AddItemCommand : public UndoCommand {
|
||||
public:
|
||||
AddItemCommand(ProjectViewModel* model, Item* folder, Item *child, QUndoCommand* parent = nullptr);
|
||||
AddItemCommand(ProjectViewModel* model, Item* folder, Item *child);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void redo() override;
|
||||
|
||||
virtual void undo_internal() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
ProjectViewModel* model_;
|
||||
@@ -179,14 +176,13 @@ public:
|
||||
*/
|
||||
class RemoveItemCommand : public UndoCommand {
|
||||
public:
|
||||
RemoveItemCommand(ProjectViewModel* model, Item* item, QUndoCommand* parent = nullptr);
|
||||
RemoveItemCommand(ProjectViewModel* model, Item* item);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void redo() override;
|
||||
|
||||
virtual void undo_internal() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
ProjectViewModel* model_;
|
||||
@@ -240,8 +236,8 @@ private:
|
||||
* This function will emit a signal indicating that rows are moving, set `destination` as the new parent of `item`,
|
||||
* and then emit a signal that the row has finished moving.
|
||||
*
|
||||
* It's not recommended to use this function directly in most cases since it does not create a QUndoCommand allowing
|
||||
* the user to undo the move. Instead this function should primarily be called from QUndoCommands belonging to this
|
||||
* It's not recommended to use this function directly in most cases since it does not create an UndoCommand allowing
|
||||
* the user to undo the move. Instead this function should primarily be called from UndoCommands belonging to this
|
||||
* class (e.g. MoveItemCommand).
|
||||
*/
|
||||
void MoveItemInternal(Item* item, Item* destination);
|
||||
|
||||
@@ -50,7 +50,7 @@ const int &ProjectImportTask::GetFileCount() const
|
||||
|
||||
bool ProjectImportTask::Run()
|
||||
{
|
||||
command_ = new QUndoCommand();
|
||||
command_ = new MultiUndoCommand();
|
||||
|
||||
int imported = 0;
|
||||
|
||||
@@ -65,7 +65,7 @@ bool ProjectImportTask::Run()
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectImportTask::Import(Folder *folder, QFileInfoList import, int &counter, QUndoCommand* parent_command)
|
||||
void ProjectImportTask::Import(Folder *folder, QFileInfoList import, int &counter, MultiUndoCommand* parent_command)
|
||||
{
|
||||
for (int i=0; i<import.size(); i++) {
|
||||
if (IsCancelled()) {
|
||||
@@ -100,10 +100,9 @@ void ProjectImportTask::Import(Folder *folder, QFileInfoList import, int &counte
|
||||
f->set_name(file_info.fileName());
|
||||
|
||||
// Create undoable command that adds the items to the model
|
||||
new ProjectViewModel::AddItemCommand(model_,
|
||||
folder,
|
||||
f,
|
||||
parent_command);
|
||||
parent_command->add_child(new ProjectViewModel::AddItemCommand(model_,
|
||||
folder,
|
||||
f));
|
||||
|
||||
// Recursively follow this path
|
||||
Import(f, entry_list, counter, parent_command);
|
||||
@@ -122,10 +121,9 @@ void ProjectImportTask::Import(Folder *folder, QFileInfoList import, int &counte
|
||||
ValidateImageSequence(footage, import, i);
|
||||
|
||||
// Create undoable command that adds the items to the model
|
||||
new ProjectViewModel::AddItemCommand(model_,
|
||||
folder,
|
||||
footage,
|
||||
parent_command);
|
||||
parent_command->add_child(new ProjectViewModel::AddItemCommand(model_,
|
||||
folder,
|
||||
footage));
|
||||
} else {
|
||||
// Add to list so we can tell the user about it later
|
||||
invalid_files_.append(file_info.absoluteFilePath());
|
||||
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
|
||||
const int& GetFileCount() const;
|
||||
|
||||
QUndoCommand* GetCommand() const
|
||||
MultiUndoCommand* GetCommand() const
|
||||
{
|
||||
return command_;
|
||||
}
|
||||
@@ -57,7 +57,7 @@ protected:
|
||||
virtual bool Run() override;
|
||||
|
||||
private:
|
||||
void Import(Folder* folder, QFileInfoList import, int& counter, QUndoCommand *parent_command);
|
||||
void Import(Folder* folder, QFileInfoList import, int& counter, MultiUndoCommand *parent_command);
|
||||
|
||||
void ValidateImageSequence(Footage *footage, QFileInfoList &info_list, int index);
|
||||
|
||||
@@ -67,7 +67,7 @@ private:
|
||||
|
||||
static int64_t GetImageSequenceLimit(const QString &start_fn, int64_t start, bool up);
|
||||
|
||||
QUndoCommand* command_;
|
||||
MultiUndoCommand* command_;
|
||||
|
||||
ProjectViewModel* model_;
|
||||
|
||||
|
||||
+20
-16
@@ -24,34 +24,38 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
UndoCommand::UndoCommand(QUndoCommand *parent) :
|
||||
QUndoCommand(parent)
|
||||
void MultiUndoCommand::redo()
|
||||
{
|
||||
for (auto it=children_.cbegin(); it!=children_.cend(); it++) {
|
||||
(*it)->redo_and_set_modified();
|
||||
}
|
||||
}
|
||||
|
||||
void UndoCommand::redo()
|
||||
void MultiUndoCommand::undo()
|
||||
{
|
||||
redo_internal();
|
||||
|
||||
modified_ = GetRelevantProject()->is_modified();
|
||||
GetRelevantProject()->set_modified(true);
|
||||
for (auto it=children_.crbegin(); it!=children_.crend(); it++) {
|
||||
(*it)->undo_and_set_modified();
|
||||
}
|
||||
}
|
||||
|
||||
void UndoCommand::undo()
|
||||
void UndoCommand::redo_and_set_modified()
|
||||
{
|
||||
undo_internal();
|
||||
redo();
|
||||
|
||||
GetRelevantProject()->set_modified(modified_);
|
||||
project_ = GetRelevantProject();
|
||||
if (project_) {
|
||||
modified_ = project_->is_modified();
|
||||
project_->set_modified(true);
|
||||
}
|
||||
}
|
||||
|
||||
void UndoCommand::redo_internal()
|
||||
void UndoCommand::undo_and_set_modified()
|
||||
{
|
||||
QUndoCommand::redo();
|
||||
}
|
||||
undo();
|
||||
|
||||
void UndoCommand::undo_internal()
|
||||
{
|
||||
QUndoCommand::undo();
|
||||
if (project_) {
|
||||
project_->set_modified(modified_);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+61
-9
@@ -21,31 +21,83 @@
|
||||
#ifndef UNDOCOMMAND_H
|
||||
#define UNDOCOMMAND_H
|
||||
|
||||
#include <QUndoCommand>
|
||||
#include <list>
|
||||
#include <QString>
|
||||
#include <vector>
|
||||
|
||||
#include "common/define.h"
|
||||
#include "node/graph.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class Project;
|
||||
|
||||
class UndoCommand : public QUndoCommand
|
||||
class UndoCommand
|
||||
{
|
||||
public:
|
||||
UndoCommand(QUndoCommand* parent = nullptr);
|
||||
UndoCommand() = default;
|
||||
|
||||
virtual ~UndoCommand(){}
|
||||
|
||||
DISABLE_COPY_MOVE(UndoCommand)
|
||||
|
||||
virtual void redo() = 0;
|
||||
virtual void undo() = 0;
|
||||
|
||||
void redo_and_set_modified();
|
||||
|
||||
void undo_and_set_modified();
|
||||
|
||||
virtual Project* GetRelevantProject() const = 0;
|
||||
|
||||
const QString& name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
void set_name(const QString& name)
|
||||
{
|
||||
name_ = name;
|
||||
}
|
||||
|
||||
private:
|
||||
bool modified_;
|
||||
|
||||
QString name_;
|
||||
|
||||
Project* project_;
|
||||
|
||||
};
|
||||
|
||||
class MultiUndoCommand : public UndoCommand
|
||||
{
|
||||
public:
|
||||
MultiUndoCommand() = default;
|
||||
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
virtual Project* GetRelevantProject() const = 0;
|
||||
virtual Project* GetRelevantProject() const override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal();
|
||||
virtual void undo_internal();
|
||||
void add_child(UndoCommand* command)
|
||||
{
|
||||
children_.push_back(command);
|
||||
}
|
||||
|
||||
int child_count() const
|
||||
{
|
||||
return children_.size();
|
||||
}
|
||||
|
||||
UndoCommand* child(int i) const
|
||||
{
|
||||
return children_[i];
|
||||
}
|
||||
|
||||
private:
|
||||
bool modified_;
|
||||
std::vector<UndoCommand*> children_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
+96
-2
@@ -20,15 +20,109 @@
|
||||
|
||||
#include "undostack.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
namespace olive {
|
||||
|
||||
void UndoStack::pushIfHasChildren(QUndoCommand *command)
|
||||
const int UndoStack::kMaxUndoCommands = 200;
|
||||
|
||||
UndoStack::UndoStack()
|
||||
{
|
||||
if (command->childCount() > 0) {
|
||||
undo_action_ = new QAction();
|
||||
connect(undo_action_, &QAction::triggered, this, &UndoStack::undo);
|
||||
|
||||
redo_action_ = new QAction();
|
||||
connect(redo_action_, &QAction::triggered, this, &UndoStack::redo);
|
||||
|
||||
UpdateActions();
|
||||
}
|
||||
|
||||
UndoStack::~UndoStack()
|
||||
{
|
||||
clear();
|
||||
|
||||
delete undo_action_;
|
||||
delete redo_action_;
|
||||
}
|
||||
|
||||
void UndoStack::pushIfHasChildren(MultiUndoCommand *command)
|
||||
{
|
||||
if (command->child_count() > 0) {
|
||||
push(command);
|
||||
} else {
|
||||
delete command;
|
||||
}
|
||||
}
|
||||
|
||||
void UndoStack::push(UndoCommand *command)
|
||||
{
|
||||
command->redo_and_set_modified();
|
||||
commands_.push_back(command);
|
||||
|
||||
if (commands_.size() > kMaxUndoCommands) {
|
||||
delete commands_.front();
|
||||
commands_.pop_front();
|
||||
}
|
||||
|
||||
if (CanRedo()) {
|
||||
for (auto it=undone_commands_.cbegin(); it!=undone_commands_.cend(); it++) {
|
||||
delete (*it);
|
||||
}
|
||||
undone_commands_.clear();
|
||||
}
|
||||
|
||||
UpdateActions();
|
||||
}
|
||||
|
||||
void UndoStack::undo()
|
||||
{
|
||||
if (CanUndo()) {
|
||||
// Undo most recently done command
|
||||
commands_.back()->undo_and_set_modified();
|
||||
|
||||
// Place at the front of the "undone commands" list
|
||||
undone_commands_.push_front(commands_.back());
|
||||
|
||||
// Remove undone command from the commands list
|
||||
commands_.pop_back();
|
||||
|
||||
// Update actions
|
||||
UpdateActions();
|
||||
}
|
||||
}
|
||||
|
||||
void UndoStack::redo()
|
||||
{
|
||||
if (CanRedo()) {
|
||||
// Redo most recently undone command
|
||||
undone_commands_.front()->redo_and_set_modified();
|
||||
|
||||
// Place at the back of the done commands list
|
||||
commands_.push_back(undone_commands_.front());
|
||||
|
||||
// Remove done command from undone list
|
||||
undone_commands_.pop_front();
|
||||
|
||||
// Update actions
|
||||
UpdateActions();
|
||||
}
|
||||
}
|
||||
|
||||
void UndoStack::clear()
|
||||
{
|
||||
for (auto it=commands_.cbegin(); it!=commands_.cend(); it++) {
|
||||
delete (*it);
|
||||
}
|
||||
commands_.clear();
|
||||
}
|
||||
|
||||
void UndoStack::UpdateActions()
|
||||
{
|
||||
undo_action_->setEnabled(CanUndo());
|
||||
redo_action_->setEnabled(CanRedo());
|
||||
|
||||
undo_action_->setText(QCoreApplication::translate("UndoStack", "Undo %1").arg(CanUndo() ? commands_.back()->name() : QString()));
|
||||
redo_action_->setText(QCoreApplication::translate("UndoStack", "Redo %1").arg(CanRedo() ? undone_commands_.front()->name() : QString()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+53
-3
@@ -21,20 +21,70 @@
|
||||
#ifndef UNDOSTACK_H
|
||||
#define UNDOSTACK_H
|
||||
|
||||
#include <QUndoStack>
|
||||
#include <QAction>
|
||||
|
||||
#include "common/define.h"
|
||||
#include "undo/undocommand.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class UndoStack : public QUndoStack {
|
||||
class UndoStack : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
UndoStack();
|
||||
|
||||
virtual ~UndoStack() override;
|
||||
|
||||
/**
|
||||
* @brief A wrapper for push() that either pushes if the command has children or deletes if not
|
||||
*
|
||||
* This function takes ownership of `command`, and may delete it so it should never be accessed after this call.
|
||||
*/
|
||||
void pushIfHasChildren(QUndoCommand* command);
|
||||
void pushIfHasChildren(MultiUndoCommand* command);
|
||||
|
||||
void push(UndoCommand* command);
|
||||
|
||||
void clear();
|
||||
|
||||
bool CanUndo() const
|
||||
{
|
||||
return !commands_.empty();
|
||||
}
|
||||
|
||||
bool CanRedo() const
|
||||
{
|
||||
return !undone_commands_.empty();
|
||||
}
|
||||
|
||||
void UpdateActions();
|
||||
|
||||
QAction* GetUndoAction()
|
||||
{
|
||||
return undo_action_;
|
||||
}
|
||||
|
||||
QAction* GetRedoAction()
|
||||
{
|
||||
return redo_action_;
|
||||
}
|
||||
|
||||
public slots:
|
||||
void undo();
|
||||
|
||||
void redo();
|
||||
|
||||
private:
|
||||
static const int kMaxUndoCommands;
|
||||
|
||||
std::list<UndoCommand*> commands_;
|
||||
|
||||
std::list<UndoCommand*> undone_commands_;
|
||||
|
||||
QAction* undo_action_;
|
||||
|
||||
QAction* redo_action_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -336,12 +336,12 @@ void CurveWidget::KeyframeTypeButtonTriggered(bool checked)
|
||||
// Ensure only the appropriate button is checked
|
||||
SetKeyframeButtonCheckedFromType(new_type);
|
||||
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
foreach (QGraphicsItem* item, selected) {
|
||||
KeyframeViewItem* key_item = static_cast<KeyframeViewItem*>(item);
|
||||
|
||||
new KeyframeSetTypeCommand(key_item->key(), new_type, command);
|
||||
command->add_child(new KeyframeSetTypeCommand(key_item->key(), new_type));
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
|
||||
@@ -59,13 +59,13 @@ void KeyframeViewBase::Clear()
|
||||
|
||||
void KeyframeViewBase::DeleteSelected()
|
||||
{
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
QMap<NodeKeyframe*, KeyframeViewItem*>::const_iterator i;
|
||||
|
||||
for (i=item_map_.constBegin(); i!=item_map_.constEnd(); i++) {
|
||||
if (i.value()->isSelected()) {
|
||||
new NodeParamRemoveKeyframeCommand(i.key(), command);
|
||||
command->add_child(new NodeParamRemoveKeyframeCommand(i.key()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,46 +307,42 @@ void KeyframeViewBase::mouseReleaseEvent(QMouseEvent *event)
|
||||
|
||||
if (dragging_) {
|
||||
if (dragging_bezier_point_) {
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
// Create undo command with the current bezier point and the old one
|
||||
new KeyframeSetBezierControlPoint(dragging_bezier_point_->key(),
|
||||
dragging_bezier_point_->mode(),
|
||||
dragging_bezier_point_->key()->bezier_control(dragging_bezier_point_->mode()),
|
||||
dragging_bezier_point_start_,
|
||||
command);
|
||||
command->add_child(new KeyframeSetBezierControlPoint(dragging_bezier_point_->key(),
|
||||
dragging_bezier_point_->mode(),
|
||||
dragging_bezier_point_->key()->bezier_control(dragging_bezier_point_->mode()),
|
||||
dragging_bezier_point_start_));
|
||||
|
||||
if (!(event->modifiers() & Qt::ControlModifier)) {
|
||||
auto opposing_type = NodeKeyframe::get_opposing_bezier_type(dragging_bezier_point_->mode());
|
||||
|
||||
new KeyframeSetBezierControlPoint(dragging_bezier_point_->key(),
|
||||
opposing_type,
|
||||
dragging_bezier_point_->key()->bezier_control(opposing_type),
|
||||
dragging_bezier_point_opposing_start_,
|
||||
command);
|
||||
command->add_child(new KeyframeSetBezierControlPoint(dragging_bezier_point_->key(),
|
||||
opposing_type,
|
||||
dragging_bezier_point_->key()->bezier_control(opposing_type),
|
||||
dragging_bezier_point_opposing_start_));
|
||||
}
|
||||
|
||||
dragging_bezier_point_ = nullptr;
|
||||
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
} else if (!selected_keys_.isEmpty()) {
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
foreach (const KeyframeItemAndTime& keypair, selected_keys_) {
|
||||
NodeKeyframe* item = keypair.key->key();
|
||||
|
||||
// Commit movement
|
||||
new NodeParamSetKeyframeTimeCommand(item,
|
||||
item->time(),
|
||||
keypair.time,
|
||||
command);
|
||||
command->add_child(new NodeParamSetKeyframeTimeCommand(item,
|
||||
item->time(),
|
||||
keypair.time));
|
||||
|
||||
// Commit value if we're setting a value
|
||||
if (IsYAxisEnabled()) {
|
||||
new NodeParamSetKeyframeValueCommand(item,
|
||||
item->value(),
|
||||
keypair.value,
|
||||
command);
|
||||
command->add_child(new NodeParamSetKeyframeValueCommand(item,
|
||||
item->value(),
|
||||
keypair.value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,11 +493,10 @@ void KeyframeViewBase::ShowContextMenu()
|
||||
new_type = NodeKeyframe::kLinear;
|
||||
}
|
||||
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
foreach (QGraphicsItem* item, items) {
|
||||
new KeyframeSetTypeCommand(static_cast<KeyframeViewItem*>(item)->key(),
|
||||
new_type,
|
||||
command);
|
||||
command->add_child(new KeyframeSetTypeCommand(static_cast<KeyframeViewItem*>(item)->key(),
|
||||
new_type));
|
||||
}
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
}
|
||||
|
||||
@@ -26,8 +26,7 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
KeyframeSetTypeCommand::KeyframeSetTypeCommand(NodeKeyframe* key, NodeKeyframe::Type type, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
KeyframeSetTypeCommand::KeyframeSetTypeCommand(NodeKeyframe* key, NodeKeyframe::Type type) :
|
||||
key_(key),
|
||||
old_type_(key->type()),
|
||||
new_type_(type)
|
||||
@@ -39,18 +38,17 @@ Project *KeyframeSetTypeCommand::GetRelevantProject() const
|
||||
return key_->parent()->parent()->parent()->project();
|
||||
}
|
||||
|
||||
void KeyframeSetTypeCommand::redo_internal()
|
||||
void KeyframeSetTypeCommand::redo()
|
||||
{
|
||||
key_->set_type(new_type_);
|
||||
}
|
||||
|
||||
void KeyframeSetTypeCommand::undo_internal()
|
||||
void KeyframeSetTypeCommand::undo()
|
||||
{
|
||||
key_->set_type(old_type_);
|
||||
}
|
||||
|
||||
KeyframeSetBezierControlPoint::KeyframeSetBezierControlPoint(NodeKeyframe* key, NodeKeyframe::BezierType mode, const QPointF& point, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
KeyframeSetBezierControlPoint::KeyframeSetBezierControlPoint(NodeKeyframe* key, NodeKeyframe::BezierType mode, const QPointF& point) :
|
||||
key_(key),
|
||||
mode_(mode),
|
||||
old_point_(key->bezier_control(mode_)),
|
||||
@@ -58,8 +56,7 @@ KeyframeSetBezierControlPoint::KeyframeSetBezierControlPoint(NodeKeyframe* key,
|
||||
{
|
||||
}
|
||||
|
||||
KeyframeSetBezierControlPoint::KeyframeSetBezierControlPoint(NodeKeyframe* key, NodeKeyframe::BezierType mode, const QPointF &new_point, const QPointF &old_point, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
KeyframeSetBezierControlPoint::KeyframeSetBezierControlPoint(NodeKeyframe* key, NodeKeyframe::BezierType mode, const QPointF &new_point, const QPointF &old_point) :
|
||||
key_(key),
|
||||
mode_(mode),
|
||||
old_point_(old_point),
|
||||
@@ -72,12 +69,12 @@ Project *KeyframeSetBezierControlPoint::GetRelevantProject() const
|
||||
return key_->parent()->parent()->parent()->project();
|
||||
}
|
||||
|
||||
void KeyframeSetBezierControlPoint::redo_internal()
|
||||
void KeyframeSetBezierControlPoint::redo()
|
||||
{
|
||||
key_->set_bezier_control(mode_, new_point_);
|
||||
}
|
||||
|
||||
void KeyframeSetBezierControlPoint::undo_internal()
|
||||
void KeyframeSetBezierControlPoint::undo()
|
||||
{
|
||||
key_->set_bezier_control(mode_, old_point_);
|
||||
}
|
||||
|
||||
@@ -28,13 +28,12 @@ namespace olive {
|
||||
|
||||
class KeyframeSetTypeCommand : public UndoCommand {
|
||||
public:
|
||||
KeyframeSetTypeCommand(NodeKeyframe* key, NodeKeyframe::Type type, QUndoCommand* parent = nullptr);
|
||||
KeyframeSetTypeCommand(NodeKeyframe* key, NodeKeyframe::Type type);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
NodeKeyframe* key_;
|
||||
@@ -47,14 +46,13 @@ private:
|
||||
|
||||
class KeyframeSetBezierControlPoint : public UndoCommand {
|
||||
public:
|
||||
KeyframeSetBezierControlPoint(NodeKeyframe* key, NodeKeyframe::BezierType mode, const QPointF& point, QUndoCommand* parent = nullptr);
|
||||
KeyframeSetBezierControlPoint(NodeKeyframe* key, NodeKeyframe::BezierType mode, const QPointF& new_point, const QPointF& old_point, QUndoCommand* parent = nullptr);
|
||||
KeyframeSetBezierControlPoint(NodeKeyframe* key, NodeKeyframe::BezierType mode, const QPointF& point);
|
||||
KeyframeSetBezierControlPoint(NodeKeyframe* key, NodeKeyframe::BezierType mode, const QPointF& new_point, const QPointF& old_point);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
NodeKeyframe* key_;
|
||||
|
||||
@@ -118,8 +118,8 @@ void MenuShared::AddItemsForNewMenu(Menu *m)
|
||||
|
||||
void MenuShared::AddItemsForEditMenu(Menu *m, bool for_clips)
|
||||
{
|
||||
m->addAction(Core::instance()->undo_stack()->createUndoAction(m));
|
||||
m->addAction(Core::instance()->undo_stack()->createRedoAction(m));
|
||||
m->addAction(Core::instance()->undo_stack()->GetUndoAction());
|
||||
m->addAction(Core::instance()->undo_stack()->GetRedoAction());
|
||||
|
||||
m->addSeparator();
|
||||
|
||||
|
||||
@@ -38,6 +38,13 @@ NodeParamViewArrayWidget::NodeParamViewArrayWidget(NodeInput *array, QWidget* pa
|
||||
UpdateCounter();
|
||||
}
|
||||
|
||||
void NodeParamViewArrayWidget::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
{
|
||||
QWidget::mouseDoubleClickEvent(event);
|
||||
|
||||
emit DoubleClicked();
|
||||
}
|
||||
|
||||
void NodeParamViewArrayWidget::UpdateCounter()
|
||||
{
|
||||
count_lbl_->setText(tr("%1 element(s)").arg(array_->ArraySize()));
|
||||
|
||||
@@ -56,6 +56,12 @@ class NodeParamViewArrayWidget : public QWidget
|
||||
public:
|
||||
NodeParamViewArrayWidget(NodeInput* array, QWidget* parent = nullptr);
|
||||
|
||||
signals:
|
||||
void DoubleClicked();
|
||||
|
||||
protected:
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent* event) override;
|
||||
|
||||
private:
|
||||
NodeInput* array_;
|
||||
|
||||
|
||||
@@ -258,15 +258,14 @@ void NodeParamViewItemBody::CreateWidgets(QGridLayout* layout, NodeInput *input,
|
||||
// Default to collapsed
|
||||
array_collapse_btn->setChecked(false);
|
||||
|
||||
// Add data
|
||||
array_collapse_btn->setProperty("input", Node::PtrToValue(input));
|
||||
|
||||
// Collapse button always goes into column 0
|
||||
layout->addWidget(array_collapse_btn, row, 0);
|
||||
|
||||
// Connect signal to show/hide array params when toggled
|
||||
connect(array_collapse_btn, &CollapseButton::toggled, this, &NodeParamViewItemBody::ArrayCollapseBtnPressed);
|
||||
|
||||
array_collapse_buttons_.insert(input, array_collapse_btn);
|
||||
|
||||
} else {
|
||||
|
||||
NodeParamViewArrayButton* insert_element_btn = new NodeParamViewArrayButton(NodeParamViewArrayButton::kAdd);
|
||||
@@ -286,6 +285,7 @@ void NodeParamViewItemBody::CreateWidgets(QGridLayout* layout, NodeInput *input,
|
||||
|
||||
// Create a widget/input bridge for this input
|
||||
ui_objects.widget_bridge = new NodeParamViewWidgetBridge(input, element, this);
|
||||
connect(ui_objects.widget_bridge, &NodeParamViewWidgetBridge::ArrayWidgetDoubleClicked, this, &NodeParamViewItemBody::ToggleArrayExpanded);
|
||||
|
||||
// 0 is for the array collapse button, 1 is for the main label, widgets start at 2
|
||||
const int widget_start = 2;
|
||||
@@ -372,7 +372,7 @@ void NodeParamViewItemBody::SignalAllKeyframes()
|
||||
|
||||
foreach (const NodeKeyframeTrack& track, input->GetKeyframeTracks(i.key().element)) {
|
||||
foreach (NodeKeyframe* key, track) {
|
||||
InputAddedKeyframeInternal(input, key);
|
||||
InputAddedKeyframeInternal(input, i.key().element, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -406,7 +406,7 @@ void NodeParamViewItemBody::InputKeyframeEnableChanged(bool e, int element)
|
||||
foreach (NodeKeyframe* key, track) {
|
||||
if (e) {
|
||||
// Add a keyframe item for each keyframe
|
||||
InputAddedKeyframeInternal(input, key);
|
||||
InputAddedKeyframeInternal(input, element, key);
|
||||
} else {
|
||||
// Remove each keyframe item
|
||||
emit KeyframeRemoved(key);
|
||||
@@ -420,13 +420,13 @@ void NodeParamViewItemBody::InputAddedKeyframe(NodeKeyframe* key)
|
||||
// Get NodeInput that emitted this signal
|
||||
NodeInput* input = static_cast<NodeInput*>(sender());
|
||||
|
||||
InputAddedKeyframeInternal(input, key);
|
||||
InputAddedKeyframeInternal(input, key->element(), key);
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::InputAddedKeyframeInternal(NodeInput *input, NodeKeyframe* keyframe)
|
||||
void NodeParamViewItemBody::InputAddedKeyframeInternal(NodeInput *input, int element, NodeKeyframe* keyframe)
|
||||
{
|
||||
// Find its row in the parameters
|
||||
QLabel* lbl = input_ui_map_.value(input).main_label;
|
||||
QLabel* lbl = input_ui_map_.value({input, element}).main_label;
|
||||
|
||||
// Find label's Y position
|
||||
QPoint lbl_center = lbl->rect().center();
|
||||
@@ -439,7 +439,7 @@ void NodeParamViewItemBody::InputAddedKeyframeInternal(NodeInput *input, NodeKey
|
||||
|
||||
void NodeParamViewItemBody::ArrayCollapseBtnPressed(bool checked)
|
||||
{
|
||||
NodeInput* input = Node::ValueToPtr<NodeInput>(sender()->property("input"));
|
||||
NodeInput* input = array_collapse_buttons_.key(static_cast<CollapseButton*>(sender()));
|
||||
|
||||
array_ui_.value(input).widget->setVisible(checked);
|
||||
}
|
||||
@@ -486,7 +486,7 @@ void NodeParamViewItemBody::ArrayAppendClicked()
|
||||
{
|
||||
for (auto it=array_ui_.cbegin(); it!=array_ui_.cend(); it++) {
|
||||
if (it.value().append_btn == sender()) {
|
||||
it.key()->ArrayAppend();
|
||||
it.key()->ArrayAppend(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -498,7 +498,7 @@ void NodeParamViewItemBody::ArrayInsertClicked()
|
||||
if (it.value().array_insert_btn == sender()) {
|
||||
// Found our input and element
|
||||
const Node::InputConnection& ic = it.key();
|
||||
ic.input->ArrayInsert(ic.element);
|
||||
ic.input->ArrayInsert(ic.element, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -510,12 +510,25 @@ void NodeParamViewItemBody::ArrayRemoveClicked()
|
||||
if (it.value().array_remove_btn == sender()) {
|
||||
// Found our input and element
|
||||
const Node::InputConnection& ic = it.key();
|
||||
ic.input->ArrayRemove(ic.element);
|
||||
ic.input->ArrayRemove(ic.element, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::ToggleArrayExpanded()
|
||||
{
|
||||
NodeParamViewWidgetBridge* bridge = static_cast<NodeParamViewWidgetBridge*>(sender());
|
||||
|
||||
for (auto it=input_ui_map_.cbegin(); it!=input_ui_map_.cend(); it++) {
|
||||
if (it.value().widget_bridge == bridge) {
|
||||
CollapseButton* b = array_collapse_buttons_.value(it.key().input);
|
||||
b->setChecked(!b->isChecked());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NodeParamViewItemBody::InputUI::InputUI() :
|
||||
main_label(nullptr),
|
||||
widget_bridge(nullptr),
|
||||
|
||||
@@ -97,7 +97,7 @@ private:
|
||||
|
||||
void UpdateUIForEdgeConnection(NodeInput* input, int element);
|
||||
|
||||
void InputAddedKeyframeInternal(NodeInput* input, NodeKeyframe* keyframe);
|
||||
void InputAddedKeyframeInternal(NodeInput* input, int element, NodeKeyframe* keyframe);
|
||||
|
||||
struct InputUI {
|
||||
InputUI();
|
||||
@@ -121,6 +121,8 @@ private:
|
||||
|
||||
QHash<NodeInput*, ArrayUI> array_ui_;
|
||||
|
||||
QHash<NodeInput*, CollapseButton*> array_collapse_buttons_;
|
||||
|
||||
/**
|
||||
* @brief The column to place the keyframe controls in
|
||||
*
|
||||
@@ -149,6 +151,8 @@ private slots:
|
||||
|
||||
void ArrayRemoveClicked();
|
||||
|
||||
void ToggleArrayExpanded();
|
||||
|
||||
};
|
||||
|
||||
class NodeParamViewItem : public QDockWidget
|
||||
|
||||
@@ -145,7 +145,7 @@ void NodeParamViewKeyframeControl::ToggleKeyframe(bool e)
|
||||
|
||||
QVector<NodeKeyframe*> keys = input_->GetKeyframesAtTime(node_time, element_);
|
||||
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
int nb_tracks = input_->GetNumberOfKeyframeTracks();
|
||||
|
||||
@@ -158,20 +158,19 @@ void NodeParamViewKeyframeControl::ToggleKeyframe(bool e)
|
||||
i,
|
||||
element_);
|
||||
|
||||
new NodeParamInsertKeyframeCommand(input_, key, command);
|
||||
command->add_child(new NodeParamInsertKeyframeCommand(input_, key));
|
||||
}
|
||||
} else if (!e && !keys.isEmpty()) {
|
||||
// Remove all keyframes at this time
|
||||
foreach (NodeKeyframe* key, keys) {
|
||||
new NodeParamRemoveKeyframeCommand(key, command);
|
||||
command->add_child(new NodeParamRemoveKeyframeCommand(key));
|
||||
|
||||
if (input_->GetKeyframeTracks(key->track()).size() == 1) {
|
||||
// If this was the last keyframe on this track, set the standard value to the value at this time too
|
||||
new NodeParamSetStandardValueCommand(input_,
|
||||
key->track(),
|
||||
element_,
|
||||
input_->GetValueAtTimeForTrack(node_time, key->track(), element_),
|
||||
command);
|
||||
command->add_child(new NodeParamSetStandardValueCommand(input_,
|
||||
key->track(),
|
||||
element_,
|
||||
input_->GetValueAtTimeForTrack(node_time, key->track(), element_)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -228,11 +227,11 @@ void NodeParamViewKeyframeControl::KeyframeEnableChanged(bool e)
|
||||
return;
|
||||
}
|
||||
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
if (e) {
|
||||
// Enable keyframing
|
||||
new NodeParamSetKeyframingCommand(input_, element_, true, command);
|
||||
command->add_child(new NodeParamSetKeyframingCommand(input_, element_, true));
|
||||
|
||||
// Create one keyframe across all tracks here
|
||||
const QVector<QVariant>& key_vals = input_->GetSplitStandardValue(element_);
|
||||
@@ -244,7 +243,7 @@ void NodeParamViewKeyframeControl::KeyframeEnableChanged(bool e)
|
||||
i,
|
||||
element_);
|
||||
|
||||
new NodeParamInsertKeyframeCommand(input_, key, command);
|
||||
command->add_child(new NodeParamInsertKeyframeCommand(input_, key));
|
||||
}
|
||||
} else {
|
||||
// Confirm the user wants to clear all keyframes
|
||||
@@ -259,17 +258,17 @@ void NodeParamViewKeyframeControl::KeyframeEnableChanged(bool e)
|
||||
// Delete all keyframes
|
||||
foreach (const NodeKeyframeTrack& track, input_->GetKeyframeTracks(element_)) {
|
||||
for (int i=track.size()-1;i>=0;i--) {
|
||||
new NodeParamRemoveKeyframeCommand(track.at(i), command);
|
||||
command->add_child(new NodeParamRemoveKeyframeCommand(track.at(i)));
|
||||
}
|
||||
}
|
||||
|
||||
// Update standard value
|
||||
for (int i=0;i<stored_vals.size();i++) {
|
||||
new NodeParamSetStandardValueCommand(input_, i, element_, stored_vals.at(i), command);
|
||||
command->add_child(new NodeParamSetStandardValueCommand(input_, i, element_, stored_vals.at(i)));
|
||||
}
|
||||
|
||||
// Disable keyframing
|
||||
new NodeParamSetKeyframingCommand(input_, element_, false, command);
|
||||
command->add_child(new NodeParamSetKeyframingCommand(input_, element_, false));
|
||||
|
||||
} else {
|
||||
// Disable action has effectively been ignored
|
||||
|
||||
@@ -25,8 +25,7 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
NodeParamSetKeyframingCommand::NodeParamSetKeyframingCommand(NodeInput *input, int element, bool setting, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
NodeParamSetKeyframingCommand::NodeParamSetKeyframingCommand(NodeInput *input, int element, bool setting) :
|
||||
input_(input),
|
||||
setting_(setting),
|
||||
element_(element)
|
||||
@@ -39,26 +38,24 @@ Project *NodeParamSetKeyframingCommand::GetRelevantProject() const
|
||||
return input_->parent()->parent()->project();
|
||||
}
|
||||
|
||||
void NodeParamSetKeyframingCommand::redo_internal()
|
||||
void NodeParamSetKeyframingCommand::redo()
|
||||
{
|
||||
input_->SetIsKeyframing(setting_, element_);
|
||||
}
|
||||
|
||||
void NodeParamSetKeyframingCommand::undo_internal()
|
||||
void NodeParamSetKeyframingCommand::undo()
|
||||
{
|
||||
input_->SetIsKeyframing(!setting_, element_);
|
||||
}
|
||||
|
||||
NodeParamSetKeyframeValueCommand::NodeParamSetKeyframeValueCommand(NodeKeyframe* key, const QVariant& value, QUndoCommand* parent) :
|
||||
UndoCommand(parent),
|
||||
NodeParamSetKeyframeValueCommand::NodeParamSetKeyframeValueCommand(NodeKeyframe* key, const QVariant& value) :
|
||||
key_(key),
|
||||
old_value_(key_->value()),
|
||||
new_value_(value)
|
||||
{
|
||||
}
|
||||
|
||||
NodeParamSetKeyframeValueCommand::NodeParamSetKeyframeValueCommand(NodeKeyframe* key, const QVariant &new_value, const QVariant &old_value, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
NodeParamSetKeyframeValueCommand::NodeParamSetKeyframeValueCommand(NodeKeyframe* key, const QVariant &new_value, const QVariant &old_value) :
|
||||
key_(key),
|
||||
old_value_(old_value),
|
||||
new_value_(new_value)
|
||||
@@ -71,18 +68,17 @@ Project *NodeParamSetKeyframeValueCommand::GetRelevantProject() const
|
||||
return key_->parent()->parent()->parent()->project();
|
||||
}
|
||||
|
||||
void NodeParamSetKeyframeValueCommand::redo_internal()
|
||||
void NodeParamSetKeyframeValueCommand::redo()
|
||||
{
|
||||
key_->set_value(new_value_);
|
||||
}
|
||||
|
||||
void NodeParamSetKeyframeValueCommand::undo_internal()
|
||||
void NodeParamSetKeyframeValueCommand::undo()
|
||||
{
|
||||
key_->set_value(old_value_);
|
||||
}
|
||||
|
||||
NodeParamInsertKeyframeCommand::NodeParamInsertKeyframeCommand(NodeInput *input, NodeKeyframe* keyframe, QUndoCommand* parent) :
|
||||
UndoCommand(parent),
|
||||
NodeParamInsertKeyframeCommand::NodeParamInsertKeyframeCommand(NodeInput *input, NodeKeyframe* keyframe) :
|
||||
input_(input),
|
||||
keyframe_(keyframe)
|
||||
{
|
||||
@@ -94,18 +90,17 @@ Project *NodeParamInsertKeyframeCommand::GetRelevantProject() const
|
||||
return input_->parent()->parent()->project();
|
||||
}
|
||||
|
||||
void NodeParamInsertKeyframeCommand::redo_internal()
|
||||
void NodeParamInsertKeyframeCommand::redo()
|
||||
{
|
||||
keyframe_->setParent(input_);
|
||||
}
|
||||
|
||||
void NodeParamInsertKeyframeCommand::undo_internal()
|
||||
void NodeParamInsertKeyframeCommand::undo()
|
||||
{
|
||||
keyframe_->setParent(&memory_manager_);
|
||||
}
|
||||
|
||||
NodeParamRemoveKeyframeCommand::NodeParamRemoveKeyframeCommand(NodeKeyframe* keyframe, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
NodeParamRemoveKeyframeCommand::NodeParamRemoveKeyframeCommand(NodeKeyframe* keyframe) :
|
||||
input_(keyframe->parent()),
|
||||
keyframe_(keyframe)
|
||||
{
|
||||
@@ -116,27 +111,25 @@ Project *NodeParamRemoveKeyframeCommand::GetRelevantProject() const
|
||||
return input_->parent()->parent()->project();
|
||||
}
|
||||
|
||||
void NodeParamRemoveKeyframeCommand::redo_internal()
|
||||
void NodeParamRemoveKeyframeCommand::redo()
|
||||
{
|
||||
// Removes from input
|
||||
keyframe_->setParent(&memory_manager_);
|
||||
}
|
||||
|
||||
void NodeParamRemoveKeyframeCommand::undo_internal()
|
||||
void NodeParamRemoveKeyframeCommand::undo()
|
||||
{
|
||||
keyframe_->setParent(input_);
|
||||
}
|
||||
|
||||
NodeParamSetKeyframeTimeCommand::NodeParamSetKeyframeTimeCommand(NodeKeyframe* key, const rational &time, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
NodeParamSetKeyframeTimeCommand::NodeParamSetKeyframeTimeCommand(NodeKeyframe* key, const rational &time) :
|
||||
key_(key),
|
||||
old_time_(key->time()),
|
||||
new_time_(time)
|
||||
{
|
||||
}
|
||||
|
||||
NodeParamSetKeyframeTimeCommand::NodeParamSetKeyframeTimeCommand(NodeKeyframe* key, const rational &new_time, const rational &old_time, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
NodeParamSetKeyframeTimeCommand::NodeParamSetKeyframeTimeCommand(NodeKeyframe* key, const rational &new_time, const rational &old_time) :
|
||||
key_(key),
|
||||
old_time_(old_time),
|
||||
new_time_(new_time)
|
||||
@@ -148,18 +141,17 @@ Project *NodeParamSetKeyframeTimeCommand::GetRelevantProject() const
|
||||
return key_->parent()->parent()->parent()->project();
|
||||
}
|
||||
|
||||
void NodeParamSetKeyframeTimeCommand::redo_internal()
|
||||
void NodeParamSetKeyframeTimeCommand::redo()
|
||||
{
|
||||
key_->set_time(new_time_);
|
||||
}
|
||||
|
||||
void NodeParamSetKeyframeTimeCommand::undo_internal()
|
||||
void NodeParamSetKeyframeTimeCommand::undo()
|
||||
{
|
||||
key_->set_time(old_time_);
|
||||
}
|
||||
|
||||
NodeParamSetStandardValueCommand::NodeParamSetStandardValueCommand(NodeInput *input, int track, int element, const QVariant &value, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
NodeParamSetStandardValueCommand::NodeParamSetStandardValueCommand(NodeInput *input, int track, int element, const QVariant &value) :
|
||||
input_(input),
|
||||
element_(element),
|
||||
track_(track),
|
||||
@@ -168,8 +160,7 @@ NodeParamSetStandardValueCommand::NodeParamSetStandardValueCommand(NodeInput *in
|
||||
{
|
||||
}
|
||||
|
||||
NodeParamSetStandardValueCommand::NodeParamSetStandardValueCommand(NodeInput *input, int track, int element, const QVariant &new_value, const QVariant &old_value, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
NodeParamSetStandardValueCommand::NodeParamSetStandardValueCommand(NodeInput *input, int track, int element, const QVariant &new_value, const QVariant &old_value) :
|
||||
input_(input),
|
||||
element_(element),
|
||||
track_(track),
|
||||
@@ -183,14 +174,19 @@ Project *NodeParamSetStandardValueCommand::GetRelevantProject() const
|
||||
return input_->parent()->parent()->project();
|
||||
}
|
||||
|
||||
void NodeParamSetStandardValueCommand::redo_internal()
|
||||
void NodeParamSetStandardValueCommand::redo()
|
||||
{
|
||||
input_->SetStandardValueOnTrack(new_value_, track_, element_);
|
||||
}
|
||||
|
||||
void NodeParamSetStandardValueCommand::undo_internal()
|
||||
void NodeParamSetStandardValueCommand::undo()
|
||||
{
|
||||
input_->SetStandardValueOnTrack(old_value_, track_, element_);
|
||||
}
|
||||
|
||||
Project *NodeParamArrayInsertCommand::GetRelevantProject() const
|
||||
{
|
||||
return input_->parent()->parent()->project();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,15 +26,15 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeParamSetKeyframingCommand : public UndoCommand {
|
||||
class NodeParamSetKeyframingCommand : public UndoCommand
|
||||
{
|
||||
public:
|
||||
NodeParamSetKeyframingCommand(NodeInput* input, int element, bool setting, QUndoCommand* parent = nullptr);
|
||||
NodeParamSetKeyframingCommand(NodeInput* input, int element, bool setting);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
NodeInput* input_;
|
||||
@@ -43,15 +43,15 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class NodeParamInsertKeyframeCommand : public UndoCommand {
|
||||
class NodeParamInsertKeyframeCommand : public UndoCommand
|
||||
{
|
||||
public:
|
||||
NodeParamInsertKeyframeCommand(NodeInput* input, NodeKeyframe* keyframe, QUndoCommand *parent = nullptr);
|
||||
NodeParamInsertKeyframeCommand(NodeInput* input, NodeKeyframe* keyframe);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
NodeInput* input_;
|
||||
@@ -62,15 +62,15 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class NodeParamRemoveKeyframeCommand : public UndoCommand {
|
||||
class NodeParamRemoveKeyframeCommand : public UndoCommand
|
||||
{
|
||||
public:
|
||||
NodeParamRemoveKeyframeCommand(NodeKeyframe* keyframe, QUndoCommand *parent = nullptr);
|
||||
NodeParamRemoveKeyframeCommand(NodeKeyframe* keyframe);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
NodeInput* input_;
|
||||
@@ -81,16 +81,16 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class NodeParamSetKeyframeTimeCommand : public UndoCommand {
|
||||
class NodeParamSetKeyframeTimeCommand : public UndoCommand
|
||||
{
|
||||
public:
|
||||
NodeParamSetKeyframeTimeCommand(NodeKeyframe* key, const rational& time, QUndoCommand* parent = nullptr);
|
||||
NodeParamSetKeyframeTimeCommand(NodeKeyframe* key, const rational& new_time, const rational& old_time, QUndoCommand* parent = nullptr);
|
||||
NodeParamSetKeyframeTimeCommand(NodeKeyframe* key, const rational& time);
|
||||
NodeParamSetKeyframeTimeCommand(NodeKeyframe* key, const rational& new_time, const rational& old_time);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
NodeKeyframe* key_;
|
||||
@@ -100,16 +100,16 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class NodeParamSetKeyframeValueCommand : public UndoCommand {
|
||||
class NodeParamSetKeyframeValueCommand : public UndoCommand
|
||||
{
|
||||
public:
|
||||
NodeParamSetKeyframeValueCommand(NodeKeyframe* key, const QVariant& value, QUndoCommand* parent = nullptr);
|
||||
NodeParamSetKeyframeValueCommand(NodeKeyframe* key, const QVariant& new_value, const QVariant& old_value, QUndoCommand* parent = nullptr);
|
||||
NodeParamSetKeyframeValueCommand(NodeKeyframe* key, const QVariant& value);
|
||||
NodeParamSetKeyframeValueCommand(NodeKeyframe* key, const QVariant& new_value, const QVariant& old_value);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
NodeKeyframe* key_;
|
||||
@@ -119,16 +119,16 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class NodeParamSetStandardValueCommand : public UndoCommand {
|
||||
class NodeParamSetStandardValueCommand : public UndoCommand
|
||||
{
|
||||
public:
|
||||
NodeParamSetStandardValueCommand(NodeInput* input, int track, int element, const QVariant& value, QUndoCommand* parent = nullptr);
|
||||
NodeParamSetStandardValueCommand(NodeInput* input, int track, int element, const QVariant& new_value, const QVariant& old_value, QUndoCommand* parent = nullptr);
|
||||
NodeParamSetStandardValueCommand(NodeInput* input, int track, int element, const QVariant& value);
|
||||
NodeParamSetStandardValueCommand(NodeInput* input, int track, int element, const QVariant& new_value, const QVariant& old_value);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
NodeInput* input_;
|
||||
@@ -140,6 +140,33 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class NodeParamArrayInsertCommand : public UndoCommand
|
||||
{
|
||||
public:
|
||||
NodeParamArrayInsertCommand(NodeInput* input, int index) :
|
||||
input_(input),
|
||||
index_(index)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
virtual void redo() override
|
||||
{
|
||||
input_->ArrayInsert(index_);
|
||||
}
|
||||
|
||||
virtual void undo() override
|
||||
{
|
||||
input_->ArrayRemove(index_);
|
||||
}
|
||||
|
||||
private:
|
||||
NodeInput* input_;
|
||||
int index_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // NODEPARAMVIEWUNDO_H
|
||||
|
||||
@@ -70,6 +70,7 @@ void NodeParamViewWidgetBridge::CreateWidgets()
|
||||
if (input_->IsArray() && element_ == -1) {
|
||||
|
||||
NodeParamViewArrayWidget* w = new NodeParamViewArrayWidget(input_);
|
||||
connect(w, &NodeParamViewArrayWidget::DoubleClicked, this, &NodeParamViewWidgetBridge::ArrayWidgetDoubleClicked);
|
||||
widgets_.append(w);
|
||||
|
||||
} else {
|
||||
@@ -190,14 +191,14 @@ void NodeParamViewWidgetBridge::CreateWidgets()
|
||||
|
||||
void NodeParamViewWidgetBridge::SetInputValue(const QVariant &value, int track)
|
||||
{
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
SetInputValueInternal(value, track, command);
|
||||
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
}
|
||||
|
||||
void NodeParamViewWidgetBridge::SetInputValueInternal(const QVariant &value, int track, QUndoCommand *command)
|
||||
void NodeParamViewWidgetBridge::SetInputValueInternal(const QVariant &value, int track, MultiUndoCommand *command)
|
||||
{
|
||||
rational node_time = GetCurrentTimeAsNodeTime();
|
||||
|
||||
@@ -205,7 +206,7 @@ void NodeParamViewWidgetBridge::SetInputValueInternal(const QVariant &value, int
|
||||
NodeKeyframe* existing_key = input_->GetKeyframeAtTimeOnTrack(node_time, track, element_);
|
||||
|
||||
if (existing_key) {
|
||||
new NodeParamSetKeyframeValueCommand(existing_key, value, command);
|
||||
command->add_child(new NodeParamSetKeyframeValueCommand(existing_key, value));
|
||||
} else {
|
||||
// No existing key, create a new one
|
||||
NodeKeyframe* new_key = new NodeKeyframe(node_time,
|
||||
@@ -214,10 +215,10 @@ void NodeParamViewWidgetBridge::SetInputValueInternal(const QVariant &value, int
|
||||
track,
|
||||
element_);
|
||||
|
||||
new NodeParamInsertKeyframeCommand(input_, new_key, command);
|
||||
command->add_child(new NodeParamInsertKeyframeCommand(input_, new_key));
|
||||
}
|
||||
} else {
|
||||
new NodeParamSetStandardValueCommand(input_, track, element_, value, command);
|
||||
command->add_child(new NodeParamSetStandardValueCommand(input_, track, element_, value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,13 +232,11 @@ void NodeParamViewWidgetBridge::ProcessSlider(SliderBase *slider, const QVariant
|
||||
|
||||
// While we're dragging, we block the input's normal signalling and create our own
|
||||
if (!dragger_.IsStarted()) {
|
||||
dragger_.Start(input_, node_time, slider_track);
|
||||
dragger_.Start(input_, node_time, slider_track, element_);
|
||||
}
|
||||
|
||||
dragger_.Drag(value);
|
||||
|
||||
//input_->parentNode()->InvalidateVisible(input_, input_);
|
||||
|
||||
} else if (dragger_.IsStarted()) {
|
||||
|
||||
// We were dragging and just stopped
|
||||
@@ -245,8 +244,10 @@ void NodeParamViewWidgetBridge::ProcessSlider(SliderBase *slider, const QVariant
|
||||
dragger_.End();
|
||||
|
||||
} else {
|
||||
|
||||
// No drag was involved, we can just push the value
|
||||
SetInputValue(value, slider_track);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,7 +322,7 @@ void NodeParamViewWidgetBridge::WidgetCallback()
|
||||
// Sender is a ColorButton
|
||||
ManagedColor c = static_cast<ColorButton*>(sender())->GetColor();
|
||||
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
SetInputValueInternal(c.red(), 0, command);
|
||||
SetInputValueInternal(c.green(), 1, command);
|
||||
@@ -394,7 +395,7 @@ void NodeParamViewWidgetBridge::CreateSliders(int count)
|
||||
|
||||
void NodeParamViewWidgetBridge::UpdateWidgetValues()
|
||||
{
|
||||
if (input_->IsArray()) {
|
||||
if (input_->IsArray() && element_ == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -428,7 +429,7 @@ void NodeParamViewWidgetBridge::UpdateWidgetValues()
|
||||
}
|
||||
case NodeValue::kVec2:
|
||||
{
|
||||
QVector2D vec2 = input_->GetValueAtTime(node_time, -1).value<QVector2D>();
|
||||
QVector2D vec2 = input_->GetValueAtTime(node_time, element_).value<QVector2D>();
|
||||
QVector2D offset = input_->property("offset").value<QVector2D>();
|
||||
|
||||
static_cast<FloatSlider*>(widgets_.at(0))->SetValue(static_cast<double>(vec2.x() + offset.x()));
|
||||
@@ -510,9 +511,11 @@ rational NodeParamViewWidgetBridge::GetCurrentTimeAsNodeTime() const
|
||||
return GetAdjustedTime(GetTimeTarget(), input_->parent(), time_, true);
|
||||
}
|
||||
|
||||
void NodeParamViewWidgetBridge::InputValueChanged(const TimeRange &range)
|
||||
void NodeParamViewWidgetBridge::InputValueChanged(const TimeRange &range, int element)
|
||||
{
|
||||
if (!dragger_.IsStarted() && range.in() <= time_ && range.out() >= time_) {
|
||||
if (element == element_
|
||||
&& !dragger_.IsStarted()
|
||||
&& range.in() <= time_ && range.out() >= time_) {
|
||||
// We'll need to update the widgets because the values have changed on our current time
|
||||
UpdateWidgetValues();
|
||||
}
|
||||
|
||||
@@ -47,12 +47,15 @@ public:
|
||||
|
||||
const QList<QWidget*>& widgets() const;
|
||||
|
||||
signals:
|
||||
void ArrayWidgetDoubleClicked();
|
||||
|
||||
private:
|
||||
void CreateWidgets();
|
||||
|
||||
void SetInputValue(const QVariant& value, int track);
|
||||
|
||||
void SetInputValueInternal(const QVariant& value, int track, QUndoCommand* command);
|
||||
void SetInputValueInternal(const QVariant& value, int track, MultiUndoCommand *command);
|
||||
|
||||
void ProcessSlider(SliderBase* slider, const QVariant& value);
|
||||
|
||||
@@ -77,7 +80,7 @@ private:
|
||||
private slots:
|
||||
void WidgetCallback();
|
||||
|
||||
void InputValueChanged(const TimeRange& range);
|
||||
void InputValueChanged(const TimeRange& range, int element);
|
||||
|
||||
void PropertyChanged(const QString& key, const QVariant& value);
|
||||
|
||||
|
||||
@@ -118,13 +118,13 @@ void NodeView::DeleteSelected()
|
||||
return;
|
||||
}
|
||||
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
{
|
||||
QVector<NodeViewEdge *> selected_edges = scene_.GetSelectedEdges();
|
||||
|
||||
foreach (NodeViewEdge* edge, selected_edges) {
|
||||
new NodeEdgeRemoveCommand(edge->output(), edge->input(), edge->element(), command);
|
||||
command->add_child(new NodeEdgeRemoveCommand(edge->output(), edge->input(), edge->element()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ void NodeView::DeleteSelected()
|
||||
|
||||
if (!selected_nodes.isEmpty()) {
|
||||
foreach (Node* node, selected_nodes) {
|
||||
new NodeRemoveAndDisconnectCommand(node, command);
|
||||
command->add_child(new NodeRemoveAndDisconnectCommand(node));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -292,7 +292,7 @@ void NodeView::Paste()
|
||||
return;
|
||||
}
|
||||
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
QVector<Node*> pasted_nodes = PasteNodesFromClipboard(graph_, command);
|
||||
|
||||
@@ -315,7 +315,7 @@ void NodeView::Duplicate()
|
||||
return;
|
||||
}
|
||||
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
QVector<Node*> duplicated_nodes = Node::CopyDependencyGraph(selected, command);
|
||||
|
||||
@@ -536,14 +536,14 @@ void NodeView::mouseReleaseEvent(QMouseEvent *event)
|
||||
|
||||
if (drop_edge_) {
|
||||
// We have everything we need to place the node in between
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
// Remove old edge
|
||||
new NodeEdgeRemoveCommand(drop_edge_->output(), drop_edge_->input(), drop_edge_->element(), command);
|
||||
command->add_child(new NodeEdgeRemoveCommand(drop_edge_->output(), drop_edge_->input(), drop_edge_->element()));
|
||||
|
||||
// Place new edges
|
||||
new NodeEdgeAddCommand(drop_edge_->output(), drop_input_, -1, command);
|
||||
new NodeEdgeAddCommand(dropping_node, drop_edge_->input(), drop_edge_->element(), command);
|
||||
command->add_child(new NodeEdgeAddCommand(drop_edge_->output(), drop_input_, -1));
|
||||
command->add_child(new NodeEdgeAddCommand(dropping_node, drop_edge_->input(), drop_edge_->element()));
|
||||
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <QFontMetrics>
|
||||
#include <QGraphicsRectItem>
|
||||
#include <QLinearGradient>
|
||||
#include <QUndoCommand>
|
||||
#include <QWidget>
|
||||
|
||||
#include "node/node.h"
|
||||
|
||||
@@ -25,22 +25,41 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
NodeEdgeAddCommand::NodeEdgeAddCommand(Node *output, NodeInput *input, int element, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
NodeEdgeAddCommand::NodeEdgeAddCommand(Node *output, NodeInput *input, int element) :
|
||||
output_(output),
|
||||
input_(input),
|
||||
element_(element)
|
||||
element_(element),
|
||||
remove_command_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void NodeEdgeAddCommand::redo_internal()
|
||||
NodeEdgeAddCommand::~NodeEdgeAddCommand()
|
||||
{
|
||||
delete remove_command_;
|
||||
}
|
||||
|
||||
void NodeEdgeAddCommand::redo()
|
||||
{
|
||||
if (input_->IsConnected(element_)) {
|
||||
if (!remove_command_) {
|
||||
remove_command_ = new NodeEdgeRemoveCommand(input_->GetConnectedNode(element_),
|
||||
input_,
|
||||
element_);
|
||||
}
|
||||
|
||||
remove_command_->redo();
|
||||
}
|
||||
|
||||
Node::ConnectEdge(output_, input_, element_);
|
||||
}
|
||||
|
||||
void NodeEdgeAddCommand::undo_internal()
|
||||
void NodeEdgeAddCommand::undo()
|
||||
{
|
||||
Node::DisconnectEdge(output_, input_, element_);
|
||||
|
||||
if (remove_command_) {
|
||||
remove_command_->undo();
|
||||
}
|
||||
}
|
||||
|
||||
Project *NodeEdgeAddCommand::GetRelevantProject() const
|
||||
@@ -48,20 +67,19 @@ Project *NodeEdgeAddCommand::GetRelevantProject() const
|
||||
return output_->parent()->project();
|
||||
}
|
||||
|
||||
NodeEdgeRemoveCommand::NodeEdgeRemoveCommand(Node *output, NodeInput *input, int element, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
NodeEdgeRemoveCommand::NodeEdgeRemoveCommand(Node *output, NodeInput *input, int element) :
|
||||
output_(output),
|
||||
input_(input),
|
||||
element_(element)
|
||||
{
|
||||
}
|
||||
|
||||
void NodeEdgeRemoveCommand::redo_internal()
|
||||
void NodeEdgeRemoveCommand::redo()
|
||||
{
|
||||
Node::DisconnectEdge(output_, input_, element_);
|
||||
}
|
||||
|
||||
void NodeEdgeRemoveCommand::undo_internal()
|
||||
void NodeEdgeRemoveCommand::undo()
|
||||
{
|
||||
Node::ConnectEdge(output_, input_, element_);
|
||||
}
|
||||
@@ -71,8 +89,7 @@ Project *NodeEdgeRemoveCommand::GetRelevantProject() const
|
||||
return output_->parent()->project();
|
||||
}
|
||||
|
||||
NodeAddCommand::NodeAddCommand(NodeGraph *graph, Node *node, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
NodeAddCommand::NodeAddCommand(NodeGraph *graph, Node *node) :
|
||||
graph_(graph),
|
||||
node_(node)
|
||||
{
|
||||
@@ -80,12 +97,12 @@ NodeAddCommand::NodeAddCommand(NodeGraph *graph, Node *node, QUndoCommand *paren
|
||||
node_->setParent(&memory_manager_);
|
||||
}
|
||||
|
||||
void NodeAddCommand::redo_internal()
|
||||
void NodeAddCommand::redo()
|
||||
{
|
||||
node_->setParent(graph_);
|
||||
}
|
||||
|
||||
void NodeAddCommand::undo_internal()
|
||||
void NodeAddCommand::undo()
|
||||
{
|
||||
node_->setParent(&memory_manager_);
|
||||
}
|
||||
@@ -95,8 +112,7 @@ Project *NodeAddCommand::GetRelevantProject() const
|
||||
return graph_->project();
|
||||
}
|
||||
|
||||
NodeCopyInputsCommand::NodeCopyInputsCommand(Node *src, Node *dest, bool include_connections, QUndoCommand *parent) :
|
||||
QUndoCommand(parent),
|
||||
NodeCopyInputsCommand::NodeCopyInputsCommand(Node *src, Node *dest, bool include_connections) :
|
||||
src_(src),
|
||||
dest_(dest),
|
||||
include_connections_(include_connections)
|
||||
@@ -110,21 +126,21 @@ void NodeCopyInputsCommand::redo()
|
||||
|
||||
void NodeRemoveAndDisconnectCommand::prep()
|
||||
{
|
||||
command_ = new QUndoCommand();
|
||||
command_ = new MultiUndoCommand();
|
||||
|
||||
// If this is a block, remove all links
|
||||
if (node_->HasLinks()) {
|
||||
new NodeUnlinkAllCommand(node_, command_);
|
||||
command_->add_child(new NodeUnlinkAllCommand(node_));
|
||||
}
|
||||
|
||||
// Disconnect everything
|
||||
foreach (const Node::InputConnection& conn, node_->edges()) {
|
||||
new NodeEdgeRemoveCommand(node_, conn.input, conn.element, command_);
|
||||
command_->add_child(new NodeEdgeRemoveCommand(node_, conn.input, conn.element));
|
||||
}
|
||||
|
||||
foreach (NodeInput* input, node_->inputs()) {
|
||||
for (auto it=input->edges().cbegin(); it!=input->edges().cend(); it++) {
|
||||
new NodeEdgeRemoveCommand(it->second, input, it->first, command_);
|
||||
command_->add_child(new NodeEdgeRemoveCommand(it->second, input, it->first));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
#ifndef NODEVIEWUNDO_H
|
||||
#define NODEVIEWUNDO_H
|
||||
|
||||
#include <QUndoCommand>
|
||||
|
||||
#include "node/graph.h"
|
||||
#include "node/node.h"
|
||||
#include "undo/undocommand.h"
|
||||
@@ -30,19 +28,18 @@
|
||||
namespace olive {
|
||||
|
||||
/**
|
||||
* @brief An undoable command for connecting two NodeParams together
|
||||
* @brief An undoable command for disconnecting two NodeParams
|
||||
*
|
||||
* Can be considered a QUndoCommand wrapper for NodeParam::ConnectEdge()/
|
||||
* Can be considered a UndoCommand wrapper for NodeParam::DisonnectEdge()/
|
||||
*/
|
||||
class NodeEdgeAddCommand : public UndoCommand {
|
||||
class NodeEdgeRemoveCommand : public UndoCommand {
|
||||
public:
|
||||
NodeEdgeAddCommand(Node* output, NodeInput* input, int element, QUndoCommand* parent = nullptr);
|
||||
NodeEdgeRemoveCommand(Node* output, NodeInput* input, int element);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
Node* output_;
|
||||
@@ -52,36 +49,38 @@ private:
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An undoable command for disconnecting two NodeParams
|
||||
* @brief An undoable command for connecting two NodeParams together
|
||||
*
|
||||
* Can be considered a QUndoCommand wrapper for NodeParam::DisonnectEdge()/
|
||||
* Can be considered a UndoCommand wrapper for NodeParam::ConnectEdge()/
|
||||
*/
|
||||
class NodeEdgeRemoveCommand : public UndoCommand {
|
||||
class NodeEdgeAddCommand : public UndoCommand {
|
||||
public:
|
||||
NodeEdgeRemoveCommand(Node* output, NodeInput* input, int element, QUndoCommand* parent = nullptr);
|
||||
NodeEdgeAddCommand(Node* output, NodeInput* input, int element);
|
||||
|
||||
virtual ~NodeEdgeAddCommand() override;
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
Node* output_;
|
||||
NodeInput* input_;
|
||||
int element_;
|
||||
|
||||
NodeEdgeRemoveCommand* remove_command_;
|
||||
|
||||
};
|
||||
|
||||
class NodeAddCommand : public UndoCommand {
|
||||
public:
|
||||
NodeAddCommand(NodeGraph* graph, Node* node, QUndoCommand* parent = nullptr);
|
||||
NodeAddCommand(NodeGraph* graph, Node* node);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
QObject memory_manager_;
|
||||
@@ -92,8 +91,7 @@ private:
|
||||
|
||||
class NodeRemoveAndDisconnectCommand : public UndoCommand {
|
||||
public:
|
||||
NodeRemoveAndDisconnectCommand(Node* node, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
NodeRemoveAndDisconnectCommand(Node* node) :
|
||||
node_(node),
|
||||
graph_(nullptr),
|
||||
command_(nullptr),
|
||||
@@ -115,8 +113,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
if (!prepped_) {
|
||||
prep();
|
||||
@@ -129,7 +126,7 @@ protected:
|
||||
node_->setParent(&memory_manager_);
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
node_->setParent(graph_);
|
||||
graph_ = nullptr;
|
||||
@@ -145,7 +142,7 @@ private:
|
||||
Node* node_;
|
||||
NodeGraph* graph_;
|
||||
|
||||
QUndoCommand* command_;
|
||||
MultiUndoCommand* command_;
|
||||
|
||||
bool prepped_;
|
||||
|
||||
@@ -153,8 +150,7 @@ private:
|
||||
|
||||
class NodeRemoveWithExclusiveDependenciesAndDisconnect : public UndoCommand {
|
||||
public:
|
||||
NodeRemoveWithExclusiveDependenciesAndDisconnect(Node* node, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
NodeRemoveWithExclusiveDependenciesAndDisconnect(Node* node) :
|
||||
node_(node),
|
||||
command_(nullptr),
|
||||
prepped_(false)
|
||||
@@ -175,8 +171,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
if (!prepped_) {
|
||||
prep();
|
||||
@@ -186,7 +181,7 @@ protected:
|
||||
command_->redo();
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
command_->undo();
|
||||
}
|
||||
@@ -194,33 +189,35 @@ protected:
|
||||
private:
|
||||
void prep()
|
||||
{
|
||||
command_ = new QUndoCommand();
|
||||
command_ = new MultiUndoCommand();
|
||||
|
||||
new NodeRemoveAndDisconnectCommand(node_, command_);
|
||||
command_->add_child(new NodeRemoveAndDisconnectCommand(node_));
|
||||
|
||||
// Remove exclusive dependencies
|
||||
QVector<Node*> deps = node_->GetExclusiveDependencies();
|
||||
foreach (Node* d, deps) {
|
||||
new NodeRemoveAndDisconnectCommand(d, command_);
|
||||
command_->add_child(new NodeRemoveAndDisconnectCommand(d));
|
||||
}
|
||||
}
|
||||
|
||||
Node* node_;
|
||||
QUndoCommand* command_;
|
||||
MultiUndoCommand* command_;
|
||||
bool prepped_;
|
||||
|
||||
};
|
||||
|
||||
class NodeCopyInputsCommand : public QUndoCommand {
|
||||
class NodeCopyInputsCommand : public UndoCommand {
|
||||
public:
|
||||
NodeCopyInputsCommand(Node* src,
|
||||
Node* dest,
|
||||
bool include_connections,
|
||||
QUndoCommand* parent = nullptr);
|
||||
bool include_connections);
|
||||
|
||||
protected:
|
||||
virtual void redo() override;
|
||||
|
||||
virtual void undo() override {}
|
||||
|
||||
virtual Project* GetRelevantProject() const override {return nullptr;}
|
||||
|
||||
private:
|
||||
Node* src_;
|
||||
|
||||
@@ -232,8 +229,7 @@ private:
|
||||
|
||||
class NodeLinkCommand : public UndoCommand {
|
||||
public:
|
||||
NodeLinkCommand(Node* a, Node* b, bool link, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
NodeLinkCommand(Node* a, Node* b, bool link) :
|
||||
a_(a),
|
||||
b_(b),
|
||||
link_(link)
|
||||
@@ -245,8 +241,7 @@ public:
|
||||
return a_->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
if (link_) {
|
||||
done_ = Node::Link(a_, b_);
|
||||
@@ -255,7 +250,7 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
if (done_) {
|
||||
if (link_) {
|
||||
@@ -276,8 +271,7 @@ private:
|
||||
|
||||
class NodeUnlinkAllCommand : public UndoCommand {
|
||||
public:
|
||||
NodeUnlinkAllCommand(Node* node, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
NodeUnlinkAllCommand(Node* node) :
|
||||
node_(node)
|
||||
{
|
||||
}
|
||||
@@ -287,8 +281,7 @@ public:
|
||||
return node_->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
unlinked_ = node_->links();
|
||||
|
||||
@@ -297,7 +290,7 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
foreach (Node* link, unlinked_) {
|
||||
Node::Link(node_, link);
|
||||
@@ -313,16 +306,15 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class NodeLinkManyCommand : public UndoCommand {
|
||||
class NodeLinkManyCommand : public MultiUndoCommand {
|
||||
public:
|
||||
NodeLinkManyCommand(const QVector<Node*> nodes, bool link, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
NodeLinkManyCommand(const QVector<Node*> nodes, bool link) :
|
||||
nodes_(nodes)
|
||||
{
|
||||
foreach (Node* a, nodes_) {
|
||||
foreach (Node* b, nodes_) {
|
||||
if (a != b) {
|
||||
new NodeLinkCommand(a, b, link, this);
|
||||
add_child(new NodeLinkCommand(a, b, link));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -571,7 +571,7 @@ void ProjectExplorer::DeleteSelected()
|
||||
return;
|
||||
}
|
||||
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
foreach (Item* item, selected) {
|
||||
// Verify whether this item is in use anywhere
|
||||
@@ -629,7 +629,7 @@ void ProjectExplorer::DeleteSelected()
|
||||
if (msgbox.clickedButton() == offline_btn || msgbox.clickedButton() == delete_clip_btn) {
|
||||
|
||||
// For safety, even if we're deleting clips, we'll offline the footage nodes too
|
||||
new OfflineFootageCommand(footage_nodes, command);
|
||||
command->add_child(new OfflineFootageCommand(footage_nodes));
|
||||
|
||||
}
|
||||
|
||||
@@ -676,7 +676,7 @@ void ProjectExplorer::DeleteSelected()
|
||||
break;
|
||||
}
|
||||
|
||||
new ProjectViewModel::RemoveItemCommand(&model_, item, command);
|
||||
command->add_child(new ProjectViewModel::RemoveItemCommand(&model_, item));
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
|
||||
@@ -31,8 +31,7 @@ namespace olive {
|
||||
*/
|
||||
class OfflineFootageCommand : public UndoCommand {
|
||||
public:
|
||||
OfflineFootageCommand(const QVector<MediaInput*>& media, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent)
|
||||
OfflineFootageCommand(const QVector<MediaInput*>& media)
|
||||
{
|
||||
foreach (MediaInput* i, media) {
|
||||
stream_data_.insert(i, i->stream());
|
||||
@@ -46,15 +45,14 @@ public:
|
||||
return project_;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
for (auto it=stream_data_.cbegin(); it!=stream_data_.cend(); it++) {
|
||||
it.key()->SetStream(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
for (auto it=stream_data_.cbegin(); it!=stream_data_.cend(); it++) {
|
||||
it.key()->SetStream(it.value());
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "timebasedwidget.h"
|
||||
|
||||
#include <QInputDialog>
|
||||
#include <QUndoCommand>
|
||||
|
||||
#include "common/autoscroll.h"
|
||||
#include "common/timecodefunctions.h"
|
||||
@@ -435,11 +434,11 @@ void TimeBasedWidget::SetPoint(Timeline::MovementMode m, const rational& time)
|
||||
return;
|
||||
}
|
||||
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
// Enable workarea if it isn't already enabled
|
||||
if (!points_->workarea()->enabled()) {
|
||||
new WorkareaSetEnabledCommand(GetTimelinePointsProject(), points_, true, command);
|
||||
command->add_child(new WorkareaSetEnabledCommand(GetTimelinePointsProject(), points_, true));
|
||||
}
|
||||
|
||||
// Determine our new range
|
||||
@@ -464,7 +463,7 @@ void TimeBasedWidget::SetPoint(Timeline::MovementMode m, const rational& time)
|
||||
}
|
||||
|
||||
// Set workarea
|
||||
new WorkareaSetRangeCommand(GetTimelinePointsProject(), points_, TimeRange(in_point, out_point), command);
|
||||
command->add_child(new WorkareaSetRangeCommand(GetTimelinePointsProject(), points_, TimeRange(in_point, out_point)));
|
||||
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
}
|
||||
@@ -647,12 +646,12 @@ Project *TimeBasedWidget::MarkerAddCommand::GetRelevantProject() const
|
||||
return project_;
|
||||
}
|
||||
|
||||
void TimeBasedWidget::MarkerAddCommand::redo_internal()
|
||||
void TimeBasedWidget::MarkerAddCommand::redo()
|
||||
{
|
||||
added_marker_ = marker_list_->AddMarker(range_, name_);
|
||||
}
|
||||
|
||||
void TimeBasedWidget::MarkerAddCommand::undo_internal()
|
||||
void TimeBasedWidget::MarkerAddCommand::undo()
|
||||
{
|
||||
marker_list_->RemoveMarker(added_marker_);
|
||||
}
|
||||
|
||||
@@ -152,9 +152,8 @@ private:
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
Project* project_;
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
#ifndef TIMELINEUNDOABLE_H
|
||||
#define TIMELINEUNDOABLE_H
|
||||
|
||||
#include <QUndoCommand>
|
||||
|
||||
#include "config/config.h"
|
||||
#include "core.h"
|
||||
#include "node/block/block.h"
|
||||
@@ -46,22 +44,21 @@ inline bool NodeCanBeRemoved(Node* n)
|
||||
return n->edges().empty();
|
||||
}
|
||||
|
||||
inline QUndoCommand* CreateRemoveCommand(Node* n)
|
||||
inline UndoCommand* CreateRemoveCommand(Node* n)
|
||||
{
|
||||
return new NodeRemoveWithExclusiveDependenciesAndDisconnect(n);
|
||||
}
|
||||
|
||||
inline QUndoCommand* CreateAndRunRemoveCommand(Node* n)
|
||||
inline UndoCommand* CreateAndRunRemoveCommand(Node* n)
|
||||
{
|
||||
QUndoCommand* command = CreateRemoveCommand(n);
|
||||
UndoCommand* command = CreateRemoveCommand(n);
|
||||
command->redo();
|
||||
return command;
|
||||
}
|
||||
|
||||
class BlockResizeCommand : public UndoCommand {
|
||||
public:
|
||||
BlockResizeCommand(Block* block, rational new_length, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
BlockResizeCommand(Block* block, rational new_length) :
|
||||
block_(block),
|
||||
new_length_(new_length)
|
||||
{
|
||||
@@ -72,14 +69,13 @@ public:
|
||||
return block_->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
old_length_ = block_->length();
|
||||
block_->set_length_and_media_out(new_length_);
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
block_->set_length_and_media_out(old_length_);
|
||||
}
|
||||
@@ -93,8 +89,7 @@ private:
|
||||
|
||||
class BlockResizeWithMediaInCommand : public UndoCommand {
|
||||
public:
|
||||
BlockResizeWithMediaInCommand(Block* block, rational new_length, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
BlockResizeWithMediaInCommand(Block* block, rational new_length) :
|
||||
block_(block),
|
||||
new_length_(new_length)
|
||||
{
|
||||
@@ -105,14 +100,13 @@ public:
|
||||
return block_->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
old_length_ = block_->length();
|
||||
block_->set_length_and_media_in(new_length_);
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
block_->set_length_and_media_in(old_length_);
|
||||
}
|
||||
@@ -135,8 +129,7 @@ private:
|
||||
*/
|
||||
class BlockTrimCommand : public UndoCommand {
|
||||
public:
|
||||
BlockTrimCommand(Track *track, Block* block, rational new_length, Timeline::MovementMode mode, QUndoCommand* command = nullptr) :
|
||||
UndoCommand(command),
|
||||
BlockTrimCommand(Track *track, Block* block, rational new_length, Timeline::MovementMode mode) :
|
||||
prepped_(false),
|
||||
track_(track),
|
||||
block_(block),
|
||||
@@ -177,8 +170,7 @@ public:
|
||||
remove_block_from_graph_ = e;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
if (!prepped_) {
|
||||
prep();
|
||||
@@ -245,7 +237,7 @@ protected:
|
||||
track_->InvalidateCache(invalidate_range, track_->block_input());
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
if (doing_nothing_) {
|
||||
return;
|
||||
@@ -360,7 +352,7 @@ private:
|
||||
bool needs_adjacent_;
|
||||
bool we_created_adjacent_;
|
||||
bool we_removed_adjacent_;
|
||||
QUndoCommand* deleted_adjacent_command_;
|
||||
UndoCommand* deleted_adjacent_command_;
|
||||
|
||||
bool trim_is_a_roll_edit_;
|
||||
bool remove_block_from_graph_;
|
||||
@@ -371,8 +363,7 @@ private:
|
||||
|
||||
class BlockSetMediaInCommand : public UndoCommand {
|
||||
public:
|
||||
BlockSetMediaInCommand(Block* block, rational new_media_in, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
BlockSetMediaInCommand(Block* block, rational new_media_in) :
|
||||
block_(block),
|
||||
new_media_in_(new_media_in)
|
||||
{
|
||||
@@ -383,14 +374,13 @@ public:
|
||||
return block_->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
old_media_in_ = block_->media_in();
|
||||
block_->set_media_in(new_media_in_);
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
block_->set_media_in(old_media_in_);
|
||||
}
|
||||
@@ -403,8 +393,7 @@ private:
|
||||
|
||||
class TrackRippleRemoveBlockCommand : public UndoCommand {
|
||||
public:
|
||||
TrackRippleRemoveBlockCommand(Track* track, Block* block, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
TrackRippleRemoveBlockCommand(Track* track, Block* block) :
|
||||
track_(track),
|
||||
block_(block)
|
||||
{
|
||||
@@ -415,14 +404,13 @@ public:
|
||||
return track_->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
before_ = block_->previous();
|
||||
track_->RippleRemoveBlock(block_);
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
track_->InsertBlockAfter(block_, before_);
|
||||
}
|
||||
@@ -438,8 +426,7 @@ private:
|
||||
|
||||
class TrackPrependBlockCommand : public UndoCommand {
|
||||
public:
|
||||
TrackPrependBlockCommand(Track* track, Block* block, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
TrackPrependBlockCommand(Track* track, Block* block) :
|
||||
track_(track),
|
||||
block_(block)
|
||||
{
|
||||
@@ -450,13 +437,12 @@ public:
|
||||
return track_->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
track_->PrependBlock(block_);
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
track_->RippleRemoveBlock(block_);
|
||||
}
|
||||
@@ -468,8 +454,7 @@ private:
|
||||
|
||||
class TrackInsertBlockAfterCommand : public UndoCommand {
|
||||
public:
|
||||
TrackInsertBlockAfterCommand(Track* track, Block* block, Block* before, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
TrackInsertBlockAfterCommand(Track* track, Block* block, Block* before) :
|
||||
track_(track),
|
||||
block_(block),
|
||||
before_(before)
|
||||
@@ -481,13 +466,12 @@ public:
|
||||
return block_->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
track_->InsertBlockAfter(block_, before_);
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
track_->RippleRemoveBlock(block_);
|
||||
}
|
||||
@@ -502,8 +486,7 @@ private:
|
||||
|
||||
class BlockSplitCommand : public UndoCommand {
|
||||
public:
|
||||
BlockSplitCommand(Block* block, rational point, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
BlockSplitCommand(Block* block, rational point) :
|
||||
block_(block),
|
||||
point_(point),
|
||||
reconnect_tree_command_(nullptr)
|
||||
@@ -528,8 +511,7 @@ public:
|
||||
return static_cast<Block*>(added_nodes_.first());
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
old_length_ = block_->length();
|
||||
|
||||
@@ -571,8 +553,8 @@ protected:
|
||||
if (!reconnect_tree_command_) {
|
||||
if (copy_dependencies_too) {
|
||||
// Create equivalent connections among our copied dependency tree
|
||||
reconnect_tree_command_ = new QUndoCommand();
|
||||
Node::CopyDependencyGraph(src_nodes_, added_nodes_, reconnect_tree_command_);
|
||||
reconnect_tree_command_ = new MultiUndoCommand();
|
||||
Node::CopyDependencyGraph(src_nodes_, added_nodes_, static_cast<MultiUndoCommand*>(reconnect_tree_command_));
|
||||
} else {
|
||||
reconnect_tree_command_ = new NodeCopyInputsCommand(block_, new_block(), true);
|
||||
}
|
||||
@@ -613,7 +595,7 @@ protected:
|
||||
track->EndOperation();
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
Track* track = block_->track();
|
||||
|
||||
@@ -646,7 +628,7 @@ private:
|
||||
|
||||
QObject memory_manager_;
|
||||
|
||||
QUndoCommand* reconnect_tree_command_;
|
||||
UndoCommand* reconnect_tree_command_;
|
||||
|
||||
NodeInput* moved_transition_;
|
||||
|
||||
@@ -657,8 +639,7 @@ private:
|
||||
|
||||
class BlockSplitPreservingLinksCommand : public UndoCommand {
|
||||
public:
|
||||
BlockSplitPreservingLinksCommand(const QVector<Block *> &blocks, const QList<rational>& times, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
BlockSplitPreservingLinksCommand(const QVector<Block *> &blocks, const QList<rational>& times) :
|
||||
blocks_(blocks),
|
||||
times_(times)
|
||||
{
|
||||
@@ -674,8 +655,7 @@ public:
|
||||
return blocks_.first()->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
if (commands_.isEmpty()) {
|
||||
QVector< QVector<Block*> > split_blocks(times_.size());
|
||||
@@ -736,7 +716,7 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
for (int i=commands_.size()-1; i>=0; i--) {
|
||||
commands_.at(i)->undo();
|
||||
@@ -748,14 +728,13 @@ private:
|
||||
|
||||
QList<rational> times_;
|
||||
|
||||
QVector<QUndoCommand*> commands_;
|
||||
QVector<UndoCommand*> commands_;
|
||||
|
||||
};
|
||||
|
||||
class TrackSplitAtTimeCommand : public UndoCommand {
|
||||
public:
|
||||
TrackSplitAtTimeCommand(Track* track, rational point, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
TrackSplitAtTimeCommand(Track* track, rational point) :
|
||||
prepped_(false),
|
||||
track_(track),
|
||||
point_(point),
|
||||
@@ -773,8 +752,7 @@ public:
|
||||
return track_->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
if (!prepped_) {
|
||||
// Find Block that contains this time
|
||||
@@ -792,7 +770,7 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
if (command_) {
|
||||
command_->undo();
|
||||
@@ -806,7 +784,7 @@ private:
|
||||
|
||||
rational point_;
|
||||
|
||||
QUndoCommand* command_;
|
||||
UndoCommand* command_;
|
||||
|
||||
};
|
||||
|
||||
@@ -819,8 +797,7 @@ private:
|
||||
*/
|
||||
class TrackRippleRemoveAreaCommand : public UndoCommand {
|
||||
public:
|
||||
TrackRippleRemoveAreaCommand(Track* track, const TimeRange& range, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
TrackRippleRemoveAreaCommand(Track* track, const TimeRange& range) :
|
||||
prepped_(false),
|
||||
track_(track),
|
||||
range_(range),
|
||||
@@ -858,8 +835,7 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
if (!prepped_) {
|
||||
prep();
|
||||
@@ -900,7 +876,7 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
foreach (QUndoCommand* c, remove_block_commands_) {
|
||||
foreach (UndoCommand* c, remove_block_commands_) {
|
||||
c->redo();
|
||||
}
|
||||
}
|
||||
@@ -911,7 +887,7 @@ protected:
|
||||
track_->InvalidateCache(TimeRange(range_.in(), RATIONAL_MAX));
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
// Begin operations
|
||||
track_->BeginOperation();
|
||||
@@ -1028,14 +1004,13 @@ private:
|
||||
Block* insert_previous_;
|
||||
|
||||
BlockSplitCommand* splice_split_command_;
|
||||
QVector<QUndoCommand*> remove_block_commands_;
|
||||
QVector<UndoCommand*> remove_block_commands_;
|
||||
|
||||
};
|
||||
|
||||
class TrackListRippleRemoveAreaCommand : public UndoCommand {
|
||||
public:
|
||||
TrackListRippleRemoveAreaCommand(TrackList* list, rational in, rational out, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
TrackListRippleRemoveAreaCommand(TrackList* list, rational in, rational out) :
|
||||
list_(list),
|
||||
in_(in),
|
||||
out_(out)
|
||||
@@ -1052,8 +1027,7 @@ public:
|
||||
return static_cast<ViewerOutput*>(list_->parent())->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
// Code that's only run on the first redo
|
||||
if (commands_.isEmpty()) {
|
||||
@@ -1096,7 +1070,7 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
if (all_tracks_unlocked_) {
|
||||
// We can optimize here by simply shifting the whole cache forward instead of re-caching
|
||||
@@ -1138,17 +1112,15 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class TimelineRippleRemoveAreaCommand : public UndoCommand {
|
||||
class TimelineRippleRemoveAreaCommand : public MultiUndoCommand {
|
||||
public:
|
||||
TimelineRippleRemoveAreaCommand(ViewerOutput* timeline, rational in, rational out, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
TimelineRippleRemoveAreaCommand(ViewerOutput* timeline, rational in, rational out) :
|
||||
timeline_(timeline)
|
||||
{
|
||||
for (int i=0; i<Track::kCount; i++) {
|
||||
new TrackListRippleRemoveAreaCommand(timeline->track_list(static_cast<Track::Type>(i)),
|
||||
in,
|
||||
out,
|
||||
this);
|
||||
add_child(new TrackListRippleRemoveAreaCommand(timeline->track_list(static_cast<Track::Type>(i)),
|
||||
in,
|
||||
out));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1173,8 +1145,7 @@ public:
|
||||
const QHash<Track*, RippleInfo>& info,
|
||||
const rational& ripple_movement,
|
||||
const Timeline::MovementMode& movement_mode,
|
||||
QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
UndoCommand* parent = nullptr) :
|
||||
track_list_(track_list),
|
||||
info_(info),
|
||||
ripple_movement_(ripple_movement),
|
||||
@@ -1188,13 +1159,12 @@ public:
|
||||
return static_cast<ViewerOutput*>(track_list_->parent())->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
ripple(true);
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
ripple(false);
|
||||
}
|
||||
@@ -1385,8 +1355,7 @@ private:
|
||||
|
||||
class TimelineAddTrackCommand : public UndoCommand {
|
||||
public:
|
||||
TimelineAddTrackCommand(TrackList *timeline, QUndoCommand* command = nullptr) :
|
||||
UndoCommand(command),
|
||||
TimelineAddTrackCommand(TrackList *timeline) :
|
||||
timeline_(timeline)
|
||||
{
|
||||
track_ = new Track();
|
||||
@@ -1415,8 +1384,7 @@ public:
|
||||
return timeline_->GetParentGraph()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
// Add track
|
||||
track_->setParent(timeline_->GetParentGraph());
|
||||
@@ -1444,7 +1412,7 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
// Remove merge if applicable
|
||||
if (merge_) {
|
||||
@@ -1490,8 +1458,7 @@ private:
|
||||
*/
|
||||
class TrackPlaceBlockCommand : public UndoCommand {
|
||||
public:
|
||||
TrackPlaceBlockCommand(TrackList *timeline, int track, Block* block, rational in, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
TrackPlaceBlockCommand(TrackList *timeline, int track, Block* block, rational in) :
|
||||
timeline_(timeline),
|
||||
track_index_(track),
|
||||
in_(in),
|
||||
@@ -1512,8 +1479,7 @@ public:
|
||||
return timeline_->GetParentGraph()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
// Determine if we need to add tracks
|
||||
if (track_index_ >= timeline_->GetTracks().size()) {
|
||||
@@ -1560,7 +1526,7 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
Track* t = timeline_->GetTrackAt(track_index_);
|
||||
|
||||
@@ -1600,8 +1566,7 @@ private:
|
||||
*/
|
||||
class TrackReplaceBlockCommand : public UndoCommand {
|
||||
public:
|
||||
TrackReplaceBlockCommand(Track* track, Block* old, Block* replace, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
TrackReplaceBlockCommand(Track* track, Block* old, Block* replace) :
|
||||
track_(track),
|
||||
old_(old),
|
||||
replace_(replace)
|
||||
@@ -1613,13 +1578,12 @@ public:
|
||||
return track_->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
track_->ReplaceBlock(old_, replace_);
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
track_->ReplaceBlock(replace_, old_);
|
||||
}
|
||||
@@ -1633,8 +1597,7 @@ private:
|
||||
|
||||
class TrackReplaceBlockWithGapCommand : public UndoCommand {
|
||||
public:
|
||||
TrackReplaceBlockWithGapCommand(Track* track, Block* block, QUndoCommand* command = nullptr) :
|
||||
UndoCommand(command),
|
||||
TrackReplaceBlockWithGapCommand(Track* track, Block* block) :
|
||||
track_(track),
|
||||
block_(block),
|
||||
existing_gap_(nullptr),
|
||||
@@ -1648,8 +1611,7 @@ public:
|
||||
return block_->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
track_->BeginOperation();
|
||||
|
||||
@@ -1721,7 +1683,7 @@ protected:
|
||||
track_->InvalidateCache(invalidate_range, track_->block_input());
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
track_->BeginOperation();
|
||||
|
||||
@@ -1793,8 +1755,7 @@ private:
|
||||
|
||||
class TimelineRippleDeleteGapsAtRegionsCommand : public UndoCommand {
|
||||
public:
|
||||
TimelineRippleDeleteGapsAtRegionsCommand(ViewerOutput* vo, const TimeRangeList& regions, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
TimelineRippleDeleteGapsAtRegionsCommand(ViewerOutput* vo, const TimeRangeList& regions) :
|
||||
timeline_(vo),
|
||||
regions_(regions)
|
||||
{
|
||||
@@ -1810,8 +1771,7 @@ public:
|
||||
return timeline_->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
if (commands_.isEmpty()) {
|
||||
foreach (const TimeRange& range, regions_) {
|
||||
@@ -1849,12 +1809,12 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
foreach (QUndoCommand* c, commands_) {
|
||||
foreach (UndoCommand* c, commands_) {
|
||||
c->redo();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
for (int i=commands_.size()-1;i>=0;i--) {
|
||||
commands_.at(i)->undo();
|
||||
@@ -1865,14 +1825,13 @@ private:
|
||||
ViewerOutput* timeline_;
|
||||
TimeRangeList regions_;
|
||||
|
||||
QVector<QUndoCommand*> commands_;
|
||||
QVector<UndoCommand*> commands_;
|
||||
|
||||
};
|
||||
|
||||
class WorkareaSetEnabledCommand : public UndoCommand {
|
||||
public:
|
||||
WorkareaSetEnabledCommand(Project *project, TimelinePoints* points, bool enabled, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
WorkareaSetEnabledCommand(Project *project, TimelinePoints* points, bool enabled) :
|
||||
project_(project),
|
||||
points_(points),
|
||||
old_enabled_(points_->workarea()->enabled()),
|
||||
@@ -1885,13 +1844,12 @@ public:
|
||||
return project_;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
points_->workarea()->set_enabled(new_enabled_);
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
points_->workarea()->set_enabled(old_enabled_);
|
||||
}
|
||||
@@ -1909,8 +1867,7 @@ private:
|
||||
|
||||
class WorkareaSetRangeCommand : public UndoCommand {
|
||||
public:
|
||||
WorkareaSetRangeCommand(Project *project, TimelinePoints* points, const TimeRange& range, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
WorkareaSetRangeCommand(Project *project, TimelinePoints* points, const TimeRange& range) :
|
||||
project_(project),
|
||||
points_(points),
|
||||
old_range_(points_->workarea()->range()),
|
||||
@@ -1923,13 +1880,12 @@ public:
|
||||
return project_;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
points_->workarea()->set_range(new_range_);
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
points_->workarea()->set_range(old_range_);
|
||||
}
|
||||
@@ -1947,8 +1903,7 @@ private:
|
||||
|
||||
class BlockEnableDisableCommand : public UndoCommand {
|
||||
public:
|
||||
BlockEnableDisableCommand(Block* block, bool enabled, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
BlockEnableDisableCommand(Block* block, bool enabled) :
|
||||
block_(block),
|
||||
old_enabled_(block_->is_enabled()),
|
||||
new_enabled_(enabled)
|
||||
@@ -1960,13 +1915,12 @@ public:
|
||||
return block_->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
block_->set_enabled(new_enabled_);
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
block_->set_enabled(old_enabled_);
|
||||
}
|
||||
@@ -1982,8 +1936,7 @@ private:
|
||||
|
||||
class TrackSlideCommand : public UndoCommand {
|
||||
public:
|
||||
TrackSlideCommand(Track* track, const QList<Block*>& moving_blocks, Block* in_adjacent, Block* out_adjacent, const rational& movement, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
TrackSlideCommand(Track* track, const QList<Block*>& moving_blocks, Block* in_adjacent, Block* out_adjacent, const rational& movement) :
|
||||
prepped_(false),
|
||||
track_(track),
|
||||
blocks_(moving_blocks),
|
||||
@@ -2007,8 +1960,7 @@ public:
|
||||
return track_->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
if (!prepped_) {
|
||||
prep();
|
||||
@@ -2073,7 +2025,7 @@ protected:
|
||||
track_->InvalidateCache(invalidate_range, track_->block_input());
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
// Make sure all movement blocks' old positions are invalidated
|
||||
TimeRange invalidate_range(blocks_.first()->in(), blocks_.last()->out());
|
||||
@@ -2145,10 +2097,10 @@ private:
|
||||
|
||||
bool we_created_in_adjacent_;
|
||||
Block* in_adjacent_;
|
||||
QUndoCommand* in_adjacent_remove_command_;
|
||||
UndoCommand* in_adjacent_remove_command_;
|
||||
bool we_created_out_adjacent_;
|
||||
Block* out_adjacent_;
|
||||
QUndoCommand* out_adjacent_remove_command_;
|
||||
UndoCommand* out_adjacent_remove_command_;
|
||||
|
||||
QObject memory_manager_;
|
||||
|
||||
@@ -2156,8 +2108,7 @@ private:
|
||||
|
||||
class TrackListInsertGaps : public UndoCommand {
|
||||
public:
|
||||
TrackListInsertGaps(TrackList* track_list, const rational& point, const rational& length, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
TrackListInsertGaps(TrackList* track_list, const rational& point, const rational& length) :
|
||||
prepped_(false),
|
||||
track_list_(track_list),
|
||||
point_(point),
|
||||
@@ -2176,8 +2127,7 @@ public:
|
||||
return static_cast<ViewerOutput*>(track_list_->parent())->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
if (!prepped_) {
|
||||
prep();
|
||||
@@ -2221,7 +2171,7 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
if (all_tracks_unlocked_) {
|
||||
// Optimize by shifting over since we have a constant amount of time being inserted
|
||||
@@ -2340,8 +2290,7 @@ private:
|
||||
|
||||
class TransitionRemoveCommand : public UndoCommand {
|
||||
public:
|
||||
TransitionRemoveCommand(TransitionBlock* block, QUndoCommand *parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
TransitionRemoveCommand(TransitionBlock* block, UndoCommand *parent = nullptr) :
|
||||
block_(block)
|
||||
{
|
||||
}
|
||||
@@ -2351,8 +2300,7 @@ public:
|
||||
return track_->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
virtual void redo() override
|
||||
{
|
||||
track_ = block_->track();
|
||||
out_block_ = block_->connected_out_block();
|
||||
@@ -2387,7 +2335,7 @@ protected:
|
||||
track_->InvalidateCache(invalidate_range, track_->block_input());
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
virtual void undo() override
|
||||
{
|
||||
track_->BeginOperation();
|
||||
|
||||
|
||||
@@ -421,7 +421,7 @@ void TimelineWidget::SplitAtPlayhead()
|
||||
|
||||
void TimelineWidget::ReplaceBlocksWithGaps(const QVector<Block *> &blocks,
|
||||
bool remove_from_graph,
|
||||
QUndoCommand *command)
|
||||
MultiUndoCommand *command)
|
||||
{
|
||||
foreach (Block* b, blocks) {
|
||||
if (b->type() == Block::kGap) {
|
||||
@@ -432,10 +432,10 @@ void TimelineWidget::ReplaceBlocksWithGaps(const QVector<Block *> &blocks,
|
||||
|
||||
Track* original_track = b->track();
|
||||
|
||||
new TrackReplaceBlockWithGapCommand(original_track, b, command);
|
||||
command->add_child(new TrackReplaceBlockWithGapCommand(original_track, b));
|
||||
|
||||
if (remove_from_graph) {
|
||||
new NodeRemoveWithExclusiveDependenciesAndDisconnect(b, command);
|
||||
command->add_child(new NodeRemoveWithExclusiveDependenciesAndDisconnect(b));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -454,7 +454,7 @@ void TimelineWidget::DeleteSelected(bool ripple)
|
||||
return;
|
||||
}
|
||||
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
QVector<Block*> clips_to_delete;
|
||||
QVector<TransitionBlock*> transitions_to_delete;
|
||||
@@ -469,16 +469,16 @@ void TimelineWidget::DeleteSelected(bool ripple)
|
||||
|
||||
// For transitions, remove them but extend their attached blocks to fill their place
|
||||
foreach (TransitionBlock* transition, transitions_to_delete) {
|
||||
new TransitionRemoveCommand(transition, command);
|
||||
command->add_child(new TransitionRemoveCommand(transition));
|
||||
|
||||
new NodeRemoveWithExclusiveDependenciesAndDisconnect(transition, command);
|
||||
command->add_child(new NodeRemoveWithExclusiveDependenciesAndDisconnect(transition));
|
||||
}
|
||||
|
||||
// Replace clips with gaps (effectively deleting them)
|
||||
ReplaceBlocksWithGaps(clips_to_delete, true, command);
|
||||
|
||||
// Remove all selections
|
||||
new SetSelectionsCommand(this, TimelineWidgetSelections(), GetSelections(), command);
|
||||
command->add_child(new SetSelectionsCommand(this, TimelineWidgetSelections(), GetSelections()));
|
||||
|
||||
// Insert ripple command now that it's all cleaned up gaps
|
||||
if (ripple) {
|
||||
@@ -488,7 +488,7 @@ void TimelineWidget::DeleteSelected(bool ripple)
|
||||
range_list.insert(TimeRange(b->in(), b->out()));
|
||||
}
|
||||
|
||||
new TimelineRippleDeleteGapsAtRegionsCommand(GetConnectedNode(), range_list, command);
|
||||
command->add_child(new TimelineRippleDeleteGapsAtRegionsCommand(GetConnectedNode(), range_list));
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
@@ -593,7 +593,7 @@ void TimelineWidget::Paste(bool insert)
|
||||
return;
|
||||
}
|
||||
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
QVector<BlockPasteData> paste_data;
|
||||
QVector<Node*> pasted = PasteNodesFromClipboard(GetConnectedNode()->parent(), command, &paste_data);
|
||||
@@ -614,11 +614,10 @@ void TimelineWidget::Paste(bool insert)
|
||||
|
||||
foreach (const BlockPasteData& bpd, paste_data) {
|
||||
qDebug() << "Placing" << bpd.block;
|
||||
new TrackPlaceBlockCommand(GetConnectedNode()->track_list(bpd.track_type),
|
||||
bpd.track_index,
|
||||
bpd.block,
|
||||
paste_start + bpd.in,
|
||||
command);
|
||||
command->add_child(new TrackPlaceBlockCommand(GetConnectedNode()->track_list(bpd.track_type),
|
||||
bpd.track_index,
|
||||
bpd.block,
|
||||
paste_start + bpd.in));
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
@@ -632,14 +631,13 @@ void TimelineWidget::DeleteInToOut(bool ripple)
|
||||
return;
|
||||
}
|
||||
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
if (ripple) {
|
||||
|
||||
new TimelineRippleRemoveAreaCommand(GetConnectedNode(),
|
||||
GetConnectedTimelinePoints()->workarea()->in(),
|
||||
GetConnectedTimelinePoints()->workarea()->out(),
|
||||
command);
|
||||
command->add_child(new TimelineRippleRemoveAreaCommand(GetConnectedNode(),
|
||||
GetConnectedTimelinePoints()->workarea()->in(),
|
||||
GetConnectedTimelinePoints()->workarea()->out()));
|
||||
|
||||
} else {
|
||||
QVector<Track*> unlocked_tracks = GetConnectedNode()->GetUnlockedTracks();
|
||||
@@ -649,23 +647,20 @@ void TimelineWidget::DeleteInToOut(bool ripple)
|
||||
|
||||
gap->set_length_and_media_out(GetConnectedTimelinePoints()->workarea()->length());
|
||||
|
||||
new NodeAddCommand(static_cast<NodeGraph*>(track->parent()),
|
||||
gap,
|
||||
command);
|
||||
command->add_child(new NodeAddCommand(static_cast<NodeGraph*>(track->parent()),
|
||||
gap));
|
||||
|
||||
new TrackPlaceBlockCommand(GetConnectedNode()->track_list(track->type()),
|
||||
track->Index(),
|
||||
gap,
|
||||
GetConnectedTimelinePoints()->workarea()->in(),
|
||||
command);
|
||||
command->add_child(new TrackPlaceBlockCommand(GetConnectedNode()->track_list(track->type()),
|
||||
track->Index(),
|
||||
gap,
|
||||
GetConnectedTimelinePoints()->workarea()->in()));
|
||||
}
|
||||
}
|
||||
|
||||
// Clear workarea after this
|
||||
new WorkareaSetEnabledCommand(GetTimelinePointsProject(),
|
||||
GetConnectedTimelinePoints(),
|
||||
false,
|
||||
command);
|
||||
command->add_child(new WorkareaSetEnabledCommand(GetTimelinePointsProject(),
|
||||
GetConnectedTimelinePoints(),
|
||||
false));
|
||||
|
||||
if (ripple) {
|
||||
SetTimeAndSignal(Timecode::time_to_timestamp(GetConnectedTimelinePoints()->workarea()->in(),
|
||||
@@ -683,12 +678,11 @@ void TimelineWidget::ToggleSelectedEnabled()
|
||||
return;
|
||||
}
|
||||
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
foreach (Block* i, items) {
|
||||
new BlockEnableDisableCommand(i,
|
||||
!i->is_enabled(),
|
||||
command);
|
||||
command->add_child(new BlockEnableDisableCommand(i,
|
||||
!i->is_enabled()));
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
@@ -701,13 +695,12 @@ void TimelineWidget::SetColorLabel(int index)
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::InsertGapsAt(const rational &earliest_point, const rational &insert_length, QUndoCommand *command)
|
||||
void TimelineWidget::InsertGapsAt(const rational &earliest_point, const rational &insert_length, MultiUndoCommand *command)
|
||||
{
|
||||
for (int i=0;i<Track::kCount;i++) {
|
||||
new TrackListInsertGaps(GetConnectedNode()->track_list(static_cast<Track::Type>(i)),
|
||||
earliest_point,
|
||||
insert_length,
|
||||
command);
|
||||
command->add_child(new TrackListInsertGaps(GetConnectedNode()->track_list(static_cast<Track::Type>(i)),
|
||||
earliest_point,
|
||||
insert_length));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1238,7 +1231,7 @@ void TimelineWidget::EditTo(Timeline::MovementMode mode)
|
||||
return;
|
||||
}
|
||||
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
foreach (const Timeline::EditToInfo& info, tracks) {
|
||||
if (info.nearest_block
|
||||
@@ -1253,11 +1246,10 @@ void TimelineWidget::EditTo(Timeline::MovementMode mode)
|
||||
}
|
||||
new_len = info.nearest_block->length() - new_len;
|
||||
|
||||
new BlockTrimCommand(info.track,
|
||||
info.nearest_block,
|
||||
new_len,
|
||||
mode,
|
||||
command);
|
||||
command->add_child(new BlockTrimCommand(info.track,
|
||||
info.nearest_block,
|
||||
new_len,
|
||||
mode));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ public:
|
||||
|
||||
void RestoreSplitterState(const QByteArray& state);
|
||||
|
||||
static void ReplaceBlocksWithGaps(const QVector<Block *> &blocks, bool remove_from_graph, QUndoCommand* command);
|
||||
static void ReplaceBlocksWithGaps(const QVector<Block *> &blocks, bool remove_from_graph, MultiUndoCommand *command);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the QGraphicsItem at a particular scene position
|
||||
@@ -136,7 +136,7 @@ public:
|
||||
return ghost_items_;
|
||||
}
|
||||
|
||||
void InsertGapsAt(const rational& time, const rational& length, QUndoCommand* command);
|
||||
void InsertGapsAt(const rational& time, const rational& length, MultiUndoCommand *command);
|
||||
|
||||
void StartRubberBandSelect(const QPoint& global_cursor_start);
|
||||
void MoveRubberBandSelect(bool enable_selecting, bool select_links);
|
||||
@@ -197,17 +197,15 @@ public:
|
||||
*/
|
||||
void SignalDeselectedAllBlocks();
|
||||
|
||||
class SetSelectionsCommand : public QUndoCommand {
|
||||
class SetSelectionsCommand : public UndoCommand {
|
||||
public:
|
||||
SetSelectionsCommand(TimelineWidget* timeline, const TimelineWidgetSelections& now, const TimelineWidgetSelections& old, QUndoCommand* parent = nullptr) :
|
||||
QUndoCommand(parent),
|
||||
SetSelectionsCommand(TimelineWidget* timeline, const TimelineWidgetSelections& now, const TimelineWidgetSelections& old) :
|
||||
timeline_(timeline),
|
||||
old_(old),
|
||||
now_(now)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo() override
|
||||
{
|
||||
timeline_->SetSelections(now_);
|
||||
@@ -218,6 +216,8 @@ public:
|
||||
timeline_->SetSelections(old_);
|
||||
}
|
||||
|
||||
virtual Project* GetRelevantProject() const override {return nullptr;}
|
||||
|
||||
private:
|
||||
TimelineWidget* timeline_;
|
||||
TimelineWidgetSelections old_;
|
||||
|
||||
@@ -91,7 +91,7 @@ void AddTool::MouseRelease(TimelineViewMouseEvent *event)
|
||||
|
||||
if (ghost_) {
|
||||
if (!ghost_->GetAdjustedLength().isNull()) {
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
ClipBlock* clip = new ClipBlock();
|
||||
clip->set_length_and_media_out(ghost_->GetAdjustedLength());
|
||||
@@ -99,15 +99,13 @@ void AddTool::MouseRelease(TimelineViewMouseEvent *event)
|
||||
|
||||
NodeGraph* graph = static_cast<NodeGraph*>(parent()->GetConnectedNode()->parent());
|
||||
|
||||
new NodeAddCommand(graph,
|
||||
clip,
|
||||
command);
|
||||
command->add_child(new NodeAddCommand(graph,
|
||||
clip));
|
||||
|
||||
new TrackPlaceBlockCommand(parent()->GetConnectedNode()->track_list(track.type()),
|
||||
track.index(),
|
||||
clip,
|
||||
ghost_->GetAdjustedIn(),
|
||||
command);
|
||||
command->add_child(new TrackPlaceBlockCommand(parent()->GetConnectedNode()->track_list(track.type()),
|
||||
track.index(),
|
||||
clip,
|
||||
ghost_->GetAdjustedIn()));
|
||||
|
||||
switch (Core::instance()->GetSelectedAddableObject()) {
|
||||
case olive::Tool::kAddableEmpty:
|
||||
@@ -117,22 +115,20 @@ void AddTool::MouseRelease(TimelineViewMouseEvent *event)
|
||||
{
|
||||
Node* solid = new SolidGenerator();
|
||||
|
||||
new NodeAddCommand(graph,
|
||||
solid,
|
||||
command);
|
||||
command->add_child(new NodeAddCommand(graph,
|
||||
solid));
|
||||
|
||||
new NodeEdgeAddCommand(solid, clip->texture_input(), -1, command);
|
||||
command->add_child(new NodeEdgeAddCommand(solid, clip->texture_input(), -1));
|
||||
break;
|
||||
}
|
||||
case olive::Tool::kAddableTitle:
|
||||
{
|
||||
Node* text = new TextGenerator();
|
||||
|
||||
new NodeAddCommand(graph,
|
||||
text,
|
||||
command);
|
||||
command->add_child(new NodeAddCommand(graph,
|
||||
text));
|
||||
|
||||
new NodeEdgeAddCommand(text, clip->texture_input(), -1, command);
|
||||
command->add_child(new NodeEdgeAddCommand(text, clip->texture_input(), -1));
|
||||
break;
|
||||
}
|
||||
case olive::Tool::kAddableBars:
|
||||
|
||||
@@ -306,7 +306,7 @@ void ImportTool::PrepGhosts(const rational& frame, const int& track_index)
|
||||
|
||||
void ImportTool::DropGhosts(bool insert)
|
||||
{
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
NodeGraph* dst_graph = nullptr;
|
||||
ViewerOutput* viewer_node = nullptr;
|
||||
@@ -383,10 +383,9 @@ void ImportTool::DropGhosts(bool insert)
|
||||
if (sequence_is_valid) {
|
||||
new_sequence->add_default_nodes();
|
||||
|
||||
new ProjectViewModel::AddItemCommand(Core::instance()->GetActiveProjectModel(),
|
||||
Core::instance()->GetSelectedFolderInActiveProject(),
|
||||
new_sequence,
|
||||
command);
|
||||
command->add_child(new ProjectViewModel::AddItemCommand(Core::instance()->GetActiveProjectModel(),
|
||||
Core::instance()->GetSelectedFolderInActiveProject(),
|
||||
new_sequence));
|
||||
|
||||
FootageToGhosts(0, dragged_footage_, new_sequence->video_params().time_base(), 0);
|
||||
|
||||
@@ -422,44 +421,43 @@ void ImportTool::DropGhosts(bool insert)
|
||||
clip->set_media_in(ghost->GetMediaIn());
|
||||
clip->set_length_and_media_out(ghost->GetLength());
|
||||
clip->SetLabel(footage_stream->footage()->name());
|
||||
new NodeAddCommand(dst_graph, clip, command);
|
||||
command->add_child(new NodeAddCommand(dst_graph, clip));
|
||||
|
||||
switch (footage_stream->type()) {
|
||||
case Stream::kVideo:
|
||||
{
|
||||
MediaInput* video_input = new MediaInput();
|
||||
video_input->SetStream(footage_stream);
|
||||
new NodeAddCommand(dst_graph, video_input, command);
|
||||
command->add_child(new NodeAddCommand(dst_graph, video_input));
|
||||
|
||||
TransformDistortNode* transform = new TransformDistortNode();
|
||||
new NodeAddCommand(dst_graph, transform, command);
|
||||
command->add_child(new NodeAddCommand(dst_graph, transform));
|
||||
|
||||
new NodeEdgeAddCommand(video_input, transform->texture_input(), -1, command);
|
||||
new NodeEdgeAddCommand(transform, clip->texture_input(), -1, command);
|
||||
command->add_child(new NodeEdgeAddCommand(video_input, transform->texture_input(), -1));
|
||||
command->add_child(new NodeEdgeAddCommand(transform, clip->texture_input(), -1));
|
||||
break;
|
||||
}
|
||||
case Stream::kAudio:
|
||||
{
|
||||
MediaInput* audio_input = new MediaInput();
|
||||
audio_input->SetStream(footage_stream);
|
||||
new NodeAddCommand(dst_graph, audio_input, command);
|
||||
command->add_child(new NodeAddCommand(dst_graph, audio_input));
|
||||
|
||||
VolumeNode* volume_node = new VolumeNode();
|
||||
new NodeAddCommand(dst_graph, volume_node, command);
|
||||
command->add_child(new NodeAddCommand(dst_graph, volume_node));
|
||||
|
||||
new NodeEdgeAddCommand(audio_input, volume_node->samples_input(), -1, command);
|
||||
new NodeEdgeAddCommand(volume_node, clip->texture_input(), -1, command);
|
||||
command->add_child(new NodeEdgeAddCommand(audio_input, volume_node->samples_input(), -1));
|
||||
command->add_child(new NodeEdgeAddCommand(volume_node, clip->texture_input(), -1));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
new TrackPlaceBlockCommand(viewer_node->track_list(ghost->GetAdjustedTrack().type()),
|
||||
ghost->GetAdjustedTrack().index(),
|
||||
clip,
|
||||
ghost->GetAdjustedIn(),
|
||||
command);
|
||||
command->add_child(new TrackPlaceBlockCommand(viewer_node->track_list(ghost->GetAdjustedTrack().type()),
|
||||
ghost->GetAdjustedTrack().index(),
|
||||
clip,
|
||||
ghost->GetAdjustedIn()));
|
||||
|
||||
block_items.replace(i, clip);
|
||||
|
||||
|
||||
@@ -563,7 +563,7 @@ void PointerTool::FinishDrag(TimelineViewMouseEvent *event)
|
||||
return;
|
||||
}
|
||||
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
if (!blocks_trimming.isEmpty()) {
|
||||
foreach (const GhostBlockPair& p, blocks_trimming) {
|
||||
@@ -574,10 +574,11 @@ void PointerTool::FinishDrag(TimelineViewMouseEvent *event)
|
||||
BlockTrimCommand* c = new BlockTrimCommand(parent()->GetTrackFromReference(ghost->GetAdjustedTrack()),
|
||||
p.block,
|
||||
ghost->GetAdjustedLength(),
|
||||
ghost->GetMode(),
|
||||
command);
|
||||
ghost->GetMode());
|
||||
|
||||
c->SetTrimIsARollEdit(ghost->GetData(TimelineViewGhostItem::kTrimIsARollEdit).toBool());
|
||||
|
||||
command->add_child(c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -590,7 +591,7 @@ void PointerTool::FinishDrag(TimelineViewMouseEvent *event)
|
||||
} else {
|
||||
new_sel.TrimOut(reference_ghost->GetOutAdjustment());
|
||||
}
|
||||
new TimelineWidget::SetSelectionsCommand(parent(), new_sel, parent()->GetSelections(), command);
|
||||
command->add_child(new TimelineWidget::SetSelectionsCommand(parent(), new_sel, parent()->GetSelections()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -632,11 +633,10 @@ void PointerTool::FinishDrag(TimelineViewMouseEvent *event)
|
||||
} else {
|
||||
copy = block->copy();
|
||||
|
||||
new NodeAddCommand(static_cast<NodeGraph*>(block->parent()),
|
||||
copy,
|
||||
command);
|
||||
command->add_child(new NodeAddCommand(static_cast<NodeGraph*>(block->parent()),
|
||||
copy));
|
||||
|
||||
new NodeCopyInputsCommand(block, copy, true, command);
|
||||
command->add_child(new NodeCopyInputsCommand(block, copy, true));
|
||||
}
|
||||
|
||||
// Place the copy instead of the original block
|
||||
@@ -644,18 +644,17 @@ void PointerTool::FinishDrag(TimelineViewMouseEvent *event)
|
||||
}
|
||||
|
||||
const Track::Reference& track_ref = p.ghost->GetAdjustedTrack();
|
||||
new TrackPlaceBlockCommand(parent()->GetConnectedNode()->track_list(track_ref.type()),
|
||||
track_ref.index(),
|
||||
block,
|
||||
p.ghost->GetAdjustedIn(),
|
||||
command);
|
||||
command->add_child(new TrackPlaceBlockCommand(parent()->GetConnectedNode()->track_list(track_ref.type()),
|
||||
track_ref.index(),
|
||||
block,
|
||||
p.ghost->GetAdjustedIn()));
|
||||
}
|
||||
|
||||
// Adjust selections
|
||||
TimelineWidgetSelections new_sel = parent()->GetSelections();
|
||||
new_sel.ShiftTime(blocks_moving.first().ghost->GetInAdjustment());
|
||||
new_sel.ShiftTracks(drag_track_type_, blocks_moving.first().ghost->GetTrackAdjustment());
|
||||
new TimelineWidget::SetSelectionsCommand(parent(), new_sel, parent()->GetSelections(), command);
|
||||
command->add_child(new TimelineWidget::SetSelectionsCommand(parent(), new_sel, parent()->GetSelections()));
|
||||
}
|
||||
|
||||
if (!blocks_sliding.isEmpty()) {
|
||||
@@ -706,18 +705,17 @@ 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++) {
|
||||
new TrackSlideCommand(parent()->GetTrackFromReference(i.key()),
|
||||
command->add_child(new TrackSlideCommand(parent()->GetTrackFromReference(i.key()),
|
||||
i.value(),
|
||||
in_adjacents.value(i.key()),
|
||||
out_adjacents.value(i.key()),
|
||||
movement,
|
||||
command);
|
||||
movement));
|
||||
}
|
||||
|
||||
// Adjust selections
|
||||
TimelineWidgetSelections new_sel = parent()->GetSelections();
|
||||
new_sel.ShiftTime(movement);
|
||||
new TimelineWidget::SetSelectionsCommand(parent(), new_sel, parent()->GetSelections(), command);
|
||||
command->add_child(new TimelineWidget::SetSelectionsCommand(parent(), new_sel, parent()->GetSelections()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ void RippleTool::FinishDrag(TimelineViewMouseEvent *event)
|
||||
info_list[track->type()].insert(track, info);
|
||||
}
|
||||
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
rational movement;
|
||||
|
||||
@@ -144,15 +144,14 @@ void RippleTool::FinishDrag(TimelineViewMouseEvent *event)
|
||||
|
||||
for (int i=0;i<info_list.size();i++) {
|
||||
if (!info_list.at(i).isEmpty()) {
|
||||
new TrackListRippleToolCommand(parent()->GetConnectedNode()->track_list(static_cast<Track::Type>(i)),
|
||||
info_list.at(i),
|
||||
movement,
|
||||
drag_movement_mode(),
|
||||
command);
|
||||
command->add_child(new TrackListRippleToolCommand(parent()->GetConnectedNode()->track_list(static_cast<Track::Type>(i)),
|
||||
info_list.at(i),
|
||||
movement,
|
||||
drag_movement_mode()));
|
||||
}
|
||||
}
|
||||
|
||||
if (command->childCount() > 0) {
|
||||
if (command->child_count() > 0) {
|
||||
TimelineWidgetSelections new_sel = parent()->GetSelections();
|
||||
TimelineViewGhostItem* reference_ghost = parent()->GetGhostItems().first();
|
||||
if (drag_movement_mode() == Timeline::kTrimIn) {
|
||||
@@ -160,7 +159,7 @@ void RippleTool::FinishDrag(TimelineViewMouseEvent *event)
|
||||
} else {
|
||||
new_sel.TrimOut(reference_ghost->GetOutAdjustment());
|
||||
}
|
||||
new TimelineWidget::SetSelectionsCommand(parent(), new_sel, parent()->GetSelections(), command);
|
||||
command->add_child(new TimelineWidget::SetSelectionsCommand(parent(), new_sel, parent()->GetSelections()));
|
||||
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
} else {
|
||||
|
||||
@@ -68,13 +68,13 @@ void SlipTool::FinishDrag(TimelineViewMouseEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
// Find earliest point to ripple around
|
||||
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
|
||||
Block* b = Node::ValueToPtr<Block>(ghost->GetData(TimelineViewGhostItem::kAttachedBlock));
|
||||
|
||||
new BlockSetMediaInCommand(b, ghost->GetAdjustedMediaIn(), command);
|
||||
command->add_child(new BlockSetMediaInCommand(b, ghost->GetAdjustedMediaIn()));
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
|
||||
@@ -128,7 +128,7 @@ void TimelineTool::GetGhostData(rational *earliest_point, rational *latest_point
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineTool::InsertGapsAtGhostDestination(QUndoCommand *command)
|
||||
void TimelineTool::InsertGapsAtGhostDestination(olive::MultiUndoCommand *command)
|
||||
{
|
||||
rational earliest_point, latest_point;
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ protected:
|
||||
|
||||
void GetGhostData(rational *earliest_point, rational *latest_point);
|
||||
|
||||
void InsertGapsAtGhostDestination(QUndoCommand* command);
|
||||
void InsertGapsAtGhostDestination(MultiUndoCommand* command);
|
||||
|
||||
QVector<rational> snap_points_;
|
||||
|
||||
|
||||
@@ -120,18 +120,16 @@ void TransitionTool::MouseRelease(TimelineViewMouseEvent *event)
|
||||
transition = static_cast<TransitionBlock*>(NodeFactory::CreateFromID(Core::instance()->GetSelectedTransition()));
|
||||
}
|
||||
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
// Place transition in place
|
||||
new NodeAddCommand(static_cast<NodeGraph*>(parent()->GetConnectedNode()->parent()),
|
||||
transition,
|
||||
command);
|
||||
command->add_child(new NodeAddCommand(static_cast<NodeGraph*>(parent()->GetConnectedNode()->parent()),
|
||||
transition));
|
||||
|
||||
new TrackPlaceBlockCommand(parent()->GetConnectedNode()->track_list(track.type()),
|
||||
track.index(),
|
||||
transition,
|
||||
ghost_->GetAdjustedIn(),
|
||||
command);
|
||||
command->add_child(new TrackPlaceBlockCommand(parent()->GetConnectedNode()->track_list(track.type()),
|
||||
track.index(),
|
||||
transition,
|
||||
ghost_->GetAdjustedIn()));
|
||||
|
||||
if (dual_transition_) {
|
||||
transition->set_length_and_media_out(ghost_->GetAdjustedLength());
|
||||
@@ -148,15 +146,13 @@ void TransitionTool::MouseRelease(TimelineViewMouseEvent *event)
|
||||
Block* in_block = (ghost_->GetMode() == Timeline::kTrimIn) ? active_block : friend_block;
|
||||
|
||||
// Connect block to transition
|
||||
new NodeEdgeAddCommand(out_block,
|
||||
transition->out_block_input(),
|
||||
-1,
|
||||
command);
|
||||
command->add_child(new NodeEdgeAddCommand(out_block,
|
||||
transition->out_block_input(),
|
||||
-1));
|
||||
|
||||
new NodeEdgeAddCommand(in_block,
|
||||
transition->in_block_input(),
|
||||
-1,
|
||||
command);
|
||||
command->add_child(new NodeEdgeAddCommand(in_block,
|
||||
transition->in_block_input(),
|
||||
-1));
|
||||
} else {
|
||||
Block* block_to_transition = Node::ValueToPtr<Block>(ghost_->GetData(TimelineViewGhostItem::kAttachedBlock));
|
||||
NodeInput* transition_input_to_connect;
|
||||
@@ -170,10 +166,9 @@ void TransitionTool::MouseRelease(TimelineViewMouseEvent *event)
|
||||
}
|
||||
|
||||
// Connect block to transition
|
||||
new NodeEdgeAddCommand(block_to_transition,
|
||||
transition_input_to_connect,
|
||||
-1,
|
||||
command);
|
||||
command->add_child(new NodeEdgeAddCommand(block_to_transition,
|
||||
transition_input_to_connect,
|
||||
-1));
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
|
||||
@@ -75,10 +75,10 @@ MainMenu::MainMenu(MainWindow *parent) :
|
||||
//
|
||||
edit_menu_ = new Menu(this);
|
||||
|
||||
edit_undo_item_ = Core::instance()->undo_stack()->createUndoAction(this);
|
||||
edit_undo_item_ = Core::instance()->undo_stack()->GetUndoAction();
|
||||
Menu::ConformItem(edit_undo_item_, "undo", "Ctrl+Z");
|
||||
edit_menu_->addAction(edit_undo_item_);
|
||||
edit_redo_item_ = Core::instance()->undo_stack()->createRedoAction(this);
|
||||
edit_redo_item_ = Core::instance()->undo_stack()->GetRedoAction();
|
||||
Menu::ConformItem(edit_redo_item_, "redo", "Ctrl+Shift+Z");
|
||||
edit_menu_->addAction(edit_redo_item_);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user