#include "gpuCacheDrawOverride.h"
#include "gpuCacheConfig.h"
#include "gpuCacheShapeNode.h"
#include "gpuCacheDrawTraversal.h"
#include "gpuCacheFrustum.h"
#include "gpuCacheGLFT.h"
#include <maya/MAnimControl.h>
#include <maya/MDrawContext.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MGlobal.h>
#include <maya/MHWGeometryUtilities.h>
#include <maya/MStateManager.h>
#include <maya/MUserData.h>
#include <algorithm>
namespace {
using namespace GPUCache;
enum DepthOffsetType {
    kNoDepthOffset,
    kApplyDepthOffset,
    kNbDepthOffsetType
};
enum ColorType {
    kSubNodeColor,
    kDefaultColor,
    kBlackColor,
    kXrayColor,
    kXrayBlackColor,
    kNbColorType
};
enum NormalsType {
    kFrontNormals,
    kBackNormals,
    kNbNormalsType
};
enum FrontFaceType {
    kFrontClockwise,
    kFrontCounterClockwise,
    kNbFrontFaceType
};
enum TwoSidedLightingType {
    kTwoSidedLighting,
    kOneSidedLighting,
    kNbTwoSidedLightingType
};
{
    if (!blendState) {
    }
}
    const DepthOffsetType                       depthOffsetType)
{
    if (depthOffsetType == kApplyDepthOffset) {
    }
}
void setShadedRasterState(
    const DepthOffsetType                       depthOffsetType,
    const FrontFaceType                         frontFaceType)
{
        {NULL, NULL};
        {NULL, NULL};
        {NULL, NULL};
    if (!cullNoneRasterizerState[kNoDepthOffset]) {
        for (int dot = 0; dot < kNbDepthOffsetType; ++dot) {
            cullNoneRasterizerState[dot] = createShadedRasterState(
                stateMgr, MRasterizerState::kCullNone, DepthOffsetType(dot));
            cullFrontRasterizerState[dot] = createShadedRasterState(
                stateMgr, MRasterizerState::kCullFront, DepthOffsetType(dot));
            cullBackRasterizerState[dot] = createShadedRasterState(
                stateMgr, MRasterizerState::kCullBack, DepthOffsetType(dot));
        }
    }
    switch (cullMode) {
        case MRasterizerState::kCullNone:
                cullNoneRasterizerState[depthOffsetType]);
            break;
        case MRasterizerState::kCullFront:
                cullFrontRasterizerState[depthOffsetType]);
            break;
        case MRasterizerState::kCullBack:
                cullBackRasterizerState[depthOffsetType]);
            break;
        default: assert(0);
    }
    
    
    
    
    
    gGLFT->glFrontFace(frontFaceType == kFrontClockwise ? MGL_CW : MGL_CCW);
}
void setShadedSolidDepthState(
{
    if (!depthState) {
    }
}
void setShadedTwoSidedLightingState(
    const TwoSidedLightingType twoSidedLightingType)
{
    
    gGLFT->glLightModeli(MGL_LIGHT_MODEL_TWO_SIDE,
        twoSidedLightingType == kTwoSidedLighting ? 1 : 0);
}
void setShadedAlphaDepthState(
{
    if (!depthState) {
    }
}
void setWireframeState(
{
    {
        if (!blendState) {
        }
    }
    {
        if (!rasterizerState) {
        }
    }
    {
        if (!depthState) {
        }
    }
}
class TopLevelCullVisitor : public SubNodeVisitor
{
public:
    TopLevelCullVisitor(const Frustum& frustrum, double seconds)
        : fFrustum(frustrum),
          fSeconds(seconds),
          fIsCulled(true)
    {}
    bool isCulled() const { return fIsCulled; }
    virtual void visit(const XformData&   xform,
                       const SubNode&     subNode)
    {
        const boost::shared_ptr<const XformSample>& sample =
            xform.getSample(fSeconds);
        if (!sample) return;
        fIsCulled =
            fFrustum.test(sample->boundingBox()) == Frustum::kOutside;
    }
    virtual void visit(const ShapeData&   shape,
                       const SubNode&     subNode)
    {
        const boost::shared_ptr<const ShapeSample>& sample =
            shape.getSample(fSeconds);
        if (!sample) return;
        fIsCulled =
            fFrustum.test(sample->boundingBox()) == Frustum::kOutside;
    }
private:
    const Frustum&  fFrustum;
    const double    fSeconds;
    bool            fIsCulled;
};
class DrawShadedState : public DrawTraversalState
{
public:
    DrawShadedState(
        const Frustum&                          frustrum,
        const double                            seconds,
        const TransparentPruneType              transparentPrune,
        const DepthOffsetType                   depthOffsetType,
        const ColorType                         colorType,
        const MColor&                           defaultDiffuseColor,
 
        const NormalsType                       normalsType)
        : DrawTraversalState(frustrum, seconds, transparentPrune),
          fStateMgr(stateMgr),
          fCullMode(cullMode),
          fDepthOffsetType(depthOffsetType),
          fColorType(colorType),
          fDefaultDiffuseColor(defaultDiffuseColor),
          fNormalsType(normalsType)
    {}
    DepthOffsetType depthOffsetType() const     { return fDepthOffsetType; }
    ColorType       colorType() const           { return fColorType; }
    const MColor&   defaultDiffuseColor()
 const { 
return fDefaultDiffuseColor; }
 
    NormalsType     normalsType() const         { return fNormalsType; }
private:
    const DepthOffsetType                   fDepthOffsetType;
    const ColorType                         fColorType;
    const MColor                            fDefaultDiffuseColor;
 
    const NormalsType                       fNormalsType;
};
class DrawShadedTraversal
    : public DrawTraversal<DrawShadedTraversal, DrawShadedState>
{
public:
    typedef DrawTraversal<DrawShadedTraversal, DrawShadedState> BaseClass;
    DrawShadedTraversal(
        DrawShadedState&        state,
        bool                    isReflection,
        Frustum::ClippingResult parentClippingResult)
        : BaseClass(state, xform, isReflection, parentClippingResult)
    {}
    void draw(const boost::shared_ptr<const ShapeSample>& sample)
    {
        if (!sample->visibility()) return;
        gGLFT->glLoadMatrixd(xform().matrix[0]);
        if (sample->isBoundingBoxPlaceHolder()) {
            state().vboProxy().drawBoundingBox(sample, true);
            GlobalReaderCache::theCache().hintShapeReadOrder(subNode());
            return;
        }
        assert(sample->positions());
        assert(sample->normals());
        switch (state().colorType()) {
        case kSubNodeColor:
            diffuseColor = sample->diffuseColor();
            break;
        case kDefaultColor:
            
            diffuseColor = state().defaultDiffuseColor();
            break;
        case kBlackColor:
            
            diffuseColor = 
MColor(0.0f, 0.0f, 0.0f, sample->diffuseColor()[3]);
            break;
        case kXrayColor:
            
            diffuseColor = 
MColor(sample->diffuseColor()[0],
                                  sample->diffuseColor()[1],
                                  sample->diffuseColor()[2],
                                  sample->diffuseColor()[3] * 0.3f);
            break;
        case kXrayBlackColor:
            
            diffuseColor = 
MColor(0.0f, 0.0f, 0.0f, sample->diffuseColor()[3] * 0.3f);
            break;
        default:
            assert(0);
        }
        if (diffuseColor[3] <= 0.0 ||
            (diffuseColor[3] >= 1.0 &&
                state().transparentPrune() == DrawShadedState::kPruneOpaque) ||
            (diffuseColor[3] <  1.0 &&
                state().transparentPrune() == DrawShadedState::kPruneTransparent)) {
            return;
        }
        
        gGLFT->glColor4f(diffuseColor[0]*diffuseColor[3],
                         diffuseColor[1]*diffuseColor[3],
                         diffuseColor[2]*diffuseColor[3],
                         diffuseColor[3]);
        setShadedRasterState(state().stateManager(),
                             state().cullMode(),
                             state().depthOffsetType(),
                             isReflection() ?
                             kFrontClockwise : kFrontCounterClockwise);
        
        for (size_t groupId = 0; groupId < sample->numIndexGroups(); ++groupId ) {
            state().vboProxy().drawTriangles(
                sample, groupId,
                state().normalsType() == kFrontNormals ?
                VBOProxy::kFrontNormals : VBOProxy::kBackNormals,
                VBOProxy::kNoUVs);
        }
    }
};
class DrawWireframeState : public DrawTraversalState
{
public:
    DrawWireframeState(
        const Frustum&  frustrum,
        const double    seconds)
        : DrawTraversalState(frustrum, seconds, kPruneNone)
    {}
};
class DrawWireframeTraversal
    : public DrawTraversal<DrawWireframeTraversal, DrawWireframeState>
{
public:
    typedef DrawTraversal<DrawWireframeTraversal, DrawWireframeState> BaseClass;
    DrawWireframeTraversal(
        DrawWireframeState&     state,
        bool                    isReflection,
        Frustum::ClippingResult parentClippingResult)
        : BaseClass(state, xform, isReflection, parentClippingResult)
    {}
    void draw(const boost::shared_ptr<const ShapeSample>& sample)
    {
        if (!sample->visibility()) return;
        gGLFT->glLoadMatrixd(xform().matrix[0]);
        if (sample->isBoundingBoxPlaceHolder()) {
            state().vboProxy().drawBoundingBox(sample);
            GlobalReaderCache::theCache().hintShapeReadOrder(subNode());
            return;
        }
        assert(sample->positions());
        assert(sample->normals());
        state().vboProxy().drawWireframe(sample);
    }
};
}
namespace GPUCache {
class DrawOverride::UserData : 
public MUserData 
{
public:
    
    UserData(const ShapeNode* node)
          fShapeNode(node),
          fSeconds(0.0),
          fIsSelected(false)
    {
        fWireframeColor[0] = 1.0f;
        fWireframeColor[1] = 1.0f;
        fWireframeColor[2] = 1.0f;
    }
    void set(const double& seconds,
             bool          isSelected)
    {
        fSeconds = seconds;
        fWireframeColor[0] = wireframeColor[0];
        fWireframeColor[1] = wireframeColor[1];
        fWireframeColor[2] = wireframeColor[2];
        fIsSelected = isSelected;
    }
private:
    
    void drawShadedSampleGL(
        const Frustum&                              frustum,
        const DepthOffsetType                       depthOffsetType,
        const ColorType                             colorType,
        const MColor&                               defaultDiffuseColor,
 
        const NormalsType                           normalsType,
        const DrawShadedState::TransparentPruneType transparentPrune,
        const SubNode::Ptr&                         rootNode) const;
    void drawWireframeSampleGL(const Frustum&  frustum,
                               const SubNode::Ptr& rootNode) const;
    void drawBoundingBoxSampleGL(
const MMatrix&      xform,
 
                                 const SubNode::Ptr& rootNode) const;
    
    virtual ~UserData()    {}
    
    const ShapeNode* fShapeNode;
    double           fSeconds;
    GLfloat          fWireframeColor[3];
    bool             fIsSelected;
};
void DrawOverride::UserData::drawShadedSampleGL(
    const Frustum&                              frustum,
    const DepthOffsetType                       depthOffsetType,
    const ColorType                             colorType,
    const MColor&                               defaultDiffuseColor,
 
    const NormalsType                           normalsType,
    const DrawShadedState::TransparentPruneType transparentPrune,
    const SubNode::Ptr&                         rootNode) const
{
    DrawShadedState state(
        frustum, fSeconds, transparentPrune, stateMgr,
        cullMode, depthOffsetType, colorType,
        defaultDiffuseColor, normalsType);
    DrawShadedTraversal visitor(
        state, xform, xform.
det3x3() < 0.0, Frustum::kUnknown);
    rootNode->accept(visitor);
}
void DrawOverride::UserData::drawWireframeSampleGL(
    const Frustum&  frustum,
    const SubNode::Ptr& rootNode) const
{
    DrawWireframeState state(frustum, fSeconds);
    DrawWireframeTraversal visitor(state, xform, false, Frustum::kUnknown);
    rootNode->accept(visitor);
}
void DrawOverride::UserData::drawBoundingBoxSampleGL(
    const SubNode::Ptr& rootNode) const
{
    
    const SubNodeData::Ptr subNodeData = rootNode->getData();
    if (!subNodeData) return;
    const XformData::Ptr xformData =
        boost::dynamic_pointer_cast<const XformData>(subNodeData);
    if (xformData) {
        const boost::shared_ptr<const XformSample>& sample =
            xformData->getSample(fSeconds);
        if (!sample || !sample->visibility()) return;
        boundingBox = sample->boundingBox();
    }
    else {
        const ShapeData::Ptr shapeData =
            boost::dynamic_pointer_cast<const ShapeData>(subNodeData);
        if (shapeData) {
            const boost::shared_ptr<const ShapeSample>& sample =
                shapeData->getSample(fSeconds);
            if (!sample || !sample->visibility()) return;
            boundingBox = sample->boundingBox();
        }
    }
    
    gGLFT->glLoadMatrixd(xform.
matrix[0]);
    VBOProxy vboProxy;
    vboProxy.drawBoundingBox(boundingBox);
}
bool DrawOverride::UserData::setupLightingGL(
{
    
    
    const unsigned int nbLights =
    if (nbLights > 0) {
        
        
        gGLFT->glLoadMatrixd(worldToView.
matrix[0]);
        gGLFT->glEnable(MGL_LIGHTING);
        gGLFT->glColorMaterial(MGL_FRONT_AND_BACK, MGL_AMBIENT_AND_DIFFUSE);
        gGLFT->glEnable(MGL_COLOR_MATERIAL) ;
        gGLFT->glEnable(MGL_NORMALIZE) ;
        {
            const MGLfloat ambient[4]  = { 0.0f, 0.0f, 0.0f, 1.0f };
            const MGLfloat specular[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
            gGLFT->glMaterialfv(MGL_FRONT_AND_BACK, MGL_AMBIENT,  ambient);
            gGLFT->glMaterialfv(MGL_FRONT_AND_BACK, MGL_SPECULAR, specular);
            gGLFT->glLightModelfv(MGL_LIGHT_MODEL_AMBIENT, ambient);
            
            if (Config::emulateTwoSidedLighting()) {
                gGLFT->glLightModeli(MGL_LIGHT_MODEL_TWO_SIDE, 0);
            }
            else {
                gGLFT->glLightModeli(MGL_LIGHT_MODEL_TWO_SIDE, 1);
            }
        }
        for (unsigned int i=0; i<nbLights; ++i) {
            float intensity;
            bool hasDirection;
            bool hasPosition;
                i, positions, direction, intensity, color,
                hasDirection, hasPosition);
            
            
            
            
            
            
            
            
            if (hasDirection) {
                if (hasPosition) {
                    
                    position[0] = positions[0][0];
                    position[1] = positions[0][1];
                    position[2] = positions[0][2];
                    const MGLfloat ambient[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
                    const MGLfloat diffuse[4] = { intensity * color[0],
                                                  intensity * color[1],
                                                  intensity * color[2],
                                                  1.0f };
                    const MGLfloat pos[4] = { position[0],
                                              position[1],
                                              position[2],
                                              1.0f };
                    const MGLfloat dir[3] = { direction[0],
                                              direction[1],
                                              direction[2]};
                    gGLFT->glLightfv(MGL_LIGHT0+i, MGL_AMBIENT,  ambient);
                    gGLFT->glLightfv(MGL_LIGHT0+i, MGL_DIFFUSE,  diffuse);
                    gGLFT->glLightfv(MGL_LIGHT0+i, MGL_POSITION, pos);
                    gGLFT->glLightfv(MGL_LIGHT0+i, MGL_SPOT_DIRECTION, dir);
                    
                    gGLFT->glLightf(MGL_LIGHT0+i,  MGL_SPOT_EXPONENT, 0.0);
                    gGLFT->glLightf(MGL_LIGHT0+i,  MGL_SPOT_CUTOFF,  20.0);
                }
                else {
                    
                    const MGLfloat ambient[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
                    const MGLfloat diffuse[4] = { intensity * color[0],
                                                  intensity * color[1],
                                                  intensity * color[2],
                                                  1.0f };
                    const MGLfloat pos[4] = { -direction[0],
                                              -direction[1],
                                              -direction[2],
                                              0.0f };
                    gGLFT->glLightfv(MGL_LIGHT0+i, MGL_AMBIENT,  ambient);
                    gGLFT->glLightfv(MGL_LIGHT0+i, MGL_DIFFUSE,  diffuse);
                    gGLFT->glLightfv(MGL_LIGHT0+i, MGL_POSITION, pos);
                    gGLFT->glLightf(MGL_LIGHT0+i, MGL_SPOT_CUTOFF, 180.0);
                }
            }
            else if (hasPosition) {
                
                position[0] = positions[0][0];
                position[1] = positions[0][1];
                position[2] = positions[0][2];
                const MGLfloat ambient[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
                const MGLfloat diffuse[4] = { intensity * color[0],
                                              intensity * color[1],
                                              intensity * color[2],
                                              1.0f };
                const MGLfloat pos[4] = { position[0],
                                          position[1],
                                          position[2],
                                          1.0f };
                gGLFT->glLightfv(MGL_LIGHT0+i, MGL_AMBIENT,  ambient);
                gGLFT->glLightfv(MGL_LIGHT0+i, MGL_DIFFUSE,  diffuse);
                gGLFT->glLightfv(MGL_LIGHT0+i, MGL_POSITION, pos);
                gGLFT->glLightf(MGL_LIGHT0+i, MGL_SPOT_CUTOFF, 180.0);
            }
            else {
                
                const MGLfloat ambient[4] = { intensity * color[0],
                                              intensity * color[1],
                                              intensity * color[2],
                                              1.0f };
                const MGLfloat diffuse[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
                const MGLfloat pos[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
                gGLFT->glLightfv(MGL_LIGHT0+i, MGL_AMBIENT,  ambient);
                gGLFT->glLightfv(MGL_LIGHT0+i, MGL_DIFFUSE,  diffuse);
                gGLFT->glLightfv(MGL_LIGHT0+i, MGL_POSITION, pos);
                gGLFT->glLightf(MGL_LIGHT0+i, MGL_SPOT_CUTOFF, 180.0);
            }
            gGLFT->glEnable(MGL_LIGHT0+i);
        }
    }
    return nbLights > 0;
}
void DrawOverride::UserData::unsetLightingGL(
{
    
    
    const unsigned int nbLights =
    
    
    if (nbLights > 0) {
        for (unsigned int i=0; i<nbLights; ++i) {
            gGLFT->glDisable(MGL_LIGHT0+i);
            const MGLfloat ambient[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
            gGLFT->glLightfv(MGL_LIGHT0+i, MGL_AMBIENT,  ambient);
            if (i==0) {
                const MGLfloat diffuse[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
                gGLFT->glLightfv(MGL_LIGHT0+i, MGL_DIFFUSE,  diffuse);
                const MGLfloat spec[4]    = { 1.0f, 1.0f, 1.0f, 1.0f };
                gGLFT->glLightfv(MGL_LIGHT0+i, MGL_SPECULAR, spec);
            }
            else {
                const MGLfloat diffuse[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
                gGLFT->glLightfv(MGL_LIGHT0+i, MGL_DIFFUSE,  diffuse);
                const MGLfloat spec[4]    = { 0.0f, 0.0f, 0.0f, 1.0f };
                gGLFT->glLightfv(MGL_LIGHT0+i, MGL_SPECULAR, spec);
            }
            const MGLfloat pos[4]     = { 0.0f, 0.0f, 1.0f, 0.0f };
            gGLFT->glLightfv(MGL_LIGHT0+i, MGL_POSITION, pos);
            const MGLfloat dir[3]     = { 0.0f, 0.0f, -1.0f };
            gGLFT->glLightfv(MGL_LIGHT0+i, MGL_SPOT_DIRECTION, dir);
            gGLFT->glLightf(MGL_LIGHT0+i,  MGL_SPOT_EXPONENT,  0.0);
            gGLFT->glLightf(MGL_LIGHT0+i,  MGL_SPOT_CUTOFF,  180.0);
        }
        gGLFT->glDisable(MGL_LIGHTING);
        gGLFT->glDisable(MGL_COLOR_MATERIAL) ;
        gGLFT->glDisable(MGL_NORMALIZE) ;
        const MGLfloat ambient[4]  = { 0.2f, 0.2f, 0.2f, 1.0f };
        const MGLfloat specular[4] = { 0.8f, 0.8f, 0.8f, 1.0f };
        gGLFT->glMaterialfv(MGL_FRONT_AND_BACK, MGL_AMBIENT,  ambient);
        gGLFT->glMaterialfv(MGL_FRONT_AND_BACK, MGL_SPECULAR, specular);
        gGLFT->glLightModelfv(MGL_LIGHT_MODEL_AMBIENT, ambient);
        gGLFT->glLightModeli(MGL_LIGHT_MODEL_TWO_SIDE, 0);
    }
}
void DrawOverride::UserData::draw(
{
    
    const SubNode::Ptr& rootNode =
        fShapeNode->getCachedGeometry();
    if (!rootNode) return;
    
    MRenderer* theRenderer = MRenderer::theRenderer();
 
    if (!theRenderer) return;
    if (!stateMgr) return;
    if (displayStyle == 0) return;
    
    static const bool debugPassInformation = false;
    if (debugPassInformation)
    {
        printf(
"gpuCache override in pass[%s], semantic[", passId.
asChar());
        for (
unsigned int i=0; i<passSem.
length(); i++)
 
            printf(" %s", passSem[i].asChar());
        printf("\n");
    }
    if (displayStyle & MFrameContext::kXray) {
        
        
        if (rasterState && rasterState->
desc().
cullMode == MRasterizerState::kCullFront) {
 
            return;
        }
    }
    
    const MMatrix worldViewProjInvMatrix =
 
        context.
getMatrix(MFrameContext::kWorldViewProjInverseMtx, &status);
    Frustum frustum( worldViewProjInvMatrix);
    {
        TopLevelCullVisitor visitor(frustum, fSeconds);
        rootNode->accept(visitor);
        if (visitor.isCulled()) return;
    }
    
        context.
getMatrix(MFrameContext::kWorldViewMtx, &status);
        context.
getMatrix(MFrameContext::kProjectionMtx, &status);
    
    
    {
        
        gGLFT->glMatrixMode(MGL_PROJECTION);
        gGLFT->glPushMatrix();
        gGLFT->glLoadMatrixd(projection.
matrix[0]);
        
        gGLFT->glMatrixMode(MGL_MODELVIEW);
        gGLFT->glPushMatrix();
        
        if (displayStyle & MFrameContext::kBoundingBox)
        {
            setWireframeState(stateMgr);
            
            gGLFT->glColor3fv(fWireframeColor);
            
            gGLFT->glEnable(MGL_LINE_STIPPLE);
            gGLFT->glLineStipple(1, Config::kLineStippleShortDashed);
            drawBoundingBoxSampleGL(xform, rootNode);
            gGLFT->glDisable(MGL_LINE_STIPPLE);
        }
        const bool needWireframe =
            !(displayStyle & MFrameContext::kBoundingBox) &&
            (displayStyle & MFrameContext::kWireFrame || fIsSelected);
        const bool wireframeOnShaded = needWireframe &&
            (displayStyle & MFrameContext::kGouraudShaded);
        const bool disableWireframeOnShaded = wireframeOnShaded &&
            (DisplayPref::wireframeOnShadedMode() == DisplayPref::kWireframeOnShadedNone);
        
        
        if (needWireframe && !disableWireframeOnShaded)
        {
            setWireframeState(stateMgr);
            
            gGLFT->glColor3fv(fWireframeColor);
            gGLFT->glEnable(MGL_LINE_STIPPLE);
            if (wireframeOnShaded) {
                
                DisplayPref::WireframeOnShadedMode wireframeOnShadedMode =
                    DisplayPref::wireframeOnShadedMode();
                if (wireframeOnShadedMode == DisplayPref::kWireframeOnShadedReduced) {
                    gGLFT->glLineStipple(1, Config::kLineStippleDotted);
                }
                else {
                    assert(wireframeOnShadedMode != DisplayPref::kWireframeOnShadedNone);
                    gGLFT->glLineStipple(1, Config::kLineStippleShortDashed);
                }
            }
            else {
                gGLFT->glLineStipple(1, Config::kLineStippleShortDashed);
            }
            drawWireframeSampleGL(frustum, xform, rootNode);
            gGLFT->glDisable( MGL_LINE_STIPPLE );
        }
        if (displayStyle & MFrameContext::kGouraudShaded)
        {
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            const DepthOffsetType depthOffsetType = needWireframe ?
                kApplyDepthOffset : kNoDepthOffset;
            
            const bool anyLights = setupLightingGL(context);
            
            ColorType colorType = kSubNodeColor;
            bool needOpaquePass      =
                rootNode->transparentType() != SubNode::kTransparent;
            bool needTransparentPass =
                rootNode->transparentType() != SubNode::kOpaque;
            DrawShadedState::TransparentPruneType opaquePassPrune =
                DrawShadedState::kPruneTransparent;
            DrawShadedState::TransparentPruneType transparentPassPrune =
                DrawShadedState::kPruneOpaque;
            if (displayStyle & MFrameContext::kDefaultMaterial) {
                
                colorType           = kDefaultColor;
                needOpaquePass      = true;
                needTransparentPass = false;
                opaquePassPrune     = DrawShadedState::kPruneNone;
                if (anyLights) {
                    defaultDiffuseColor = Config::kDefaultGrayColor;
                }
            }
            else if (displayStyle & MFrameContext::kXray) {
                
                needOpaquePass       = false;
                needTransparentPass  = true;
                transparentPassPrune = DrawShadedState::kPruneNone;
                colorType = anyLights ? kXrayColor : kXrayBlackColor;
            }
            else
            if (!anyLights) {
                
                colorType = kBlackColor;
            }
            setShadedBlendState(stateMgr);
            
            if (needOpaquePass) {
                setShadedSolidDepthState(stateMgr);
                if (displayStyle & MFrameContext::kTwoSidedLighting) {
                    
                    if (Config::emulateTwoSidedLighting()) {
                        setShadedTwoSidedLightingState(kOneSidedLighting);
                        drawShadedSampleGL(
                            frustum, stateMgr, MRasterizerState::kCullFront,
                            depthOffsetType, colorType, defaultDiffuseColor,
                            kBackNormals, opaquePassPrune, xform, rootNode);
                        drawShadedSampleGL(
                            frustum, stateMgr, MRasterizerState::kCullBack,
                            depthOffsetType, colorType, defaultDiffuseColor,
                            kFrontNormals, opaquePassPrune, xform, rootNode);
                    }
                    else {
                        setShadedTwoSidedLightingState(kTwoSidedLighting);
                        drawShadedSampleGL(
                            frustum, stateMgr, MRasterizerState::kCullNone,
                            depthOffsetType, colorType, defaultDiffuseColor,
                            kFrontNormals, opaquePassPrune, xform, rootNode);
                    }
                }
                else {
                    
                    setShadedTwoSidedLightingState(kOneSidedLighting);
                    drawShadedSampleGL(
                        frustum, stateMgr, MRasterizerState::kCullNone,
                        depthOffsetType, colorType, defaultDiffuseColor,
                        kFrontNormals, opaquePassPrune, xform, rootNode);
                }
            }
            
            if (needTransparentPass) {
                setShadedAlphaDepthState(stateMgr);
                if (displayStyle & MFrameContext::kTwoSidedLighting) {
                    
                    setShadedTwoSidedLightingState(
                           Config::emulateTwoSidedLighting() ?
                           kOneSidedLighting : kTwoSidedLighting );
                    drawShadedSampleGL(
                        frustum, stateMgr, MRasterizerState::kCullFront,
                        depthOffsetType, colorType, defaultDiffuseColor,
                        Config::emulateTwoSidedLighting() ? kBackNormals : kFrontNormals,
                        transparentPassPrune, xform, rootNode);
                    drawShadedSampleGL(
                        frustum, stateMgr, MRasterizerState::kCullBack,
                        depthOffsetType, colorType, defaultDiffuseColor,
                        kFrontNormals,  transparentPassPrune, xform, rootNode);
                }
                else {
                    
                    setShadedTwoSidedLightingState(kOneSidedLighting);
                    drawShadedSampleGL(
                        frustum, stateMgr, MRasterizerState::kCullFront,
                        depthOffsetType, colorType, defaultDiffuseColor,
                        kFrontNormals, transparentPassPrune, xform, rootNode);
                    drawShadedSampleGL(
                        frustum, stateMgr, MRasterizerState::kCullBack,
                        depthOffsetType, colorType, defaultDiffuseColor,
                        kFrontNormals, transparentPassPrune, xform, rootNode);
                }
            }
            unsetLightingGL(context);
        }
        
        
        gGLFT->glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
        
        gGLFT->glFrontFace(GL_CCW);
        
        gGLFT->glLightModeli(MGL_LIGHT_MODEL_TWO_SIDE, 1);
        gGLFT->glMatrixMode(MGL_PROJECTION);
        gGLFT->glPopMatrix();
        gGLFT->glMatrixMode(MGL_MODELVIEW);
        gGLFT->glPopMatrix();
    }
    else {
        
    }
}
void DrawOverride::drawCb(
{
    
    
    
    
    ShapeNode::init3dViewPostRenderCallbacks();
    InitializeGLFT();
    const UserData* data = dynamic_cast<const UserData*>(userData);
    if (data) data->draw(context);
}
DrawOverride::creator(
const MObject& obj)
{
    return new DrawOverride(obj);
}
DrawOverride::DrawOverride(
const MObject& obj)
{}
DrawOverride::~DrawOverride()
{}
{
    
}
bool DrawOverride::isBounded(
const MDagPath& ,
 
{
    return true;
}
{
    
    const ShapeNode* shapeNode = dynamic_cast<ShapeNode*>(node.userNode());
    const SubNode::Ptr subNode = shapeNode->getCachedGeometry();
    const SubNodeData::Ptr subNodeData = subNode->getData();
    
    const XformData::Ptr xform =
        boost::dynamic_pointer_cast<const XformData>(subNodeData);
    if (xform) {
        const boost::shared_ptr<const XformSample>& sample =
            xform->getSample(seconds);
        return sample->boundingBox();
    }
    
    const ShapeData::Ptr shape =
        boost::dynamic_pointer_cast<const ShapeData>(subNodeData);
    if (shape) {
        const boost::shared_ptr<const ShapeSample>& sample =
            shape->getSample(seconds);
        return sample->boundingBox();
    }
}
bool DrawOverride::disableInternalBoundingBoxDraw() const
{
    
    
    return true;
}
{
    
    UserData* data = dynamic_cast<UserData*>(oldData);
    if (!data)
    {
        
        if (status)
        {
            data = new UserData(
                dynamic_cast<ShapeNode*>(node.userNode()));
        }
    }
    if (data) {
        
        const bool isSelected =
            (displayStatus == 
kLead)   ||
        data->set(
            wireframeColor,
            isSelected);
    }
    return data;
}
}