// Copyright (c) 2021 The Foundry Visionmongers Ltd. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // * Neither the name of Foundry nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // This work is a C++ implementation compatible with version 1.2.8 of the Python-based Nuke gizmo // authored at Psyop by Jonah Friedman and Andy Jones (see https://github.com/Psyop/Cryptomatte). #ifndef CRYPTOMATTE_PLUGIN_H #define CRYPTOMATTE_PLUGIN_H #include "CryptomatteUtils.h" #include "CryptomattePickingManager.h" #include "DDImage/Enumeration_KnobI.h" #include "DDImage/Knobs.h" #include "DDImage/PixelIop.h" #include namespace Foundry { namespace NukePlugins { class CryptomattePlugin : public DD::Image::PixelIop, public Cryptomatte::PickingInterface { public: CryptomattePlugin(Node* node); static const Description kDescription; const char* Class() const override; const char* node_help() const override; void in_channels(int input, DD::Image::ChannelSet& mask) const override; void knobs(DD::Image::Knob_Callback callback) override; int knob_changed(DD::Image::Knob* k) override; bool updateUI(const DD::Image::OutputContext& context) override; // Picking interface functions Cryptomatte::CryptomatteObject getSelectedCryptomatteObject() const override; Cryptomatte::Manifest legacyGetManifestFromSelectedSource(const Cryptomatte::CryptomatteObject& cryptomatte); Cryptomatte::Manifest getManifestFromSelectedSource(const Cryptomatte::CryptomatteObject& cryptomatte) override; Cryptomatte::PickingInterface::PixelRowFetcher getCryptomattePixelRowFetcher() const override; protected: void _validate(bool forReal) override; void pixel_engine(const DD::Image::Row& in, int y, int x, int r, DD::Image::ChannelMask channels, DD::Image::Row& out) override; private: // Possible sources of the Cryptomatte Manifest enum class ManifestSource { MetadataEmbedded = 0, //< Manifest is embedded in the metadata. MetadataSidecar, //< Manifest source is a sidecar. The path to the file is provided in the metadata. MetadataAuto, //< Manifest source is a sidecar, if the path to the file is provided in the metadata; // otherwise embedded. CustomSidecar //< Manifest source is a sidecar. The path to the file is provided by the user // in the Sidecar Filepath knob. }; // Helper struct that contains Cryptomatte objects, fetched from the metadata, // the index of currently selected object, and the flag that determines whether the UI // is up to date in regards to fetched objects. struct CryptomatteContext { std::vector objects; size_t selectedIndex = 0; bool cryptoLayersUiInvalid = true; bool legacySidecarFilenameUiInvalid = true; bool manifestSourceUiInvalid = true; }; // Fetches available Cryptomatte objects from the metadata and determines the index // of selected object as well as whether the UI is up to date in regards to fetched objects. CryptomatteContext loadCryptomatteContext() const; void saveLastSelectedCryptoLayerName(const CryptomatteContext& objectsAndState); // Updates the value and the Enabled flag of the Sidecar Filepath knob, // depending on the selected manifest source. void updateSidecarFilepathKnob(const CryptomatteContext& cryptomatteContext); // Copies the filepath from the sidecar file knob to the custom sidecar knob, // if the selected Manifest Source is Custom Sidecar. void saveCustomSidecar(); // Updates manifest source knob and sidecar filepath knob in regards to the state of selected Cryptomatte Object. void legacyUpdateManifestSourceKnobs(const CryptomatteContext& cryptomatteContext); // Populates Cryptomatte Layers menu in regards to the state of selected Cryptomatte Object. void updateCryptoLayerChoiceKnob(const CryptomatteContext& objectsAndState); // Enables sidecar filepath knob, if the source of Manifest is sidecar file; otherwise disables it. void legacyUpdateSidecarFilenameKnobEnabled(); // Add obsolete knobs for backward compatibility & error handling when loading a Cryptomatte gizmo. void addObsoleteKnobs(DD::Image::Knob_Callback f) const; // Helper method that returns an interface to enumeration knob by the given name. // nullptr is returned if the enumeration knob isn't found. DD::Image::Enumeration_KnobI* enumerationKnobI(const char* name) const; // Gets the value determining whether the user changed the sidecar file path to a custom value. bool legacyGetManifestSourceModified() const; // Checks if the value in the sidecar filepath knob differs from the value in the metadata. // If it differs, set the manifest source modified knob. void legacyCheckManifestSourceModified(CryptomattePlugin::CryptomatteContext context); // Knob names static const char* kCryptoLayerChoiceKnob; static const char* kLegacyManifestSourceKnob; static const char* kManifestSourceKnob; static const char* const kManifestSourceOptions[]; static const char* kSidecarFilepathKnob; static const char* kCustomSidecarKnob; static const char* kMatteOutputKnob; static const char* kUnpremultiply; static const char* kRemoveChannelsKnob; static const char* kLegacyManifestSourceModifiedKnob; static const char* kLastSelectedCryptoLayerNameKnob; Cryptomatte::PickingManager _picker; // Index of user-selected cryptomatte that persists // in a collection of available cryptomattes int _selectedCryptomatteIndex = 0; // Menu items of the Cryptomatte Layers enumeration knob DD::Image::ENUM_LABELS _cryptoLayersMenu = nullptr; // Index of manifest source. int _manifestSourceIndex = static_cast(ManifestSource::MetadataAuto); int _legacyManifestSourceIndex = 0; // Path to the sidecar manifest file, either custom or from metadata, // displayed on the properties pannel. // // Note: The value is dynamic and depends on the state of Manifest Source enumeration knob. // It is used for displaying purposes and is not stored with the script. const char* _sidecarFilePath = nullptr; // Path to the custom sidecar manifest file, if the user provided any. std::string _customSidecar; // Determines if the output must be unpremultiplied by the input alpha bool _unpremultiplyEnabled = false; // User-selected Matte Out Channel DD::Image::Channel _matteOutChannel = DD::Image::Chan_Alpha; // Determines if all the channels except for RGB // and the Matte Output channel should be removed. bool _removeChannels = false; // Determines if the manifest source was modified by the user. // This flag keeps the sidecar file path knob from being automatically updated // when the sidecar filepath changes in the upstream metadata. bool _legacyManifestSourceModified = false; // Preserves the name of last user-selected cryptomatte. std::string _lastSelectedCryptoLayerName; // Dynamic values, updated by each _validate() call // Cryptomatte IDs, resolved from the user-selected Matte List std::set _resolvedIDs; // User-selected cryptomatte object Cryptomatte::CryptomatteObject _selectedCryptomatte; // Counter that determines how deep we are in the call stack of methods // that may modify the manifest source procedurally. // It's used to distinguish the user modifications from the procedural ones. int _legacyInsideManifestSourceProceduralModeficator = 0; }; } } #endif