From b88b7380710895ebdc6730bf11ff94e2bea924dd Mon Sep 17 00:00:00 2001 From: itsmattkc <34096995+itsmattkc@users.noreply.github.com> Date: Tue, 28 Feb 2023 15:20:05 -0800 Subject: [PATCH] project: moved color manager outside of node graph --- app/common/qtutils.cpp | 10 + app/common/qtutils.h | 1 + .../projectproperties/projectproperties.cpp | 13 + .../projectproperties/projectproperties.h | 2 + app/node/color/colormanager/colormanager.cpp | 112 ++---- app/node/color/colormanager/colormanager.h | 67 +--- app/node/color/ociobase/ociobase.cpp | 7 +- app/node/color/ociobase/ociobase.h | 8 +- app/node/node.h | 3 + app/node/nodeundo.cpp | 2 +- app/node/project.cpp | 80 ++-- app/node/project.h | 34 +- app/node/project/footage/footage.cpp | 34 +- app/node/project/footage/footage.h | 7 +- app/node/project/serializer/serializer.cpp | 6 +- .../project/serializer/serializer210528.cpp | 84 ++++- .../project/serializer/serializer210528.h | 2 + .../project/serializer/serializer210907.cpp | 84 ++++- .../project/serializer/serializer210907.h | 2 + .../project/serializer/serializer211228.cpp | 84 ++++- .../project/serializer/serializer211228.h | 2 + .../project/serializer/serializer220403.cpp | 83 ++++- .../project/serializer/serializer220403.h | 2 + .../project/serializer/serializer230220.cpp | 341 +++++++++--------- app/render/colorprocessor.cpp | 5 - app/render/previewautocacher.cpp | 2 +- app/render/projectcopier.h | 2 + app/task/export/export.cpp | 2 +- app/task/precache/precachetask.cpp | 1 - app/widget/manageddisplay/manageddisplay.cpp | 15 +- app/widget/manageddisplay/manageddisplay.h | 2 - 31 files changed, 706 insertions(+), 393 deletions(-) diff --git a/app/common/qtutils.cpp b/app/common/qtutils.cpp index 495c95047..95ca7b712 100644 --- a/app/common/qtutils.cpp +++ b/app/common/qtutils.cpp @@ -172,6 +172,16 @@ void QtUtils::SetComboBoxData(QComboBox *cb, int data) } } +void QtUtils::SetComboBoxData(QComboBox *cb, const QString &data) +{ + for (int i=0; icount(); i++) { + if (cb->itemData(i).toString() == data) { + cb->setCurrentIndex(i); + break; + } + } +} + QColor QtUtils::toQColor(const core::Color &i) { QColor c; diff --git a/app/common/qtutils.h b/app/common/qtutils.h index 8fb85ae1c..c4eeef027 100644 --- a/app/common/qtutils.h +++ b/app/common/qtutils.h @@ -57,6 +57,7 @@ public: static Qt::KeyboardModifiers FlipControlAndShiftModifiers(Qt::KeyboardModifiers e); static void SetComboBoxData(QComboBox *cb, int data); + static void SetComboBoxData(QComboBox *cb, const QString &data); template static T *GetParentOfType(const QObject *child) diff --git a/app/dialog/projectproperties/projectproperties.cpp b/app/dialog/projectproperties/projectproperties.cpp index def4e269f..e059e9ac9 100644 --- a/app/dialog/projectproperties/projectproperties.cpp +++ b/app/dialog/projectproperties/projectproperties.cpp @@ -74,6 +74,16 @@ ProjectPropertiesDialog::ProjectPropertiesDialog(Project* p, QWidget *parent) : row++; + color_layout->addWidget(new QLabel(tr("Reference Space:")), row, 0); + + reference_space_ = new QComboBox(this); + reference_space_->addItem(tr("Scene Linear"), OCIO::ROLE_SCENE_LINEAR); + reference_space_->addItem(tr("Compositing Log"), OCIO::ROLE_COMPOSITING_LOG); + QtUtils::SetComboBoxData(reference_space_, p->GetColorReferenceSpace()); + color_layout->addWidget(reference_space_, row, 1, 1, 2); + + row++; + QPushButton* browse_btn = new QPushButton(tr("Browse")); color_layout->addWidget(browse_btn, 0, 2); connect(browse_btn, &QPushButton::clicked, this, &ProjectPropertiesDialog::BrowseForOCIOConfig); @@ -177,6 +187,9 @@ void ProjectPropertiesDialog::accept() if (working_project_->color_manager()->GetDefaultInputColorSpace() != default_input_colorspace_->currentText()) { working_project_->color_manager()->SetDefaultInputColorSpace(default_input_colorspace_->currentText()); } + if (working_project_->GetColorReferenceSpace() != reference_space_->currentData().toString()) { + working_project_->SetColorReferenceSpace(reference_space_->currentData().toString()); + } super::accept(); } diff --git a/app/dialog/projectproperties/projectproperties.h b/app/dialog/projectproperties/projectproperties.h index ed0bbf786..46b3131ea 100644 --- a/app/dialog/projectproperties/projectproperties.h +++ b/app/dialog/projectproperties/projectproperties.h @@ -51,6 +51,8 @@ private: QComboBox* default_input_colorspace_; + QComboBox *reference_space_; + bool ocio_config_is_valid_; QString ocio_config_error_; diff --git a/app/node/color/colormanager/colormanager.cpp b/app/node/color/colormanager/colormanager.cpp index 4dfac3e6c..c65e316f7 100644 --- a/app/node/color/colormanager/colormanager.cpp +++ b/app/node/color/colormanager/colormanager.cpp @@ -30,29 +30,22 @@ namespace olive { -const QString ColorManager::kConfigFilenameIn = QStringLiteral("config"); -const QString ColorManager::kDefaultColorspaceIn = QStringLiteral("default_input"); -const QString ColorManager::kReferenceSpaceIn = QStringLiteral("reference_space"); - #define super Node OCIO::ConstConfigRcPtr ColorManager::default_config_ = nullptr; -ColorManager::ColorManager() : +ColorManager::ColorManager(Project *project) : + QObject(project), config_(nullptr) { - // Filename input - AddInput(kConfigFilenameIn, NodeValue::kFile, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable)); - - // Colorspace input - AddInput(kDefaultColorspaceIn, NodeValue::kCombo, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable)); - - // Default reference space is scene linear - AddInput(kReferenceSpaceIn, NodeValue::kCombo, 0, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable)); +} +void ColorManager::Init() +{ // Set config to our built-in default - SetConfig(GetDefaultConfig()); + config_ = GetDefaultConfig(); SetDefaultInputColorSpace(config_->getCanonicalName(OCIO::ROLE_DEFAULT)); + project()->SetColorReferenceSpace(OCIO::ROLE_SCENE_LINEAR); } OCIO::ConstConfigRcPtr ColorManager::GetConfig() const @@ -62,14 +55,12 @@ OCIO::ConstConfigRcPtr ColorManager::GetConfig() const OCIO::ConstConfigRcPtr ColorManager::CreateConfigFromFile(const QString &filename) { - OCIO_SET_C_LOCALE_FOR_SCOPE; - return OCIO::Config::CreateFromFile(filename.toUtf8()); } QString ColorManager::GetConfigFilename() const { - return GetStandardValue(kConfigFilenameIn).toString(); + return project()->GetColorConfigFilename(); } OCIO::ConstConfigRcPtr ColorManager::GetDefaultConfig() @@ -82,7 +73,6 @@ void ColorManager::SetUpDefaultConfig() if (!qEnvironmentVariableIsEmpty("OCIO")) { // Attempt to set config from "OCIO" environment variable try { - OCIO_SET_C_LOCALE_FOR_SCOPE; default_config_ = OCIO::Config::CreateFromEnv(); return; @@ -100,15 +90,12 @@ void ColorManager::SetUpDefaultConfig() qDebug() << "Extracting default OCIO config to" << dir; - { - OCIO_SET_C_LOCALE_FOR_SCOPE; - default_config_ = CreateConfigFromFile(QDir(dir).filePath(QStringLiteral("config.ocio"))); - } + default_config_ = CreateConfigFromFile(QDir(dir).filePath(QStringLiteral("config.ocio"))); } void ColorManager::SetConfigFilename(const QString &filename) { - SetStandardValue(kConfigFilenameIn, filename); + project()->SetColorConfigFilename(filename); } QStringList ColorManager::ListAvailableDisplays() @@ -167,23 +154,17 @@ QStringList ColorManager::ListAvailableColorspaces() const QString ColorManager::GetDefaultInputColorSpace() const { - return ListAvailableColorspaces().at(GetStandardValue(kDefaultColorspaceIn).toInt()); + return project()->GetDefaultInputColorSpace(); } void ColorManager::SetDefaultInputColorSpace(const QString &s) { - SetStandardValue(kDefaultColorspaceIn, ListAvailableColorspaces().indexOf(s)); + project()->SetDefaultInputColorSpace(s); } QString ColorManager::GetReferenceColorSpace() const { - ReferenceSpace ref_space = static_cast(GetStandardValue(kReferenceSpaceIn).toInt()); - - if (ref_space == kCompositingLog) { - return OCIO::ROLE_COMPOSITING_LOG; - } else { - return OCIO::ROLE_SCENE_LINEAR; - } + return project()->GetColorReferenceSpace(); } QString ColorManager::GetCompliantColorSpace(const QString &s) @@ -253,62 +234,33 @@ void ColorManager::GetDefaultLumaCoefs(double *rgb) const config_->getDefaultLumaCoefs(rgb); } -void ColorManager::Retranslate() +Project *ColorManager::project() const { - super::Retranslate(); - - SetInputName(kConfigFilenameIn, tr("Configuration")); - SetInputName(kDefaultColorspaceIn, tr("Default Input")); - SetInputName(kReferenceSpaceIn, tr("Reference Space")); - - SetComboBoxStrings(kReferenceSpaceIn, {tr("Scene Linear"), tr("Compositing Log")}); - SetInputProperty(kConfigFilenameIn, QStringLiteral("placeholder"), tr("(built-in)")); + return static_cast(parent()); } -void ColorManager::InputValueChangedEvent(const QString &input, int element) +void ColorManager::UpdateConfigFromFilename() { - Q_UNUSED(element) + try { + QString config_filename = GetConfigFilename(); + QString old_default_cs = GetDefaultInputColorSpace(); - if (input == kConfigFilenameIn) { + config_ = OCIO::Config::CreateFromFile(config_filename.toUtf8()); - try { - QString old_default_cs = GetDefaultInputColorSpace(); - - SetConfig(OCIO::Config::CreateFromFile(GetConfigFilename().toUtf8())); - - // Set new default colorspace appropriately - int new_default = 0; - QStringList available_cs = ListAvailableColorspaces(); - for (int i=0; i Category() const override - { - return {kCategoryColor}; - } - - virtual QString Description() const override - { - return tr("Color management configuration for project."); - } + void Init(); OCIO::ConstConfigRcPtr GetConfig() const; @@ -98,47 +76,20 @@ public: void GetDefaultLumaCoefs(double *rgb) const; - class SetLocale - { - public: - SetLocale(const char* new_locale); + Project *project() const; - ~SetLocale(); - - private: - QString old_locale_; - - }; - - QMutex* mutex() - { - return &mutex_; - } - - static const QString kConfigFilenameIn; - static const QString kDefaultColorspaceIn; - static const QString kReferenceSpaceIn; - - virtual void Retranslate() override; + void UpdateConfigFromFilename(); signals: - void ConfigChanged(); + void ConfigChanged(const QString &s); -protected: - virtual void InputValueChangedEvent(const QString &input, int element) override; + void ReferenceSpaceChanged(const QString &s); + + void DefaultInputChanged(const QString &s); private: - enum ReferenceSpace { - kSceneLinear, - kCompositingLog - }; - - void SetConfig(OCIO::ConstConfigRcPtr config); - OCIO::ConstConfigRcPtr config_; - QMutex mutex_; - static OCIO::ConstConfigRcPtr default_config_; }; diff --git a/app/node/color/ociobase/ociobase.cpp b/app/node/color/ociobase/ociobase.cpp index f749922ca..015f1db97 100644 --- a/app/node/color/ociobase/ociobase.cpp +++ b/app/node/color/ociobase/ociobase.cpp @@ -35,20 +35,17 @@ OCIOBaseNode::OCIOBaseNode() : SetEffectInput(kTextureInput); - connect(this, &Node::AddedToGraph, this, &OCIOBaseNode::AddedToGraph); - connect(this, &Node::RemovedFromGraph, this, &OCIOBaseNode::RemovedFromGraph); - SetFlag(kVideoEffect); } -void OCIOBaseNode::AddedToGraph(Project *p) +void OCIOBaseNode::AddedToGraphEvent(Project *p) { manager_ = p->color_manager(); connect(manager_, &ColorManager::ConfigChanged, this, &OCIOBaseNode::ConfigChanged); ConfigChanged(); } -void OCIOBaseNode::RemovedFromGraph() +void OCIOBaseNode::RemovedFromGraphEvent(Project *p) { if (manager_) { disconnect(manager_, &ColorManager::ConfigChanged, this, &OCIOBaseNode::ConfigChanged); diff --git a/app/node/color/ociobase/ociobase.h b/app/node/color/ociobase/ociobase.h index 1c5f349fa..c476a69fe 100644 --- a/app/node/color/ociobase/ociobase.h +++ b/app/node/color/ociobase/ociobase.h @@ -32,6 +32,9 @@ class OCIOBaseNode : public Node public: OCIOBaseNode(); + virtual void AddedToGraphEvent(Project *p) override; + virtual void RemovedFromGraphEvent(Project *p) override; + virtual void Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const override; static const QString kTextureInput; @@ -50,11 +53,6 @@ private: ColorProcessorPtr processor_; -private slots: - void AddedToGraph(Project *p); - - void RemovedFromGraph(); - }; } diff --git a/app/node/node.h b/app/node/node.h index c05877fa6..129b240fe 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -977,6 +977,9 @@ public: void ArrayResizeInternal(const QString& id, int size); + virtual void AddedToGraphEvent(Project *p){} + virtual void RemovedFromGraphEvent(Project *p){} + static const QString kEnabledInput; protected: diff --git a/app/node/nodeundo.cpp b/app/node/nodeundo.cpp index d78ab94c7..f83f2666d 100644 --- a/app/node/nodeundo.cpp +++ b/app/node/nodeundo.cpp @@ -198,7 +198,7 @@ void NodeAddCommand::undo() Project *NodeAddCommand::GetRelevantProject() const { - return dynamic_cast(graph_); + return graph_; } void NodeRemoveAndDisconnectCommand::prepare() diff --git a/app/node/project.cpp b/app/node/project.cpp index 30ce0a246..7e948e5fc 100644 --- a/app/node/project.cpp +++ b/app/node/project.cpp @@ -27,6 +27,7 @@ #include "common/xmlutils.h" #include "core.h" #include "dialog/progress/progress.h" +#include "node/color/ociobase/ociobase.h" #include "node/factory.h" #include "node/serializeddata.h" #include "render/diskmanager.h" @@ -36,6 +37,12 @@ namespace olive { #define super QObject +const QString Project::kCacheLocationSettingKey = QStringLiteral("cachesetting"); +const QString Project::kCachePathKey = QStringLiteral("customcachepath"); +const QString Project::kColorConfigFilename = QStringLiteral("colorconfigfilename"); +const QString Project::kDefaultInputColorSpaceKey = QStringLiteral("defaultinputcolorspace"); +const QString Project::kColorReferenceSpace = QStringLiteral("colorreferencespace"); + const QString Project::kItemMimeType = QStringLiteral("application/x-oliveprojectitemdata"); Project::Project() : @@ -51,13 +58,8 @@ Project::Project() : root_->SetLabel(tr("Root")); AddDefaultNode(root_); - // Adds a color manager "node" to this project so that it synchronizes - color_manager_ = new ColorManager(); - color_manager_->setParent(this); - AddDefaultNode(color_manager_); - - connect(color_manager(), &ColorManager::ValueChanged, - this, &Project::ColorManagerValueChanged); + color_manager_ = new ColorManager(this); + color_manager_->Init(); } Project::~Project() @@ -92,8 +94,6 @@ SerializedData Project::Load(QXmlStreamReader *reader) while (XMLReadNextStartElement(reader)) { if (reader->name() == QStringLiteral("node")) { bool is_root = false; - bool is_cm = false; - bool is_settings = false; QString id; { @@ -102,10 +102,6 @@ SerializedData Project::Load(QXmlStreamReader *reader) id = attr.value().toString(); } else if (attr.name() == QStringLiteral("root") && attr.value() == QStringLiteral("1")) { is_root = true; - } else if (attr.name() == QStringLiteral("cm") && attr.value() == QStringLiteral("1")) { - is_cm = true; - } else if (attr.name() == QStringLiteral("settings") && attr.value() == QStringLiteral("1")) { - is_settings = true; } } } @@ -118,8 +114,6 @@ SerializedData Project::Load(QXmlStreamReader *reader) if (is_root) { node = this->root(); - } else if (is_cm) { - node = this->color_manager(); } else { node = NodeFactory::CreateFromID(id); } @@ -141,6 +135,12 @@ SerializedData Project::Load(QXmlStreamReader *reader) } } + } else if (reader->name() == QStringLiteral("settings")) { + while (XMLReadNextStartElement(reader)) { + QString key = reader->name().toString(); + QString val = reader->readElementText(); + SetSetting(key, val); + } } else { // Skip this @@ -158,23 +158,33 @@ void Project::Save(QXmlStreamWriter *writer) const writer->writeTextElement(QStringLiteral("uuid"), this->GetUuid().toString()); - writer->writeStartElement(QStringLiteral("nodes")); + if (!this->nodes().isEmpty()) { + writer->writeStartElement(QStringLiteral("nodes")); - foreach (Node* node, this->nodes()) { - writer->writeStartElement(QStringLiteral("node")); + foreach (Node* node, this->nodes()) { + writer->writeStartElement(QStringLiteral("node")); - if (node == this->root()) { - writer->writeAttribute(QStringLiteral("root"), QStringLiteral("1")); - } else if (node == this->color_manager()) { - writer->writeAttribute(QStringLiteral("cm"), QStringLiteral("1")); + if (node == this->root()) { + writer->writeAttribute(QStringLiteral("root"), QStringLiteral("1")); + } + + node->Save(writer); + + writer->writeEndElement(); // node } - node->Save(writer); - - writer->writeEndElement(); // node + writer->writeEndElement(); // nodes } - writer->writeEndElement(); // nodes + if (!this->settings_.isEmpty()) { + writer->writeStartElement(QStringLiteral("settings")); + + for (auto it = this->settings_.cbegin(); it != this->settings_.cend(); it++) { + writer->writeTextElement(it.key(), it.value()); + } + + writer->writeEndElement(); // settings + } } int Project::GetNumberOfContextsNodeIsIn(Node *node, bool except_itself) const @@ -215,6 +225,7 @@ void Project::childEvent(QChildEvent *event) emit NodeAdded(node); emit node->AddedToGraph(this); + node->AddedToGraphEvent(this); // Emit input connections for (auto it=node->input_connections().cbegin(); it!=node->input_connections().cend(); it++) { @@ -248,6 +259,7 @@ void Project::childEvent(QChildEvent *event) emit NodeRemoved(node); emit node->RemovedFromGraph(this); + node->RemovedFromGraphEvent(this); // Remove from any contexts foreach (Node *context, node_children_) { @@ -368,17 +380,13 @@ void Project::SetSetting(const QString &key, const QString &value) { settings_.insert(key, value); emit SettingChanged(key, value); -} -void Project::ColorManagerValueChanged(const NodeInput &input, const TimeRange &range) -{ - Q_UNUSED(input) - Q_UNUSED(range) - - QVector footage = root()->ListChildrenOfType(); - - foreach (Footage* item, footage) { - item->InvalidateAll(QString()); + if (key == kColorReferenceSpace) { + emit color_manager_->ReferenceSpaceChanged(value); + } else if (key == kColorConfigFilename) { + color_manager_->UpdateConfigFromFilename(); + } else if (key == kDefaultInputColorSpaceKey) { + emit color_manager_->DefaultInputChanged(value); } } diff --git a/app/node/project.h b/app/node/project.h index a4d91c971..2e562943d 100644 --- a/app/node/project.h +++ b/app/node/project.h @@ -25,9 +25,9 @@ #include #include -#include "node/color/colormanager/colormanager.h" #include "node/output/viewer/viewer.h" #include "node/project/footage/footage.h" +#include "node/color/colormanager/colormanager.h" #include "window/mainwindow/mainwindowlayoutinfo.h" namespace olive { @@ -87,7 +87,7 @@ public: void set_filename(const QString& s); Folder* root() const { return root_; } - ColorManager* color_manager() const { return color_manager_; } + ColorManager *color_manager() const { return color_manager_; } bool is_modified() const { return is_modified_; } void set_modified(bool e); @@ -139,14 +139,29 @@ public: static const QString kItemMimeType; + static const QString kCacheLocationSettingKey; + static const QString kCachePathKey; + static const QString kColorConfigFilename; + static const QString kColorReferenceSpace; + static const QString kDefaultInputColorSpaceKey; + QString GetSetting(const QString &key) const { return settings_.value(key); } void SetSetting(const QString &key, const QString &value); - CacheSetting GetCacheLocationSetting() const { return static_cast(GetSetting(QStringLiteral("cachesetting")).toInt()); } - void SetCacheLocationSetting(CacheSetting s) { SetSetting(QStringLiteral("cachesetting"), QString::number(s)); } + CacheSetting GetCacheLocationSetting() const { return static_cast(GetSetting(kCacheLocationSettingKey).toInt()); } + void SetCacheLocationSetting(CacheSetting s) { SetSetting(kCacheLocationSettingKey, QString::number(s)); } - QString GetCustomCachePath() const { return GetSetting(QStringLiteral("customcachepath")); } - void SetCustomCachePath(const QString &path) { SetSetting(QStringLiteral("customcachepath"), path); } + QString GetCustomCachePath() const { return GetSetting(kCachePathKey); } + void SetCustomCachePath(const QString &path) { SetSetting(kCachePathKey, path); } + + QString GetColorConfigFilename() const { return GetSetting(kColorConfigFilename); } + void SetColorConfigFilename(const QString& s) { SetSetting(kColorConfigFilename, s); } + + QString GetDefaultInputColorSpace() const { return GetSetting(kDefaultInputColorSpaceKey); } + void SetDefaultInputColorSpace(const QString& s) { SetSetting(kDefaultInputColorSpaceKey, s); } + + QString GetColorReferenceSpace() const { return GetSetting(kColorReferenceSpace); } + void SetColorReferenceSpace(const QString& s) { SetSetting(kColorReferenceSpace, s); } signals: void NameChanged(); @@ -196,21 +211,18 @@ private: QString saved_url_; - ColorManager* color_manager_; - bool is_modified_; bool autorecovery_saved_; + ColorManager *color_manager_; + QVector node_children_; QVector default_nodes_; QMap settings_; -private slots: - void ColorManagerValueChanged(const NodeInput& input, const TimeRange& range); - }; } diff --git a/app/node/project/footage/footage.cpp b/app/node/project/footage/footage.cpp index 08f7d05fb..1ff8cdce0 100644 --- a/app/node/project/footage/footage.cpp +++ b/app/node/project/footage/footage.cpp @@ -350,13 +350,6 @@ rational Footage::AdjustTimeByLoopMode(rational time, LoopMode loop_mode, const return time; } -void Footage::LoadFinishedEvent() -{ - if (!filename().isEmpty()) { - Reprobe(); - } -} - QVariant Footage::data(const DataType &d) const { switch (d) { @@ -472,6 +465,16 @@ void Footage::SaveCustom(QXmlStreamWriter *writer) const writer->writeEndElement(); // viewer } +void Footage::AddedToGraphEvent(Project *p) +{ + connect(p->color_manager(), &ColorManager::DefaultInputChanged, this, &Footage::DefaultColorSpaceChanged); +} + +void Footage::RemovedFromGraphEvent(Project *p) +{ + disconnect(p->color_manager(), &ColorManager::DefaultInputChanged, this, &Footage::DefaultColorSpaceChanged); +} + void Footage::Reprobe() { // Determine if file still exists @@ -596,4 +599,21 @@ void Footage::CheckFootage() } } +void Footage::DefaultColorSpaceChanged() +{ + bool inv = false; + int sz = GetVideoStreamCount(); + for (int i = 0; i < sz; i++) { + // Check if any of our streams are using the default colorspace + if (GetVideoParams(i).colorspace().isEmpty()) { + inv = true; + break; + } + } + + if (inv) { + InvalidateAll(kVideoParamsInput); + } +} + } diff --git a/app/node/project/footage/footage.h b/app/node/project/footage/footage.h index 1f2716434..39d5c1f58 100644 --- a/app/node/project/footage/footage.h +++ b/app/node/project/footage/footage.h @@ -167,8 +167,6 @@ public: static rational AdjustTimeByLoopMode(rational time, LoopMode loop_mode, const rational& length, VideoParams::Type type, const rational &timebase); - virtual void LoadFinishedEvent() override; - virtual QVariant data(const DataType &d) const override; virtual int GetTotalStreamCount() const override { return total_stream_count_; } @@ -178,6 +176,9 @@ public: static const QString kFilenameInput; + virtual void AddedToGraphEvent(Project *p) override; + virtual void RemovedFromGraphEvent(Project *p) override; + protected: virtual void InputValueChangedEvent(const QString &input, int element) override; @@ -209,6 +210,8 @@ private: private slots: void CheckFootage(); + void DefaultColorSpaceChanged(); + }; } diff --git a/app/node/project/serializer/serializer.cpp b/app/node/project/serializer/serializer.cpp index b08ba90b8..bc85d221c 100644 --- a/app/node/project/serializer/serializer.cpp +++ b/app/node/project/serializer/serializer.cpp @@ -109,13 +109,15 @@ ProjectSerializer::Result ProjectSerializer::Load(Project *project, QXmlStreamRe XMLAttributeLoop(reader, attr) { if (attr.name() == QStringLiteral("version")) { // 230220+ projects version = attr.value().toUInt(); + } else if (reader->name() == QStringLiteral("url")) { // 230220+ projects + project->SetSavedURL(attr.value().toString()); } } while (XMLReadNextStartElement(reader)) { if (reader->name() == QStringLiteral("version")) { // projects <= 220403 version = reader->readElementText().toUInt(); - } else if (reader->name() == QStringLiteral("url")) { + } else if (reader->name() == QStringLiteral("url")) { // projects <= 220403 if (project) { project->SetSavedURL(reader->readElementText()); } else { @@ -208,7 +210,7 @@ ProjectSerializer::Result ProjectSerializer::Save(QXmlStreamWriter *writer, cons writer->writeAttribute(QStringLiteral("version"), QString::number(serializer->Version())); if (!data.GetFilename().isEmpty()) { - writer->writeTextElement("url", data.GetFilename()); + writer->writeAttribute("url", data.GetFilename()); } serializer->Save(writer, data, nullptr); diff --git a/app/node/project/serializer/serializer210528.cpp b/app/node/project/serializer/serializer210528.cpp index 4d1800be7..03d155f44 100644 --- a/app/node/project/serializer/serializer210528.cpp +++ b/app/node/project/serializer/serializer210528.cpp @@ -68,7 +68,8 @@ ProjectSerializer210528::LoadData ProjectSerializer210528::Load(Project *project if (is_root) { node = project->root(); } else if (is_cm) { - node = project->color_manager(); + LoadColorManager(reader, project); + handled_elsewhere = true; } else if (is_settings) { LoadProjectSettings(reader, project); handled_elsewhere = true; @@ -257,6 +258,87 @@ void ProjectSerializer210528::LoadNode(Node *node, XMLNodeData &xml_node_data, Q node->LoadFinishedEvent(); } +void ProjectSerializer210528::LoadColorManager(QXmlStreamReader *reader, Project *project) const +{ + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("input")) { + QString id; + XMLAttributeLoop(reader, attr) { + if (attr.name() == QStringLiteral("id")) { + id = attr.value().toString(); + } + } + + if (id == QStringLiteral("config") || id == QStringLiteral("default_input") || id == QStringLiteral("reference_space")) { + QString value; + + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("primary")) { + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("standard")) { + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("track")) { + value = reader->readElementText(); + } else { + reader->skipCurrentElement(); + } + } + } else { + reader->skipCurrentElement(); + } + } + } else { + reader->skipCurrentElement(); + } + } + + if (id == QStringLiteral("default_input")) { + // Default color space + // NOTE: Stupidly, we saved these as integers which means we can't add anything to the OCIO + // config. So we must convert back to string here. + static const QStringList list = { + QStringLiteral("Linear"), + QStringLiteral("CIE-XYZ D65"), + QStringLiteral("Filmic Log Encoding"), + QStringLiteral("sRGB OETF"), + QStringLiteral("Apple DCI-P3 D65"), + QStringLiteral("AppleP3 sRGB OETF"), + QStringLiteral("BT.1886 EOTF"), + QStringLiteral("AppleP3 Filmic Log Encoding"), + QStringLiteral("BT.1886 Filmic Log Encoding"), + QStringLiteral("Fuji F-Log OETF"), + QStringLiteral("Fuji F-Log F-Gamut"), + QStringLiteral("Panasonic V-Log V-Gamut"), + QStringLiteral("Arri Wide Gamut / LogC EI 800"), + QStringLiteral("Arri Wide Gamut / LogC EI 400"), + QStringLiteral("Blackmagic Film Wide Gamut (Gen 5)"), + QStringLiteral("Rec.709 OETF"), + QStringLiteral("Non-Colour Data") + }; + int num_value = value.toInt(); + value = list.at(num_value); + project->SetDefaultInputColorSpace(value); + } else if (id == QStringLiteral("reference_space")) { + // Reference space + if (value == QStringLiteral("1")) { + value = OCIO::ROLE_COMPOSITING_LOG; + } else { + value = OCIO::ROLE_SCENE_LINEAR; + } + project->SetColorReferenceSpace(value); + } else { + // Config filename + project->SetColorConfigFilename(value); + } + } else { + reader->skipCurrentElement(); + } + } else { + reader->skipCurrentElement(); + } + } +} + void ProjectSerializer210528::LoadProjectSettings(QXmlStreamReader *reader, Project *project) const { while (XMLReadNextStartElement(reader)) { diff --git a/app/node/project/serializer/serializer210528.h b/app/node/project/serializer/serializer210528.h index 3ff084304..322e30b6a 100644 --- a/app/node/project/serializer/serializer210528.h +++ b/app/node/project/serializer/serializer210528.h @@ -68,6 +68,8 @@ private: void LoadNode(Node *node, XMLNodeData &xml_node_data, QXmlStreamReader *reader) const; + void LoadColorManager(QXmlStreamReader* reader, Project *project) const; + void LoadProjectSettings(QXmlStreamReader* reader, Project *project) const; void LoadInput(Node *node, QXmlStreamReader* reader, XMLNodeData &xml_node_data) const; diff --git a/app/node/project/serializer/serializer210907.cpp b/app/node/project/serializer/serializer210907.cpp index 1961cb3bf..776007b29 100644 --- a/app/node/project/serializer/serializer210907.cpp +++ b/app/node/project/serializer/serializer210907.cpp @@ -68,7 +68,8 @@ ProjectSerializer210907::LoadData ProjectSerializer210907::Load(Project *project if (is_root) { node = project->root(); } else if (is_cm) { - node = project->color_manager(); + LoadColorManager(reader, project); + handled_elsewhere = true; } else if (is_settings) { LoadProjectSettings(reader, project); handled_elsewhere = true; @@ -254,6 +255,87 @@ void ProjectSerializer210907::LoadNode(Node *node, XMLNodeData &xml_node_data, Q node->LoadFinishedEvent(); } +void ProjectSerializer210907::LoadColorManager(QXmlStreamReader *reader, Project *project) const +{ + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("input")) { + QString id; + XMLAttributeLoop(reader, attr) { + if (attr.name() == QStringLiteral("id")) { + id = attr.value().toString(); + } + } + + if (id == QStringLiteral("config") || id == QStringLiteral("default_input") || id == QStringLiteral("reference_space")) { + QString value; + + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("primary")) { + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("standard")) { + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("track")) { + value = reader->readElementText(); + } else { + reader->skipCurrentElement(); + } + } + } else { + reader->skipCurrentElement(); + } + } + } else { + reader->skipCurrentElement(); + } + } + + if (id == QStringLiteral("default_input")) { + // Default color space + // NOTE: Stupidly, we saved these as integers which means we can't add anything to the OCIO + // config. So we must convert back to string here. + static const QStringList list = { + QStringLiteral("Linear"), + QStringLiteral("CIE-XYZ D65"), + QStringLiteral("Filmic Log Encoding"), + QStringLiteral("sRGB OETF"), + QStringLiteral("Apple DCI-P3 D65"), + QStringLiteral("AppleP3 sRGB OETF"), + QStringLiteral("BT.1886 EOTF"), + QStringLiteral("AppleP3 Filmic Log Encoding"), + QStringLiteral("BT.1886 Filmic Log Encoding"), + QStringLiteral("Fuji F-Log OETF"), + QStringLiteral("Fuji F-Log F-Gamut"), + QStringLiteral("Panasonic V-Log V-Gamut"), + QStringLiteral("Arri Wide Gamut / LogC EI 800"), + QStringLiteral("Arri Wide Gamut / LogC EI 400"), + QStringLiteral("Blackmagic Film Wide Gamut (Gen 5)"), + QStringLiteral("Rec.709 OETF"), + QStringLiteral("Non-Colour Data") + }; + int num_value = value.toInt(); + value = list.at(num_value); + project->SetDefaultInputColorSpace(value); + } else if (id == QStringLiteral("reference_space")) { + // Reference space + if (value == QStringLiteral("1")) { + value = OCIO::ROLE_COMPOSITING_LOG; + } else { + value = OCIO::ROLE_SCENE_LINEAR; + } + project->SetColorReferenceSpace(value); + } else { + // Config filename + project->SetColorConfigFilename(value); + } + } else { + reader->skipCurrentElement(); + } + } else { + reader->skipCurrentElement(); + } + } +} + void ProjectSerializer210907::LoadProjectSettings(QXmlStreamReader *reader, Project *project) const { while (XMLReadNextStartElement(reader)) { diff --git a/app/node/project/serializer/serializer210907.h b/app/node/project/serializer/serializer210907.h index d135aa2b5..8da5e752d 100644 --- a/app/node/project/serializer/serializer210907.h +++ b/app/node/project/serializer/serializer210907.h @@ -67,6 +67,8 @@ private: void LoadNode(Node *node, XMLNodeData &xml_node_data, QXmlStreamReader *reader) const; + void LoadColorManager(QXmlStreamReader* reader, Project *project) const; + void LoadProjectSettings(QXmlStreamReader* reader, Project *project) const; void LoadInput(Node *node, QXmlStreamReader* reader, XMLNodeData &xml_node_data) const; diff --git a/app/node/project/serializer/serializer211228.cpp b/app/node/project/serializer/serializer211228.cpp index 8d0a81a55..b5de4e896 100644 --- a/app/node/project/serializer/serializer211228.cpp +++ b/app/node/project/serializer/serializer211228.cpp @@ -70,7 +70,8 @@ ProjectSerializer211228::LoadData ProjectSerializer211228::Load(Project *project if (is_root) { node = project->root(); } else if (is_cm) { - node = project->color_manager(); + LoadColorManager(reader, project); + handled_elsewhere = true; } else if (is_settings) { LoadProjectSettings(reader, project); handled_elsewhere = true; @@ -304,6 +305,87 @@ void ProjectSerializer211228::LoadNode(Node *node, XMLNodeData &xml_node_data, Q node->LoadFinishedEvent(); } +void ProjectSerializer211228::LoadColorManager(QXmlStreamReader *reader, Project *project) const +{ + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("input")) { + QString id; + XMLAttributeLoop(reader, attr) { + if (attr.name() == QStringLiteral("id")) { + id = attr.value().toString(); + } + } + + if (id == QStringLiteral("config") || id == QStringLiteral("default_input") || id == QStringLiteral("reference_space")) { + QString value; + + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("primary")) { + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("standard")) { + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("track")) { + value = reader->readElementText(); + } else { + reader->skipCurrentElement(); + } + } + } else { + reader->skipCurrentElement(); + } + } + } else { + reader->skipCurrentElement(); + } + } + + if (id == QStringLiteral("default_input")) { + // Default color space + // NOTE: Stupidly, we saved these as integers which means we can't add anything to the OCIO + // config. So we must convert back to string here. + static const QStringList list = { + QStringLiteral("Linear"), + QStringLiteral("CIE-XYZ D65"), + QStringLiteral("Filmic Log Encoding"), + QStringLiteral("sRGB OETF"), + QStringLiteral("Apple DCI-P3 D65"), + QStringLiteral("AppleP3 sRGB OETF"), + QStringLiteral("BT.1886 EOTF"), + QStringLiteral("AppleP3 Filmic Log Encoding"), + QStringLiteral("BT.1886 Filmic Log Encoding"), + QStringLiteral("Fuji F-Log OETF"), + QStringLiteral("Fuji F-Log F-Gamut"), + QStringLiteral("Panasonic V-Log V-Gamut"), + QStringLiteral("Arri Wide Gamut / LogC EI 800"), + QStringLiteral("Arri Wide Gamut / LogC EI 400"), + QStringLiteral("Blackmagic Film Wide Gamut (Gen 5)"), + QStringLiteral("Rec.709 OETF"), + QStringLiteral("Non-Colour Data") + }; + int num_value = value.toInt(); + value = list.at(num_value); + project->SetDefaultInputColorSpace(value); + } else if (id == QStringLiteral("reference_space")) { + // Reference space + if (value == QStringLiteral("1")) { + value = OCIO::ROLE_COMPOSITING_LOG; + } else { + value = OCIO::ROLE_SCENE_LINEAR; + } + project->SetColorReferenceSpace(value); + } else { + // Config filename + project->SetColorConfigFilename(value); + } + } else { + reader->skipCurrentElement(); + } + } else { + reader->skipCurrentElement(); + } + } +} + void ProjectSerializer211228::LoadProjectSettings(QXmlStreamReader *reader, Project *project) const { while (XMLReadNextStartElement(reader)) { diff --git a/app/node/project/serializer/serializer211228.h b/app/node/project/serializer/serializer211228.h index 2cf5d2537..bd16d847a 100644 --- a/app/node/project/serializer/serializer211228.h +++ b/app/node/project/serializer/serializer211228.h @@ -68,6 +68,8 @@ private: void LoadNode(Node *node, XMLNodeData &xml_node_data, QXmlStreamReader *reader) const; + void LoadColorManager(QXmlStreamReader* reader, Project *project) const; + void LoadProjectSettings(QXmlStreamReader* reader, Project *project) const; void LoadInput(Node *node, QXmlStreamReader* reader, XMLNodeData &xml_node_data) const; diff --git a/app/node/project/serializer/serializer220403.cpp b/app/node/project/serializer/serializer220403.cpp index 7dbf2d459..db71168ed 100644 --- a/app/node/project/serializer/serializer220403.cpp +++ b/app/node/project/serializer/serializer220403.cpp @@ -89,7 +89,8 @@ ProjectSerializer220403::LoadData ProjectSerializer220403::Load(Project *project if (is_root) { node = project->root(); } else if (is_cm) { - node = project->color_manager(); + LoadColorManager(reader, project); + handled_elsewhere = true; } else if (is_settings) { LoadProjectSettings(reader, project); handled_elsewhere = true; @@ -452,6 +453,86 @@ void ProjectSerializer220403::LoadNode(Node *node, XMLNodeData &xml_node_data, Q node->LoadFinishedEvent(); } +void ProjectSerializer220403::LoadColorManager(QXmlStreamReader *reader, Project *project) const +{ + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("input")) { + QString id; + XMLAttributeLoop(reader, attr) { + if (attr.name() == QStringLiteral("id")) { + id = attr.value().toString(); + } + } + + if (id == QStringLiteral("config") || id == QStringLiteral("default_input") || id == QStringLiteral("reference_space")) { + QString value; + + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("primary")) { + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("standard")) { + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("track")) { + value = reader->readElementText(); + } else { + reader->skipCurrentElement(); + } + } + } else { + reader->skipCurrentElement(); + } + } + } else { + reader->skipCurrentElement(); + } + } + + if (id == QStringLiteral("default_input")) { + // Default color space + // NOTE: Stupidly, we saved these as integers which means we can't add anything to the OCIO + // config. So we must convert back to string here. + static const QStringList list = { + QStringLiteral("Linear"), + QStringLiteral("Filmic Log Encoding"), + QStringLiteral("sRGB OETF"), + QStringLiteral("Apple DCI-P3 D65"), + QStringLiteral("AppleP3 sRGB OETF"), + QStringLiteral("BT.1886 EOTF"), + QStringLiteral("AppleP3 Filmic Log Encoding"), + QStringLiteral("BT.1886 Filmic Log Encoding"), + QStringLiteral("Fuji F-Log OETF"), + QStringLiteral("Fuji F-Log F-Gamut"), + QStringLiteral("Panasonic V-Log V-Gamut"), + QStringLiteral("Arri Wide Gamut / LogC EI 800"), + QStringLiteral("Arri Wide Gamut / LogC EI 400"), + QStringLiteral("Blackmagic Film Wide Gamut (Gen 5)"), + QStringLiteral("Rec.709 OETF"), + QStringLiteral("Non-Colour Data") + }; + int num_value = value.toInt(); + value = list.at(num_value); + project->SetDefaultInputColorSpace(value); + } else if (id == QStringLiteral("reference_space")) { + // Reference space + if (value == QStringLiteral("1")) { + value = OCIO::ROLE_COMPOSITING_LOG; + } else { + value = OCIO::ROLE_SCENE_LINEAR; + } + project->SetColorReferenceSpace(value); + } else { + // Config filename + project->SetColorConfigFilename(value); + } + } else { + reader->skipCurrentElement(); + } + } else { + reader->skipCurrentElement(); + } + } +} + void ProjectSerializer220403::LoadProjectSettings(QXmlStreamReader *reader, Project *project) const { while (XMLReadNextStartElement(reader)) { diff --git a/app/node/project/serializer/serializer220403.h b/app/node/project/serializer/serializer220403.h index 5cc6e5d9e..74c6ccad7 100644 --- a/app/node/project/serializer/serializer220403.h +++ b/app/node/project/serializer/serializer220403.h @@ -74,6 +74,8 @@ private: void LoadNode(Node *node, XMLNodeData &xml_node_data, QXmlStreamReader *reader) const; + void LoadColorManager(QXmlStreamReader* reader, Project *project) const; + void LoadProjectSettings(QXmlStreamReader* reader, Project *project) const; void LoadInput(Node *node, QXmlStreamReader* reader, XMLNodeData &xml_node_data) const; diff --git a/app/node/project/serializer/serializer230220.cpp b/app/node/project/serializer/serializer230220.cpp index 0991d9a60..e312b5515 100644 --- a/app/node/project/serializer/serializer230220.cpp +++ b/app/node/project/serializer/serializer230220.cpp @@ -37,196 +37,211 @@ ProjectSerializer230220::LoadData ProjectSerializer230220::Load(Project *project switch (load_type) { case kProject: { - while (XMLReadNextStartElement(reader)) { - if (reader->name() == QStringLiteral("project")) { - project_data = project->Load(reader); - } else if (reader->name() == QStringLiteral("layout")) { - load_data.layout = MainWindowLayoutInfo::fromXml(reader, project_data.node_ptrs); - } else { - reader->skipCurrentElement(); + if (reader->name() == QStringLiteral("project")) { + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("project")) { + project_data = project->Load(reader); + } else if (reader->name() == QStringLiteral("layout")) { + load_data.layout = MainWindowLayoutInfo::fromXml(reader, project_data.node_ptrs); + } else { + reader->skipCurrentElement(); + } } - } - PostConnect(project->nodes(), &project_data); + PostConnect(project->nodes(), &project_data); + } else { + reader->skipCurrentElement(); + } break; } case kOnlyMarkers: { - while (XMLReadNextStartElement(reader)) { - if (reader->name() == QStringLiteral("marker")) { - TimelineMarker *marker = new TimelineMarker(); - marker->load(reader); - load_data.markers.push_back(marker); - } else { - reader->skipCurrentElement(); + if (reader->name() == QStringLiteral("markers")) { + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("marker")) { + TimelineMarker *marker = new TimelineMarker(); + marker->load(reader); + load_data.markers.push_back(marker); + } else { + reader->skipCurrentElement(); + } } + } else { + reader->skipCurrentElement(); } break; } case kOnlyKeyframes: { - while (XMLReadNextStartElement(reader)) { - if (reader->name() == QStringLiteral("node")) { - QString node_id; - XMLAttributeLoop(reader, attr) { - if (attr.name() == QStringLiteral("id")) { - node_id = attr.value().toString(); - break; - } - } - - Node *n = nullptr; - if (!node_id.isEmpty()) { - n = NodeFactory::CreateFromID(node_id); - } - - if (!n) { - reader->skipCurrentElement(); - } else { - while (XMLReadNextStartElement(reader)) { - if (reader->name() == QStringLiteral("input")) { - QString input_id; - XMLAttributeLoop(reader, attr) { - if (attr.name() == QStringLiteral("id")) { - input_id = attr.value().toString(); - break; - } - } - - if (input_id.isEmpty()) { - reader->skipCurrentElement(); - } else { - while (XMLReadNextStartElement(reader)) { - if (reader->name() == QStringLiteral("element")) { - QString element_id; - XMLAttributeLoop(reader, attr) { - if (attr.name() == QStringLiteral("id")) { - element_id = attr.value().toString(); - break; - } - } - - if (element_id.isEmpty()) { - reader->skipCurrentElement(); - } else { - while (XMLReadNextStartElement(reader)) { - if (reader->name() == QStringLiteral("track")) { - QString track_id; - XMLAttributeLoop(reader, attr) { - if (attr.name() == QStringLiteral("id")) { - track_id = attr.value().toString(); - break; - } - } - - if (track_id.isEmpty()) { - reader->skipCurrentElement(); - } else { - while (XMLReadNextStartElement(reader)) { - if (reader->name() == QStringLiteral("key")) { - NodeKeyframe *key = new NodeKeyframe(); - key->set_input(input_id); - key->set_element(element_id.toInt()); - key->set_track(track_id.toInt()); - - key->load(reader, n->GetInputDataType(input_id)); - - load_data.keyframes[node_id].append(key); - } else { - reader->skipCurrentElement(); - } - } - } - } else { - reader->skipCurrentElement(); - } - } - } - } else { - reader->skipCurrentElement(); - } - } - } - } else { - reader->skipCurrentElement(); + if (reader->name() == QStringLiteral("keyframes")) { + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("node")) { + QString node_id; + XMLAttributeLoop(reader, attr) { + if (attr.name() == QStringLiteral("id")) { + node_id = attr.value().toString(); + break; } } - } - delete n; - } else { - reader->skipCurrentElement(); + Node *n = nullptr; + if (!node_id.isEmpty()) { + n = NodeFactory::CreateFromID(node_id); + } + + if (!n) { + reader->skipCurrentElement(); + } else { + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("input")) { + QString input_id; + XMLAttributeLoop(reader, attr) { + if (attr.name() == QStringLiteral("id")) { + input_id = attr.value().toString(); + break; + } + } + + if (input_id.isEmpty()) { + reader->skipCurrentElement(); + } else { + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("element")) { + QString element_id; + XMLAttributeLoop(reader, attr) { + if (attr.name() == QStringLiteral("id")) { + element_id = attr.value().toString(); + break; + } + } + + if (element_id.isEmpty()) { + reader->skipCurrentElement(); + } else { + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("track")) { + QString track_id; + XMLAttributeLoop(reader, attr) { + if (attr.name() == QStringLiteral("id")) { + track_id = attr.value().toString(); + break; + } + } + + if (track_id.isEmpty()) { + reader->skipCurrentElement(); + } else { + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("key")) { + NodeKeyframe *key = new NodeKeyframe(); + key->set_input(input_id); + key->set_element(element_id.toInt()); + key->set_track(track_id.toInt()); + + key->load(reader, n->GetInputDataType(input_id)); + + load_data.keyframes[node_id].append(key); + } else { + reader->skipCurrentElement(); + } + } + } + } else { + reader->skipCurrentElement(); + } + } + } + } else { + reader->skipCurrentElement(); + } + } + } + } else { + reader->skipCurrentElement(); + } + } + } + + delete n; + } else { + reader->skipCurrentElement(); + } } + } else { + reader->skipCurrentElement(); } break; } case kOnlyNodes: { - while (XMLReadNextStartElement(reader)) { - if (reader->name() == QStringLiteral("node")) { - QString id; + if (reader->name() == QStringLiteral("nodes")) { + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("node")) { + QString id; - XMLAttributeLoop(reader, attr) { - if (attr.name() == QStringLiteral("id")) { - id = attr.value().toString(); + XMLAttributeLoop(reader, attr) { + if (attr.name() == QStringLiteral("id")) { + id = attr.value().toString(); + } } - } - if (id.isEmpty()) { - qWarning() << "Failed to load node with empty ID"; - reader->skipCurrentElement(); + if (id.isEmpty()) { + qWarning() << "Failed to load node with empty ID"; + reader->skipCurrentElement(); + } else { + Node* node = NodeFactory::CreateFromID(id); + if (!node) { + qWarning() << "Failed to find node with ID" << id; + reader->skipCurrentElement(); + } else { + // Disable cache while node is being loaded (we'll re-enable it later) + node->SetCachesEnabled(false); + node->Load(reader, &project_data); + load_data.nodes.append(node); + } + } + } else if (reader->name() == QStringLiteral("properties")) { + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("node")) { + quintptr ptr = 0; + + XMLAttributeLoop(reader, attr) { + if (attr.name() == QStringLiteral("ptr")) { + ptr = attr.value().toULongLong(); + + // Only attribute we're looking for right now + break; + } + } + + if (ptr) { + QMap properties_for_node; + while (XMLReadNextStartElement(reader)) { + properties_for_node.insert(reader->name().toString(), reader->readElementText()); + } + properties.insert(ptr, properties_for_node); + } + } else { + reader->skipCurrentElement(); + } + } } else { - Node* node = NodeFactory::CreateFromID(id); - if (!node) { - qWarning() << "Failed to find node with ID" << id; - reader->skipCurrentElement(); - } else { - // Disable cache while node is being loaded (we'll re-enable it later) - node->SetCachesEnabled(false); - node->Load(reader, &project_data); - load_data.nodes.append(node); - } + reader->skipCurrentElement(); } - } else if (reader->name() == QStringLiteral("properties")) { - while (XMLReadNextStartElement(reader)) { - if (reader->name() == QStringLiteral("node")) { - quintptr ptr = 0; + } - XMLAttributeLoop(reader, attr) { - if (attr.name() == QStringLiteral("ptr")) { - ptr = attr.value().toULongLong(); + PostConnect(load_data.nodes, &project_data); - // Only attribute we're looking for right now - break; - } - } - - if (ptr) { - QMap properties_for_node; - while (XMLReadNextStartElement(reader)) { - properties_for_node.insert(reader->name().toString(), reader->readElementText()); - } - properties.insert(ptr, properties_for_node); - } - } else { - reader->skipCurrentElement(); - } + // Resolve serialized properties (if any) + for (auto it=properties.cbegin(); it!=properties.cend(); it++) { + Node *node = project_data.node_ptrs.value(it.key()); + if (node) { + load_data.properties.insert(node, it.value()); } - } else { - reader->skipCurrentElement(); } + } else { + reader->skipCurrentElement(); } - - PostConnect(load_data.nodes, &project_data); - - // Resolve serialized properties (if any) - for (auto it=properties.cbegin(); it!=properties.cend(); it++) { - Node *node = project_data.node_ptrs.value(it.key()); - if (node) { - load_data.properties.insert(node, it.value()); - } - } - break; } } @@ -332,13 +347,17 @@ void ProjectSerializer230220::Save(QXmlStreamWriter *writer, const SaveData &dat writer->writeEndElement(); // nodes } else if (Project *project = data.GetProject()) { + writer->writeStartElement(QStringLiteral("project")); + writer->writeStartElement(QStringLiteral("project")); project->Save(writer); - writer->writeEndElement(); + writer->writeEndElement(); // project writer->writeStartElement(QStringLiteral("layout")); data.GetLayout().toXml(writer); - writer->writeEndElement(); + writer->writeEndElement(); // layout + + writer->writeEndElement(); // project } else { qCritical() << "ProjectSerializer provided nothing to save"; } diff --git a/app/render/colorprocessor.cpp b/app/render/colorprocessor.cpp index 8cc4adb8d..8fe246ea1 100644 --- a/app/render/colorprocessor.cpp +++ b/app/render/colorprocessor.cpp @@ -28,8 +28,6 @@ namespace olive { ColorProcessor::ColorProcessor(ColorManager *config, const QString &input, const ColorTransform &transform, Direction direction) { - QMutexLocker locker(config->mutex()); - const QString& output = (transform.output().isEmpty()) ? config->GetDefaultDisplay() : transform.output(); if (transform.is_display()) { @@ -43,8 +41,6 @@ ColorProcessor::ColorProcessor(ColorManager *config, const QString &input, const display_transform->setView(view.toUtf8()); display_transform->setDirection(direction == kNormal ? OCIO::TRANSFORM_DIR_FORWARD : OCIO::TRANSFORM_DIR_INVERSE); - OCIO_SET_C_LOCALE_FOR_SCOPE; - if (transform.look().isEmpty()) { processor_ = config->GetConfig()->getProcessor(display_transform); } else { @@ -69,7 +65,6 @@ ColorProcessor::ColorProcessor(ColorManager *config, const QString &input, const } else { - OCIO_SET_C_LOCALE_FOR_SCOPE; try { if (direction == kNormal) { processor_ = config->GetConfig()->getProcessor(input.toUtf8(), output.toUtf8()); diff --git a/app/render/previewautocacher.cpp b/app/render/previewautocacher.cpp index 2abe537bd..3e349b34f 100644 --- a/app/render/previewautocacher.cpp +++ b/app/render/previewautocacher.cpp @@ -733,7 +733,7 @@ void PreviewAutoCacher::SetProject(Project *project) } // Find copied viewer node - copied_color_manager_ = copier_->GetCopy(project_->color_manager()); + copied_color_manager_ = copier_->GetCopiedProject()->color_manager(); SetRendersPaused(false); } diff --git a/app/render/projectcopier.h b/app/render/projectcopier.h index f1065cd05..727c62515 100644 --- a/app/render/projectcopier.h +++ b/app/render/projectcopier.h @@ -45,6 +45,8 @@ public: return static_cast(copy_map_.key(copy)); } + Project *GetCopiedProject() const { return copy_; } + const QHash &GetNodeMap() const { return copy_map_; } const JobTime &GetGraphChangeTime() const { return graph_changed_time_; } diff --git a/app/task/export/export.cpp b/app/task/export/export.cpp index 0ab71cc09..a171df1ce 100644 --- a/app/task/export/export.cpp +++ b/app/task/export/export.cpp @@ -34,7 +34,7 @@ ExportTask::ExportTask(ViewerOutput *viewer_node, copier_->SetProject(viewer_node->project()); set_viewer(copier_->GetCopy(viewer_node)); - color_manager_ = copier_->GetCopy(color_manager); + color_manager_ = copier_->GetCopiedProject()->color_manager(); // Adjust video params to have no divider VideoParams vp = viewer_node->GetVideoParams(); diff --git a/app/task/precache/precachetask.cpp b/app/task/precache/precachetask.cpp index 39b63c450..8357b5a7d 100644 --- a/app/task/precache/precachetask.cpp +++ b/app/task/precache/precachetask.cpp @@ -40,7 +40,6 @@ PreCacheTask::PreCacheTask(Footage *footage, int index, Sequence* sequence) viewer()->SetAudioParams(sequence->GetAudioParams()); // Copy project config nodes - Node::CopyInputs(footage->project()->color_manager(), project_->color_manager(), false); Project::CopySettings(footage->project(), project_); // Copy footage node so it can precache without any modifications from the user screwing it up diff --git a/app/widget/manageddisplay/manageddisplay.cpp b/app/widget/manageddisplay/manageddisplay.cpp index abbf0b223..d90a9d5fb 100644 --- a/app/widget/manageddisplay/manageddisplay.cpp +++ b/app/widget/manageddisplay/manageddisplay.cpp @@ -92,13 +92,15 @@ void ManagedDisplayWidget::ConnectColorManager(ColorManager *color_manager) } if (color_manager_ != nullptr) { - disconnect(color_manager_, &ColorManager::ValueChanged, this, &ManagedDisplayWidget::ColorManagerValueChanged); + disconnect(color_manager_, &ColorManager::ConfigChanged, this, &ManagedDisplayWidget::ColorConfigChanged); + disconnect(color_manager_, &ColorManager::ReferenceSpaceChanged, this, &ManagedDisplayWidget::ColorConfigChanged); } color_manager_ = color_manager; if (color_manager_ != nullptr) { - connect(color_manager_, &ColorManager::ValueChanged, this, &ManagedDisplayWidget::ColorManagerValueChanged); + connect(color_manager_, &ColorManager::ConfigChanged, this, &ManagedDisplayWidget::ColorConfigChanged); + connect(color_manager_, &ColorManager::ReferenceSpaceChanged, this, &ManagedDisplayWidget::ColorConfigChanged); } ColorConfigChanged(); @@ -416,13 +418,4 @@ void ManagedDisplayWidget::SetupColorProcessor() emit ColorProcessorChanged(color_service_); } -void ManagedDisplayWidget::ColorManagerValueChanged(const NodeInput &input, const TimeRange &range) -{ - Q_UNUSED(range) - - if (input.input() == ColorManager::kConfigFilenameIn || input.input() == ColorManager::kReferenceSpaceIn) { - ColorConfigChanged(); - } -} - } diff --git a/app/widget/manageddisplay/manageddisplay.h b/app/widget/manageddisplay/manageddisplay.h index 5dceb3fc1..bbebbd339 100644 --- a/app/widget/manageddisplay/manageddisplay.h +++ b/app/widget/manageddisplay/manageddisplay.h @@ -286,8 +286,6 @@ private slots: */ void ColorConfigChanged(); - void ColorManagerValueChanged(const NodeInput &input, const TimeRange &range); - /** * @brief The default context menu shown */