Search code examples
c++nuke

Write data to selected mask


I try write to the selected mask, but it's doesn't work.

class IdMaskV1 : public Iop
{
public:

    IdMaskV1(Node* node) : Iop(node),
        aaIndexFile(0)
    {
        mChannelSet = Mask_RGBA;
    }

    ~IdMaskV1() {}

    //int maximum_inputs() const { return 1; }
    //int minimum_inputs() const { return 1; }

    virtual void knobs(Knob_Callback);
    void _validate(bool);
    void in_channels(int input_number, ChannelSet& channels) const;
    void _request(int x, int y, int r, int t, ChannelMask channels, int count);
    void engine(int y, int x, int r, ChannelMask channels, Row& outRow);


    const char* Class() const { return CLASS; }
    const char* node_help() const { return HELP; }

private:
    static const Iop::Description description;
    static const char* const CLASS;
    static const char* const HELP;
    ChannelSet mChannelSet;
};


static Iop* IdMaskV1Create(Node* node)
{
    return new IdMaskV1(node);
}

const Iop::Description IdMaskV1::description(CLASS, "Examples/IdMaskV1", IdMaskV1Create);
const char* const IdMaskV1::CLASS = "IdMaskV1";
const char* const IdMaskV1::HELP = "Example Plugin";

void IdMaskV1::_validate(bool for_real)
{
    copy_info();
    set_out_channels(mChannelSet);
    info_.turn_on(mChannelSet);
}

void IdMaskV1::in_channels(int input_number, ChannelSet& channels) const
{
    /*
    // Must turn on the other color channels if any color channels are requested:
    foreach(z, channels) {
        if (colourIndex(z) <= 3) { // it is red, green, or blue
            if (!(mChannelSet & z)) { // save some time if we already turned this on
                mChannelSet.addBrothers(z, 3); // add all three to the "done" set
            }
        }
    }*/
    //channels += mChannelSet; // add the colors to the channels we need
}

void IdMaskV1::_request(int x, int y, int r, int t, ChannelMask channels, int count)
{
    input(0)->request(x, y, r, t, ChannelMask(channels), count);
}


void IdMaskV1::engine(int y, int x, int r, ChannelMask channels, Row& outRow)
{

    ChannelMask mask(channels);

    if (aborted()) {
        std::cerr << "Aborted!";
        return;
    }

    Row inputRow(x, r);
    inputRow.get(input0(), y, x, r, mask);

    foreach(channel, mask) {
        Channel ch = brother(channel, colourIndex(channel));
        mChannelSet += ch;
    }

    for (int curX = x; curX < r; curX++) {

        foreach(channel, mChannelSet) {
            float value = 0;

                        // some process. In RGB i write 0.f, to A i write mask;

            outRow.writable(channel)[curX] = value;
        }
    }
}


void IdMaskV1::knobs(Knob_Callback f)
{
    ...
    ChannelMask_knob(f, &mChannelSet, 1, "channels");
}

For process i created 'other.test'. In Knob i chose channel rgba(or custom: 'test') and custom mask: 'other.test'

I wait for result in 'other.test', but result i see in rgba | rgba.alpha | A :\

Update

new attempt:

#include "DDImage/Iop.h"
#include "DDImage/Row.h"
#include "DDImage/Knobs.h"
#include "DDImage/Tile.h"

using namespace DD::Image;
using namespace std;

class IdMaskV1 : public Iop
{
public:

    IdMaskV1(Node* node) : Iop(node)
    {

    }

    ~IdMaskV1() {}

    virtual void knobs(Knob_Callback);
    void _validate(bool);
    void _request(int x, int y, int r, int t, ChannelMask channels, int count);
    void engine(int y, int x, int r, ChannelMask channels, Row& outRow);

    const char* Class() const { return CLASS; }
    const char* node_help() const { return HELP; }

private:
    static const Iop::Description description;
    static const char* const CLASS;
    static const char* const HELP;
    Channel mMaskChan;
};


static Iop* IdMaskV1Create(Node* node)
{
    return new IdMaskV1(node);
}

const Iop::Description IdMaskV1::description(CLASS, "Examples/IdMaskV1", IdMaskV1Create);
const char* const IdMaskV1::CLASS = "IdMaskV1";
const char* const IdMaskV1::HELP = "Example Plugin";

void IdMaskV1::_validate(bool for_real)
{
    copy_info();
    set_out_channels(mMaskChan);
    info_.turn_on(mMaskChan);
}

void IdMaskV1::_request(int x, int y, int r, int t, ChannelMask channels, int count)
{
    input(0)->request(x, y, r, t, channels, count);
}


void IdMaskV1::engine(int y, int x, int r, ChannelMask channels, Row& outRow)
{
    if (aborted()) {
        std::cerr << "Aborted!";
        return;
    }
    ChannelSet unchanged(channels);

    if (unchanged & mMaskChan) {
        unchanged -= mMaskChan;

        static float value = 0.1678f;

        float* out = outRow.writable(mMaskChan) + x;
        const float* END = outRow[mMaskChan] + r;
        while (out < END)
            *out++ = value;
    }

    if (unchanged)
        input0().get(y, x, r, unchanged, outRow);
}

void IdMaskV1::knobs(Knob_Callback f)
{
    Channel_knob(f, &mMaskChan, 1, "channels");
}

does't work :\

Screen from Nuke: enter image description here


Solution

  • Usually, you would use a ChannelSet_knob (or one if its variations) if you wanted to perform the same operation on all of the channels the user specifies. However, it can be tricky to determine whether a given channel in the knob's ChannelSet is actually the channel being specified in the mask pulldown on the knob, since some of the other channels can be disabled.

    Thus, if you want to write specific data to one specific channel, it would be much simpler to use a Channel_knob, and to just present and operate on a single channel internally.

    In that case, an engine() implementation might look like this:

    void IdMaskV1::engine(int y, int x, int r, ChannelMask channels, Row& outRow)
    {
        ChannelSet unchanged(channels);
    
        // mMaskChan is a `Channel`, and is the private knob storage for a `Channel_knob`
        if (unchanged & mMaskChan) {
            unchanged -= mMaskChan;
    
            static float value = 0.1678f;  // Whatever value or data you want
    
            float* OUT = outRow.writable(mMaskChan) + x;
            const float* END = outRow[mMaskChan] + r;
            while (OUT < END)
                *OUT++ = value;
        }
    
        if (unchanged)
            input0().get(y, x, r, unchanged, outRow);
    }
    

    You would also need to modify your _validate method to call set_out_channels and info_.turn_on on mMaskChan instead of mChannelSet.

    Hope this helps.