/*** Olive - Non-Linear Video Editor Copyright (C) 2022 Olive Team Modifications Copyright (C) 2025 mikesolar 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 . ***/ #include "factory.h" #include #include "audio/pan/pan.h" #include "audio/volume/volume.h" #include "block/clip/clip.h" #include "block/gap/gap.h" #include "block/subtitle/subtitle.h" #include "block/transition/crossdissolve/crossdissolvetransition.h" #include "block/transition/diptocolor/diptocolortransition.h" #include "color/displaytransform/displaytransform.h" #include "color/ociogradingtransformlinear/ociogradingtransformlinear.h" #include "color/ociogradingtransformlog/ociogradingtransformlog.h" #include "color/ociolut/ociolut.h" #include "color/threewaycolor/threewaycolor.h" #include "color/whitebalance/whitebalance.h" #include "common/current.h" #include "distort/cornerpin/cornerpindistortnode.h" #include "distort/crop/cropdistortnode.h" #include "distort/flip/flipdistortnode.h" #include "distort/mask/mask.h" #include "distort/ripple/rippledistortnode.h" #include "distort/swirl/swirldistortnode.h" #include "distort/tile/tiledistortnode.h" #include "distort/transform/transformdistortnode.h" #include "distort/wave/wavedistortnode.h" #include "effect/opacity/opacityeffect.h" #include "filter/blur/blur.h" #include "filter/dropshadow/dropshadowfilter.h" #include "filter/mosaic/mosaicfilternode.h" #include "filter/stroke/stroke.h" #include "generator/matrix/matrix.h" #include "generator/noise/noise.h" #include "generator/polygon/polygon.h" #include "generator/shape/shapenode.h" #include "generator/solid/solid.h" #include "generator/text/textv1.h" #include "generator/text/textv2.h" #include "generator/text/textv3.h" #include "input/multicam/multicamnode.h" #include "input/time/timeinput.h" #include "input/value/valuenode.h" #include "keying/chromakey/chromakey.h" #include "keying/colordifferencekey/colordifferencekey.h" #include "keying/despill/despill.h" #include "math/math/math.h" #include "math/merge/merge.h" #include "math/trigonometry/trigonometry.h" #include "output/track/track.h" #include "output/viewer/viewer.h" #include "pluginSupport/olivehost.h" #include "plugins/plugin.h" #include "project/folder/folder.h" #include "project/footage/footage.h" #include "project/sequence/sequence.h" #include "time/timeformat/timeformat.h" #include "time/timeoffset/timeoffsetnode.h" #include "time/timeremap/timeremap.h" namespace olive { QList NodeFactory::library; void NodeFactory::initialize() { destroy(); // Add internal types for (int i = 0; i < k_internal_node_count; i++) { Node *created_node = create_from_factory_index(static_cast(i)); library.append(created_node); } register_plugin_nodes(); } void NodeFactory::destroy() { qDeleteAll(library); library.clear(); } QString NodeFactory::get_name_from_id(const QString &id) { if (!id.isEmpty()) { foreach (Node *n, library) { if (n->id() == id) { return n->name(); } } } return QString(); } Node *NodeFactory::create_from_id(const QString &id) { QString resolved_id = id; // Node IDs renamed after older project files were written static const QHash k_legacy_i_ds = { { QStringLiteral("org.oliveeditor.Olive.flip"), QStringLiteral("org.olivevideoeditor.Olive.flip") }, { QStringLiteral("org.oliveeditor.Olive.ripple"), QStringLiteral("org.olivevideoeditor.Olive.ripple") }, { QStringLiteral("org.oliveeditor.Olive.swirl"), QStringLiteral("org.olivevideoeditor.Olive.swirl") }, { QStringLiteral("org.oliveeditor.Olive.tile"), QStringLiteral("org.olivevideoeditor.Olive.tile") }, { QStringLiteral("org.oliveeditor.Olive.wave"), QStringLiteral("org.olivevideoeditor.Olive.wave") }, }; resolved_id = k_legacy_i_ds.value(id, id); foreach (Node *n, library) { if (n->id() == resolved_id) { return n->copy(); } } return nullptr; } void NodeFactory::register_plugin_nodes() { 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(); if (contexts.empty()) { qWarning() << "Skipping OFX plugin with no contexts:" << plugin_id; continue; } std::string context = kOfxImageEffectContextFilter; if (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::create_from_factory_index(const NodeFactory::InternalID &id) { switch (id) { case k_clip_block: return new ClipBlock(); case k_gap_block: return new GapBlock(); case k_polygon_generator: return new PolygonGenerator(); case k_matrix_generator: return new MatrixGenerator(); case k_transform_distort: return new TransformDistortNode(); case k_track_output: return new Track(); case k_viewer_output: return new ViewerOutput(); case k_audio_volume: return new VolumeNode(); case k_audio_panning: return new PanNode(); case k_math: return new MathNode(); case k_trigonometry: return new TrigonometryNode(); case k_time: return new TimeInput(); case k_blur_filter: return new BlurFilterNode(); case k_solid_generator: return new SolidGenerator(); case k_merge: return new MergeNode(); case k_stroke_filter: return new StrokeFilterNode(); case k_text_generator_v1: return new TextGeneratorV1(); case k_text_generator_v2: return new TextGeneratorV2(); case k_text_generator_v3: return new TextGeneratorV3(); case k_cross_dissolve_transition: return new CrossDissolveTransition(); case k_dip_to_color_transition: return new DipToColorTransition(); case k_mosaic_filter: return new MosaicFilterNode(); case k_crop_distort: return new CropDistortNode(); case k_project_footage: return new Footage(); case k_project_folder: return new Folder(); case k_project_sequence: return new Sequence(); case k_value_node: return new ValueNode(); case k_time_remap_node: return new TimeRemapNode(); case k_subtitle_block: return new SubtitleBlock(); case k_shape_generator: return new ShapeNode(); case k_color_difference_key_keying: return new ColorDifferenceKeyNode(); case k_despill_keying: return new DespillNode(); case k_group_node: return new NodeGroup(); case k_opacity_effect: return new OpacityEffect(); case k_flip_distort: return new FlipDistortNode(); case k_noise_generator: return new NoiseGeneratorNode(); case k_time_offset_node: return new TimeOffsetNode(); case k_corner_pin_distort: return new CornerPinDistortNode(); case k_display_transform: return new DisplayTransformNode(); case k_ocio_grading_transform_linear: return new OCIOGradingTransformLinearNode(); case k_ocio_grading_transform_log: return new OCIOGradingTransformLogNode(); case k_white_balance: return new WhiteBalanceNode(); case k_ocio_lut: return new OCIOLutNode(); case k_three_way_color: return new ThreeWayColorNode(); case k_chroma_key: return new ChromaKeyNode(); case k_mask_distort: return new MaskDistortNode(); case k_drop_shadow_filter: return new DropShadowFilter(); case k_time_format: return new TimeFormatNode(); case k_wave_distort: return new WaveDistortNode(); case k_tile_distort: return new TileDistortNode(); case k_swirl_distort: return new SwirlDistortNode(); case k_ripple_distort: return new RippleDistortNode(); case k_multicam_node: return new MultiCamNode(); case k_internal_node_count: break; } return nullptr; } }