From 003c3bb5be1ca415c0576415409e2ffaf2c56ae5 Mon Sep 17 00:00:00 2001 From: Mike Solar Date: Mon, 5 Jan 2026 02:25:13 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=83=A8=E5=88=86=E8=AF=AD?= =?UTF-8?q?=E6=B3=95=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/node/factory.cpp | 62 ++++++++++++++++---------- app/node/factory.h | 1 + app/node/project.cpp | 104 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+), 23 deletions(-) diff --git a/app/node/factory.cpp b/app/node/factory.cpp index 5debfb3f1..8dfddf721 100644 --- a/app/node/factory.cpp +++ b/app/node/factory.cpp @@ -89,29 +89,7 @@ void NodeFactory::Initialize() } olive::plugin::loadPlugins(QString()); - - for (auto plugin : OFX::Host::PluginCache::getPluginCache()->getPlugins()) { - auto *image_effect = - dynamic_cast(plugin); - if (!image_effect) { - continue; - } - - const auto &contexts = image_effect->getContexts(); - std::string context = kOfxImageEffectContextFilter; - if (!contexts.empty() && - contexts.find(kOfxImageEffectContextFilter) == contexts.end()) { - context = *contexts.begin(); - } - - auto *instance = image_effect->createInstance(context, nullptr); - if (!instance) { - continue; - } - - plugin::PluginNode *plugin_node = new plugin::PluginNode(instance); - library_.append(plugin_node); - } + RegisterPluginNodes(); } @@ -238,6 +216,44 @@ Node *NodeFactory::CreateFromID(const QString &id) return nullptr; } +void NodeFactory::RegisterPluginNodes() +{ + QSet existing_ids; + for (Node *node : library_) { + existing_ids.insert(node->id()); + } + + for (auto plugin : OFX::Host::PluginCache::getPluginCache()->getPlugins()) { + auto *image_effect = + dynamic_cast(plugin); + if (!image_effect) { + continue; + } + + const QString plugin_id = QString::fromStdString( + image_effect->getIdentifier()); + if (existing_ids.contains(plugin_id)) { + continue; + } + + const auto &contexts = image_effect->getContexts(); + std::string context = kOfxImageEffectContextFilter; + if (!contexts.empty() && + contexts.find(kOfxImageEffectContextFilter) == contexts.end()) { + context = *contexts.begin(); + } + + auto *instance = image_effect->createInstance(context, nullptr); + if (!instance) { + continue; + } + + plugin::PluginNode *plugin_node = new plugin::PluginNode(instance); + library_.append(plugin_node); + existing_ids.insert(plugin_id); + } +} + Node *NodeFactory::CreateFromFactoryIndex(const NodeFactory::InternalID &id) { switch (id) { diff --git a/app/node/factory.h b/app/node/factory.h index 9131a9676..3dc05adb4 100644 --- a/app/node/factory.h +++ b/app/node/factory.h @@ -102,6 +102,7 @@ public: static QString GetNameFromID(const QString &id); static Node *CreateFromID(const QString &id); + static void RegisterPluginNodes(); static Node *CreateFromFactoryIndex(const InternalID &id); diff --git a/app/node/project.cpp b/app/node/project.cpp index 81dd1714f..71ddbef76 100644 --- a/app/node/project.cpp +++ b/app/node/project.cpp @@ -21,6 +21,7 @@ #include #include +#include "common/Current.h" #include "common/qtutils.h" #include "common/xmlutils.h" #include "core.h" @@ -28,6 +29,8 @@ #include "node/color/ociobase/ociobase.h" #include "node/factory.h" #include "node/serializeddata.h" +#include "pluginSupport/OliveHost.h" +#include "ofxhPluginCache.h" #include "render/diskmanager.h" #include "window/mainwindow/mainwindow.h" @@ -95,11 +98,53 @@ void Project::Clear() SerializedData Project::Load(QXmlStreamReader *reader) { SerializedData data; + QSet plugin_paths; while (XMLReadNextStartElement(reader)) { if (reader->name() == QStringLiteral("uuid")) { this->SetUuid(QUuid::fromString(reader->readElementText())); + } else if (reader->name() == QStringLiteral("plugins")) { + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("plugin")) { + QString bundle_path; + QString file_path; + XMLAttributeLoop(reader, attr) + { + if (attr.name() == QStringLiteral("bundle")) { + bundle_path = attr.value().toString(); + } else if (attr.name() == QStringLiteral("file")) { + file_path = attr.value().toString(); + } + } + + const QString path = bundle_path.isEmpty() + ? file_path + : bundle_path; + if (!path.isEmpty()) { + plugin_paths.insert(path); + } + + reader->skipCurrentElement(); + } else { + reader->skipCurrentElement(); + } + } + + if (!plugin_paths.isEmpty()) { + if (!Current::getInstance().pluginHost() || + !Current::getInstance().pluginCache()) { + plugin::loadPlugins(QString()); + } + + auto *cache = OFX::Host::PluginCache::getPluginCache(); + for (const QString &path : plugin_paths) { + cache->addFileToPath(path.toStdString(), true); + } + cache->scanPluginFiles(); + NodeFactory::RegisterPluginNodes(); + } + } else if (reader->name() == QStringLiteral("nodes")) { while (XMLReadNextStartElement(reader)) { if (reader->name() == QStringLiteral("node")) { @@ -171,6 +216,65 @@ void Project::Save(QXmlStreamWriter *writer) const writer->writeTextElement(QStringLiteral("uuid"), this->GetUuid().toString()); + QVector>> plugins_to_save; + { + QSet seen; + for (Node *node : this->nodes()) { + auto *plugin = node->getPlugin(); + if (!plugin) { + continue; + } + + const std::string id = plugin->getIdentifier(); + const int major = plugin->getVersionMajor(); + const int minor = plugin->getVersionMinor(); + QString bundle_path; + QString file_path; + if (auto *binary = plugin->getBinary()) { + bundle_path = QString::fromStdString(binary->getBundlePath()); + file_path = QString::fromStdString(binary->getFilePath()); + } + + const QString key = QStringLiteral("%1|%2|%3|%4|%5") + .arg(QString::fromStdString(id)) + .arg(major) + .arg(minor) + .arg(bundle_path) + .arg(file_path); + if (seen.contains(key)) { + continue; + } + seen.insert(key); + + QMap attrs; + attrs.insert(QStringLiteral("id"), + QString::fromStdString(id)); + attrs.insert(QStringLiteral("major"), QString::number(major)); + attrs.insert(QStringLiteral("minor"), QString::number(minor)); + if (!bundle_path.isEmpty()) { + attrs.insert(QStringLiteral("bundle"), bundle_path); + } + if (!file_path.isEmpty()) { + attrs.insert(QStringLiteral("file"), file_path); + } + + plugins_to_save.append({ QString::fromStdString(id), attrs }); + } + } + + if (!plugins_to_save.isEmpty()) { + writer->writeStartElement(QStringLiteral("plugins")); + for (const auto &entry : plugins_to_save) { + writer->writeStartElement(QStringLiteral("plugin")); + for (auto it = entry.second.cbegin(); + it != entry.second.cend(); ++it) { + writer->writeAttribute(it.key(), it.value()); + } + writer->writeEndElement(); + } + writer->writeEndElement(); + } + if (!this->nodes().isEmpty()) { writer->writeStartElement(QStringLiteral("nodes"));