/* 
 CutrColorByRayHit.cpp
 Generated by Cutter from:
     "/home/mkesson/maya/projects/RfM_ris/Args/CutrColorByRayHit.args"
 at 1.18:18pm 5.23.2017
*/
#include <RixPattern.h> 
#include <RixShadingUtils.h>
#include <RixShading.h>
#include <RixColorUtils.h>
#include <cstring>
  
class CutrColorByRayHit : public RixPattern {
public:
  
    CutrColorByRayHit();
    virtual ~CutrColorByRayHit() { }
    virtual int Init(RixContext &, char const *pluginpath);
    virtual RixSCParamInfo const *GetParamTable();
    virtual void Finalize(RixContext &) { }
    virtual int ComputeOutputParams(RixShadingContext const *ctx,
                                    RtInt *noutputs, 
                                    OutputSpec **outputs,
                                    RtConstPointer instanceData,
                                    RixSCParamInfo const *ignored);
    private:
        RixMessages *m_msg;
        RixShadeFunctions *m_shd;  // Shading functions in RixInterfaces.h
        RtColorRGB const m_incolor;
        RtInt const m_action;
        RtColorRGB const m_alternative;
        RtInt const m_passthrough;
    };
  
CutrColorByRayHit::CutrColorByRayHit():
    m_msg(NULL),
    m_shd(NULL),
    m_incolor(1,1,0),
    m_action(0),
    m_alternative(1,0,0),
    m_passthrough(0)
    { }
  
int CutrColorByRayHit::Init(RixContext &ctx, char const *pluginpath) {
    m_msg = (RixMessages*)ctx.GetRixInterface(k_RixMessages);
    m_shd = (RixShadeFunctions*)ctx.GetRixInterface(k_RixShadeFunctions);
  
    // Uncomment the next three lines if a rib Option will be queried.
    //RixRenderState *rstate = (RixRenderState*)ctx.GetRixInterface(k_RixRenderState);
    //RixRenderState::Type optType;
    //RtInt optNumValues, err;
    // Example of using messaging,
    //    m_msg->Info("%f\n", a_float_value);
    return (!m_msg) ? 1 : 0;
    }
  
RixSCParamInfo const *CutrColorByRayHit::GetParamTable() {
    static RixSCParamInfo s_ptable[] = {
        // Outputs
        RixSCParamInfo("resultRGB", k_RixSCColor, k_RixSCOutput),
        RixSCParamInfo("resultMask", k_RixSCFloat, k_RixSCOutput),
        RixSCParamInfo("resultInvertedMask", k_RixSCFloat, k_RixSCOutput),
        // Inputs
        RixSCParamInfo("incolor", k_RixSCColor),
        RixSCParamInfo("action", k_RixSCInteger),
        RixSCParamInfo("alternative", k_RixSCColor),
        RixSCParamInfo("passthrough", k_RixSCInteger),
        RixSCParamInfo() // end of table
        };
    return &s_ptable[0];
    }
  
enum paramIndex {
    k_resultRGB = 0,
    k_resultMask,
    k_resultInvertedMask,
    k_incolor,
    k_action,
    k_alternative,
    k_passthrough
    };
    
int CutrColorByRayHit::ComputeOutputParams(RixShadingContext const *ctx,
                                RtInt *noutputs, 
                                OutputSpec **outputs,
                                RtConstPointer instanceData,
                                RixSCParamInfo const *ignored) {
    // OUTPUTS BEGIN____________________________________
    // Allocate memory for the OutputSpec data structure.
    RixShadingContext::Allocator pool(ctx);
    OutputSpec *outSpec = pool.AllocForPattern<OutputSpec>(3);
    *outputs = outSpec;
  
    // Allocate memory for each output.
    RtColorRGB    *resultRGB = pool.AllocForPattern<RtColorRGB>(ctx->numPts);
    RtFloat          *resultMask = pool.AllocForPattern<RtFloat>(ctx->numPts);
    RtFloat          *resultInvertedMask = pool.AllocForPattern<RtFloat>(ctx->numPts);
    // Connect the output(s) to the OutputSpec.
    *noutputs = 3;
    outSpec[0].paramId = k_resultRGB;
    outSpec[0].detail = k_RixSCVarying;
    outSpec[0].value = resultRGB;
    outSpec[1].paramId = k_resultMask;
    outSpec[1].detail = k_RixSCVarying;
    outSpec[1].value = resultMask;
    outSpec[2].paramId = k_resultInvertedMask;
    outSpec[2].detail = k_RixSCVarying;
    outSpec[2].value = resultInvertedMask;
          
    // INPUTS BEGIN____________________________________
    bool varying = true;
    bool uniform = false;
    // Declare a pointer for each input then obtain their values
    // using EvalParam().
    RtColorRGB const *incolor;
    RtInt const *actionPtr;
    RtColorRGB const *alternative;
    RtInt const *passthroughPtr;
    ctx->EvalParam(k_incolor, -1, &incolor, &m_incolor, varying);
    ctx->EvalParam(k_action, -1, &actionPtr, &m_action, uniform);
    ctx->EvalParam(k_alternative, -1, &alternative, &m_alternative, varying);
    ctx->EvalParam(k_passthrough, -1, &passthroughPtr, &m_passthrough, uniform);
    int passthrough = *passthroughPtr;
    int action = *actionPtr;
    
    // Assign values to the output(s).
    for(int i = 0; i < ctx->numPts; i++) {
        
        if(ctx->scTraits.primaryHit) {
            resultMask[i] = 1.0;
            resultInvertedMask[i] = 0.0;
            }
        else
            {
            resultMask[i] = 0.0;
            resultInvertedMask[i] = 1.0;
            }
        
        // Note the testing of "primaryHit"
        if(ctx->scTraits.primaryHit || passthrough) {
            resultRGB[i] = incolor[i];
            }
        else if(action == 0) {
            RtColorRGB  hsv;
            RixRgbToHsv(incolor[i], hsv);
            hsv[0] += 0.5;
            RixHsvToRgb(hsv, resultRGB[i]);
            }
        else if(action == 1) {
            RtColorRGB  hsv;
            RixRgbToHsv(incolor[i], hsv);
            hsv[1] = 0.0;
            RixHsvToRgb(hsv, resultRGB[i]);
            }
        else if(action == 2) {
            RtColorRGB  hsv;
            RixRgbToHsv(incolor[i], hsv);
            resultRGB[i].r = 1.0 - hsv[2];
            resultRGB[i].g = 1.0 - hsv[2];
            resultRGB[i].b = 1.0 - hsv[2];
            }
        else
            resultRGB[i] = alternative[i]; 
         
        }
    return 0;
    }
RIX_PATTERNCREATE {
    return new CutrColorByRayHit();
    }
RIX_PATTERNDESTROY {
    delete((CutrColorByRayHit*)pattern);
    }