CurveBrush/CurveCreator.cpp

#include "CurveCreator.h"

#include <QtCore/QVector>
#include <math.h>

IMPLEMENT_CLASS( CurveCreator, BrushOperation, "CurveCreator" );

static QVector< Store< Vector >* > gLines;

QVector< Store<Vector>* >& CurveCreator::Lines() { return gLines; }

CurveCreator::CurveCreator() :
m_iCurrentCurve( -1 ),
m_iDoState( 0 )
{

};

void CurveCreator::BeginStroke( Mesh *, Modifier, TriggerType )
{
    // start a new curve
    gLines.push_back( new Store<Vector> );
    
    // indicate we are in the middle of doing the operation.
    m_iDoState = 0;
    m_iCurrentCurve = gLines.size() - 1;
};

void CurveCreator::EndStroke( void )
{
    if( gLines.back()->ItemCount() == 0 )
    {
        // we can get here if the user does a mouse click
        // with no mouse movement. since we don't want empty
        // curves in the array, remove the last one we added.
        m_iCurrentCurve = -1; 
        gLines.pop_back();
    };

    // treat this as an undoable operation.
    Kernel()->DoOperation( this );

    Kernel()->Redraw();
};

void CurveCreator::AddPatch( const SurfacePoint *, const Vector &, float, float, float, AxisAlignedBoundingBox & )
{

};

void CurveCreator::MouseMove( float fX, float fY, float , float , AxisAlignedBoundingBox &a )
{
    // determine where the user clicked in 3d space
    SurfacePoint pp;
    ViewPort *pVPp = Kernel()->ViewPort();
    if( Kernel()->Scene()->ActiveCamera()->Pick( fX*pVPp->Width(), fY*pVPp->Height(), pp ) )
    {
        gLines.back()->Add( pp.WorldPosition() );
    };

    // expand the dirty region of the viewport
    for( unsigned int i = 0; i < gLines.size(); ++i )
    {
        for( unsigned int j = 0; j < gLines[i]->ItemCount(); ++j )
            a.Extend( gLines[i]->operator[](j) );
    };
};

bool CurveCreator::ExecuteAndInvert( void )
{
    if( m_iDoState == 0 )   // this is do
    {
        m_iLine.Clear();
        m_iDoState = 1;
    }
    else if( m_iDoState == 1 ) // this is undo
    {
        if( m_iCurrentCurve != -1 )
        {
            Store<Vector>* pLine = gLines.back();
            m_iLine = *pLine;
            gLines.pop_back();
            delete pLine;
            pLine = 0;
        };
        m_iDoState = 2;
    }
    else if( m_iDoState == 2 )  // this is redo
    {
        if( m_iCurrentCurve != -1 )
        {
            Store<Vector>* pNewLine = new Store<Vector>;
            *pNewLine = m_iLine;

            gLines.push_back( pNewLine );
        };
        m_iDoState = 1;
    };

    Kernel()->Redraw();

    return true;
};

void CurveCreator::Serialize( Stream &s )
{
    // this method saves undo data
    s == m_iCurrentCurve == m_iLine == m_iDoState;
};