/* 
 CutrCullByThreshold.cpp
 Generated by Cutter from:
     "/Users/malcolmkesson/Documents/maya/rfm_scripts/nodes/Args/CutrCullByThreshold.args"
 at 6.31:2pm 8.14.2018
 For use with RPS 22.
*/
#include <RixPattern.h> 
#include <RixShadingUtils.h>
//#include <RixInterfaces.h>
//#include <RixShading.h>
#include <RixPredefinedStrings.hpp>
#include <sstream>
#include <string>
  
class CutrCullByThreshold : public RixPattern {
public:
  
    CutrCullByThreshold();
    virtual ~CutrCullByThreshold() { }
    virtual int Init(RixContext &ctx, RtUString pluginpath);
    virtual RixSCParamInfo const *GetParamTable();
    virtual void Synchronize(RixContext &ctx, RixSCSyncMsg sync_msg,
                            RixParameterList const *plist) { }
    virtual int CreateInstanceData(RixContext &ctx, RtUString const str,
                            RixParameterList const *plist, InstanceData *data)
            {
            return -1;
            }
    virtual void Finalize(RixContext &) { }
    virtual int ComputeOutputParams(RixShadingContext const *ctx,
                                    RtInt *noutputs, 
                                    OutputSpec **outputs,
                                    RtPointer instanceData,
                                    RixSCParamInfo const *ignored);
    virtual bool Bake2dOutput(RixBakeContext const *ctx, Bake2dSpec &spec, RtPointer ptr) { return false; }
    virtual bool Bake3dOutput(RixBakeContext const *ctx, Bake3dSpec &spec, RtPointer ptr) { return false; }
    private:
        RixMessages *m_msg;
        RixShadeFunctions *m_shd;  // Shading functions in RixInterfaces.h
        RtFloat const m_threshold;
        RtUString m_fullAttrName;
    };
  
CutrCullByThreshold::CutrCullByThreshold():
    m_msg(NULL),
    m_shd(NULL),
    m_threshold(1)
    { }
  
int CutrCullByThreshold::Init(RixContext &ctx, RtUString const pluginpath) {
    m_msg = (RixMessages*)ctx.GetRixInterface(k_RixMessages);
    m_shd = (RixShadeFunctions*)ctx.GetRixInterface(k_RixShadeFunctions);
    return (!m_msg) ? 1 : 0;
    }
  
RixSCParamInfo const *CutrCullByThreshold::GetParamTable() {
    static RixSCParamInfo s_ptable[] = {
        // Outputs
        RixSCParamInfo(RtUString("resultMask"), k_RixSCFloat, k_RixSCOutput),
        RixSCParamInfo(RtUString("resultF"), k_RixSCFloat, k_RixSCOutput),
        // Inputs
        RixSCParamInfo(RtUString("attrname"), k_RixSCString),
        RixSCParamInfo(RtUString("threshold"), k_RixSCFloat),
        RixSCParamInfo() // end of table
        };
    return &s_ptable[0];
    }
  
enum paramIndex {
    k_resultMask = 0,
    k_resultF,
    k_attrname,
    k_threshold
    };
    
int CutrCullByThreshold::ComputeOutputParams(RixShadingContext const *ctx,
                                RtInt *noutputs, 
                                OutputSpec **outputs,
                                RtPointer instanceData,
                                RixSCParamInfo const *ignored) {
  
    // Uncomment the next three lines if a rib Attribute will be queried. Note
    // that Rib Options should be queried in the init() method - not here!
    RixRenderState *rstate = (RixRenderState*)ctx->GetRixInterface(k_RixRenderState);
    RixRenderState::Type attrType;
    RtInt attrNumValues, err;
  
    // OUTPUTS BEGIN____________________________________
    // Allocate memory for the OutputSpec data structure.
    RixShadingContext::Allocator pool(ctx);
    OutputSpec *outSpec = pool.AllocForPattern<OutputSpec>(2);
    *outputs = outSpec;
  
    // Allocate memory for each output.
    RtFloat    *resultMask = pool.AllocForPattern<RtFloat>(ctx->numPts);
    RtFloat    *resultF = pool.AllocForPattern<RtFloat>(ctx->numPts);
  
    // Connect the output(s) to the OutputSpec.
    *noutputs = 2;
    outSpec[0].paramId = k_resultMask;
    outSpec[0].detail = k_RixSCVarying;
    outSpec[0].value = resultMask;
    outSpec[1].paramId = k_resultF;
    outSpec[1].detail = k_RixSCVarying;
    outSpec[1].value = resultF;
  
    // INPUTS BEGIN____________________________________
    bool varying = true;
    RtUString const *attrnamePtr = NULL;
    RtFloat const *threshold;
    ctx->EvalParam(k_attrname, -1, &attrnamePtr,(RtUString*)&Rix::k_empty);
    ctx->EvalParam(k_threshold, -1, &threshold, &m_threshold, varying);
  
    RtFloat attrValue = 1.0;    
    if(attrnamePtr->Length() == 0)
        attrValue = 1.0;
    else
        {
        if(m_fullAttrName.Empty()) {
            std::stringstream ss;
            ss << "user:" << attrnamePtr->CStr();
            m_fullAttrName = RtUString(ss.str().c_str());
            //m_msg->WarningAlways("initialized %s\n", m_fullAttrName.CStr());
            }
        err = rstate->GetAttribute(m_fullAttrName, &attrValue, sizeof(RtFloat),
                                           &attrType, &attrNumValues);
        if(err != 0) {
            attrValue = 1.0;
            m_msg->Warning("Cannot find attribute %s\n", m_fullAttrName.CStr());
            }
        }
    // Assign values to the output(s).
    for(int i = 0; i < ctx->numPts; i++) {
        resultF[i] = attrValue;
        if(threshold[i] > attrValue)
            resultMask[i] = 1;
        else
            resultMask[i] = 0;
        }
    return 0;
    }
RIX_PATTERNCREATE {
    return new CutrCullByThreshold();
    }
RIX_PATTERNDESTROY {
    delete((CutrCullByThreshold*)pattern);
    }