//**************************************************************************/
// Copyright (c) 2008 Autodesk, Inc.
// All rights reserved.

// Use of this software is subject to the terms of the Autodesk license
// agreement provided at the time of installation or download, or which
// otherwise accompanies this software in either electronic or hard copy form.
//

//**************************************************************************/                      
// DESCRIPTION:
// CREATED: October 2008
//**************************************************************************/

#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4201)
#endif

namespace mudbox {

/// Represents a 3D vector or point with S23E8 floating point elements.
class MBDLL_DECL Vector
{
public:
    /// Constructs the vector with zero values.
    inline Vector( void ) throw() { x = y = z = 0.0f; };

    /// Constructs the vector with specified values.
    inline Vector( float fX, float fY, float fZ = 0.0f ) throw() 
    { x = fX; y = fY; z = fZ; };

    /// Copy constructor.
    inline Vector( const Vector &vVector ) throw() 
    { x = vVector.x; y = vVector.y; z = vVector.z; };

    /// Construct the vector from a pointer to 8bit signed data. The 
    /// array must have at least 3 elements, with values 
    /// in the range -127 to +127.
    inline Vector( const char *pVector ) throw()
    { x = pVector[0]*(1.0f/127.0f); y = pVector[1]*(1.0f/127.0f); z = pVector[2]*(1.0f/127.0f); };

    /// Construct the vector from a pointer to 16bit signed data. The array 
    /// must have at least 3 elements in the range -32767 to +32767.
    inline Vector( const short *pVector ) throw() 
    { x = pVector[0]*(1.0f/32767.0f); y = pVector[1]*(1.0f/32767.0f); z = pVector[2]*(1.0f/32767.0f); };

    /// Sets the values of the vector elements and returns the vector.
    inline Vector &Set( float fX, float fY, float fZ ) throw() 
    { x = fX; y = fY; z = fZ; return *this; };

    /// Zeros all the components of the Vector, then returns it.
    inline Vector &Clear( void ) throw () 
    { return Set( 0.0f, 0.0f, 0.0f ); };

    /// \brief Normalizes the vector and returns it.
    ///
    /// If the vector is zero length, it is set to (0,1,0)
    Vector &Normalize( void ) throw();

    /// \brief Normalizes the vector and returns it.
    ///
    /// If the vector is zero length, it is set to (0,1,0)
    /// TO BE REMOVED.  This was an experiment at improving speed in exchange for accurracy.
    Vector &NormalizeApprox( void ) throw();

    /// Returns a normalized version of the vector, without changing this vector.
    Vector Normalized( void ) const throw();

    /// \brief Makes this vector orthogonal to the given vBase vector and 
    /// normalizes it.  Returns the vector.
    ///
    /// The resulting vector will lie on the plane defined by the original 
    /// value of this vector, and vBase.
    Vector &MakeOrthogonal( const Vector &vBase );

    /// \brief Sets the vector to the given length, without changing its 
    /// direction.
    ///
    /// If the vector is of zero length, then it is arbitrarily made 
    /// parallel to the Y axis.
    inline Vector &SetLength( float fLength ) 
    { Normalize(); operator *=( fLength ); return *this; };


    /// \brief Rotates this vector to be orthogonal to vBase without changing 
    /// its length, and returns it.
    ///
    /// The resulting vector will lie on the plane defined by the original value 
    /// of this vector, and vBase.
    inline Vector &RotateOrthogonal( const Vector &vBase ) 
    { float fLen = Length(); MakeOrthogonal( vBase ); SetLength( fLen ); return *this; };

    
    /// Returns the square of the length of the vector.
    inline float LengthSquare( void ) { return x*x+y*y+z*z; };
    
    /// Returns the length of the vector.
    float Length() const throw();

    /// Returns the 2D length of the vector, ignoring the z element.
    float Length2D() const throw();

    /// Returns the distance between two points (this and another, 
    /// represented as Vector objects).
    inline float DistanceFrom( const Vector &v ) const { return operator -(v).Length(); };

    /// Returns the shortest distance between this point and a line defined 
    /// by two other points (all points represented by vector objects).
    float DistanceFromLine( const Vector &v0, const Vector &v1 ) const;

    /// \brief Converts this (2d) vector to represent itself as a linear 
    /// combination of the supplied basis vectors.  Returns the result.
    ///
    /// This function works in 2d, ignoring the Z component of all the 
    /// vectors.  The supplied basis vectors must not be parallel.
    ///
    /// This method figures out how to express this vector (x,y) as a 
    /// linear combination of the two vector arguments.  X is set to the 
    /// multiplier on the first vector, and Y to the multiplier on the 
    /// second vector.
    /// So the original vector could be reconstructed from the final one 
    /// like this:  original = x*v0 + y*v1
    const Vector &Relocate2D( const Vector &v0, const Vector &v1 );

    /// \brief Converts this vector to represent itself as a linear combination 
    /// of the supplied basis vectors.
    ///
    /// This method figures out how to express this vector (x,y,z) as a linear 
    /// combination of the three vector arguments.  X is set to the multiplier 
    /// on the first vector, Y to the multiplier on the second vector, and Z to 
    /// the multiplier on the third.  The supplied basis vectors must not be 
    /// parallel. So the original vector could be reconstructed from the final 
    /// one like this:  original = x*v0 + y*v1 + z*v2
    void Relocate( const Vector &v0, const Vector &v1, const Vector &v2 );


    /// \brief This operation calculates the baricentric coordinates inside a quad 
    /// where the quad corners are v0,v1,v2,v3.
    ////
    /// 2d points in this function are represented by 3d Vector objects, with the 
    /// Z component ignored.
    /// This function works in 2d only. If v0, v1, v2 and v3 are the corners 
    /// of a quad in a 2d space (such as UV space), and this object's (x,y) 
    /// coordinates represent a point inside that quad, then this function will 
    /// calculate the baricentric coordinates inside the quad (v0 and v3 are 
    /// opposite corners). After this operation the following code can calculate 
    /// the original value stored in the vector (this can help you understand 
    /// what the function does):
    /// \code
    /// Vector vEdgeA = v1-v0;
    /// Vector vEdgeB = v3-v2;
    /// Vector vPointA = v0+vEdgeA*x;
    /// Vector vPointB = v2+vEdgeB*x;
    /// Vector vEdge = vPointB-vPointA;
    /// Vector vValueBeforeOperation = vPointA+vEdge*y;
    /// \endcode
    bool Relocate2DQuad( const Vector &v0, const Vector &v1, 
                         const Vector &v2, const Vector &v3 );
    
    /// Returns the cosine of the angle between this vector and the one passed in.
    float AngleCos( const Vector &v1 ) const throw() 
    { return Vector(*this).Normalize()|Vector(v1).Normalize(); };
    

    /// Returns the minimum of this and the argument vector.  
    /// Minimums are calculated individually for z, y, and z.
    inline Vector Minimum( const Vector &o ) 
    { return Vector( Min(x, o.x), Min(y, o.y), Min(z, o.z) ); };

    /// Returns the maximum of this and the argument vector.  
    /// Maximums are calculated individually for z, y, and z.
    inline Vector Maximum( const Vector &o ) 
    { return Vector( Max(x, o.x), Max(y, o.y), Max(z, o.z) ); };

    /// Returns the inverse of the vector.
    inline Vector operator -( void ) const throw() 
    { return Vector( -x, -y, -z ); };

    /// Returns the sum of a vector and a scalar.  
    /// (The scalar is added to each component individually).
    inline Vector operator +( float f ) const throw() 
    { return Vector( x+f, y+f, z+f ); };

    /// Returns the sum of two vectors.
    inline Vector operator +( const Vector &v ) const throw() 
    { return Vector( x+v.x, y+v.y, z+v.z ); };

    /// Returns the difference between two vectors/points.
    inline Vector operator -( const Vector &v ) const throw() 
    { return Vector( x-v.x, y-v.y, z-v.z ); };

    /// Returns the product of two vectors by components.
    inline Vector operator *( const Vector &v ) const throw() 
    { return Vector( x*v.x, y*v.y, z*v.z ); };

    /// Returns the product of the vector and a scalar.
    inline Vector operator *( float f ) const throw() 
    { return Vector( x*f, y*f, z*f ); };
    
    /// Returns the quotient of two vectors by components.
    inline Vector operator /( const Vector &v ) const throw() 
    { return Vector( x/v.x, y/v.y, z/v.z ); };

    /// Returns the quotient of a vector and a scalar.
    inline Vector operator /( float f ) const throw() 
    { return operator *( 1.0f/f ); };

    /// Returns the product of a vector and an integer.
    inline Vector operator *( int i ) const throw() 
    { return operator *( float(i) ); };

    /// Returns the quotient of a vector and an integer.
    inline Vector operator /( int i ) const throw() 
    { return operator /( float(i) ); };

    /// Returns the quotient of a vector and an unsigned integer.
    inline Vector operator /( unsigned int i ) const throw() 
    { return operator /( float(i) ); };

    /// Returns the dot product of two vectors.
    inline float operator |( const Vector &v ) const throw() 
    { return x*v.x+y*v.y+z*v.z; };

    /// Returns the cross product of two vectors.
    Vector operator &( const Vector &v ) const
    {
        Vector vR;
        vR.m_fX = m_fY*v.m_fZ-m_fZ*v.m_fY;
        vR.m_fY = m_fZ*v.m_fX-m_fX*v.m_fZ;
        vR.m_fZ = m_fX*v.m_fY-m_fY*v.m_fX;
        return vR;
    };

    /// Returns \b true if the two vectors are identical, 
    /// \b false otherwise.
    inline bool operator ==( const Vector &v ) const throw() 
    { return x == v.x && y == v.y && z == v.z; };

    /// Returns \b true if the two vectors are different, \b false otherwise.
    inline bool operator !=( const Vector &v ) const throw() 
    { return !operator ==( v ); };

    /// Returns \b true if the vector is not a zero vector, \b false otherwise.
    inline operator bool( void ) const throw() { return x || y || z; };
    
    /// Returns \b true if the vector is a zero vector, \b false otherwise.
    inline bool operator !( void ) const throw() { return !operator bool(); };

    /// Sets this vector to equal another one and returns it.
    inline Vector &operator =( const Vector &v ) 
    { x = v.x; y = v.y; z = v.z; return *this; };

    /// Sets this vector to equal another one and returns it.
    inline Vector &operator <<( const Vector &v ) 
    { x = v.x; y = v.y; z = v.z; return *this; };

    /// Subtracts the component values of another vector from 
    /// this one's, and returns the result.
    inline Vector &operator -=( const Vector &v ) throw() 
    { x-=v.x; y-=v.y; z-=v.z; return *this; };
    
    /// Adds another vector to this one and returns the result.
    inline Vector &operator +=( const Vector &v ) throw() 
        { x+=v.x; y+=v.y; z+=v.z; return *this; };

    /// Multiplies the components of the vector with a scalar 
    /// value and returns the result.
    inline Vector &operator *=( float f ) { x *= f; y *= f; z *= f; return *this; };

    /// Multiplies the vector with another vector by components and 
    /// returns the result.
    inline Vector &operator *=( const Vector &v ) 
        { x *= v.x; y *= v.y; z *= v.z; return *this; };

    /// Divides the vector by a scalar and returns the result.
    inline Vector &operator /=( float f ) { return operator *=( 1.0f/f ); };

    /// Returns a individual components of the vector.
    inline float &operator [] (
        int i   ///< [in] Allowed range:  0 to 2.
        ) throw() { return m_aCoors[i]; };

    /// Returns a component of the vector.
    inline float &operator [](
        unsigned int i  ///< [in] Allowed range:  0 to 2.
        ) throw() { return m_aCoors[i]; };
        
    /// Returns a pointer to the data of the vector.  Do not delete this pointer.
    inline operator const float *( void ) const { return &x; };
    union 
    {
        struct { float m_fX, m_fY, m_fZ; };
        struct { float x, y, z; };
        float m_aCoors[3];
    };

};


/// Multiplies a float scalar value by a vector, the result is a vector.
inline MBDLL_DECL Vector operator *( float f, const Vector &v ) throw() 
{ return v*f; };

/// Multiplies an integer scalar value by a vector, the result is a vector.
inline MBDLL_DECL Vector operator *( int i, const Vector &v ) throw() 
{ return float(i)*v; };

typedef AttributeInstance<Vector> avector;

MBDLL_DECL AttributeWidget *CreateNewVectorWidget( QWidget *pParent, 
                                                   int      iWidth, 
                                                   avector *pAttribute );

template <> inline
AttributeWidget *avector::CreateEditorWidget( QWidget *pParent, int iWidth ) 
{ return CreateNewVectorWidget( pParent, iWidth, this ); };

template <> inline
QString avector::AsString( void ) const 
{ return QString("%1 %2 %3").arg(m_cValue.x).arg(m_cValue.y).arg(m_cValue.z); };

template <> inline
void avector::SetFromString( const QString &s ) 
{ m_cValue.x = s.section( ' ', 0,0 ).toFloat(); 
  m_cValue.y = s.section( ' ', 1,1 ).toFloat(); 
  m_cValue.z = s.section( ' ', 2,2 ).toFloat(); };

template <> inline

Attribute::AttributeType avector::Type( void ) const { return typeVector; };


/// A four dimensionsional vector (X, Y, Z, and W)
class MBDLL_DECL Vector4
{
public:
    Vector4() { x=y=z=w=0.0f; }

    Vector4(float X, float Y, float Z, float W) {x=X; y=Y; z=Z; w=W;}

    inline bool operator ==( const Vector4 &v ) const throw() 
    { return x == v.x && y == v.y && z == v.z; };

    inline bool operator !=( const Vector4 &v ) const throw() 
    { return !operator ==( v ); };

    float x, y, z, w;
};



typedef AttributeInstance<Vector4> avector4;

MBDLL_DECL AttributeWidget *CreateNewVector4Widget( QWidget *pParent, int iWidth, avector4 *pAttribute );

template <> inline

AttributeWidget *avector4::CreateEditorWidget( QWidget *pParent, int iWidth ) 
{ return CreateNewVector4Widget( pParent, iWidth, this ); };

template <> inline
QString avector4::AsString( void ) const 
{ return QString("%1 %2 %3 %4").arg(m_cValue.x).arg(m_cValue.y).arg(m_cValue.z).arg(m_cValue.w); };

template <> inline
void avector4::SetFromString( const QString &s ) 
{ m_cValue.x = s.section( ' ', 0, 0 ).toFloat(); 
  m_cValue.y = s.section( ' ', 1, 1 ).toFloat(); 
  m_cValue.z = s.section( ' ', 2, 2 ).toFloat(); 
  m_cValue.w = s.section( ' ', 3, 3 ).toFloat();};

template <> inline
Attribute::AttributeType avector4::Type( void ) const { return typeVector; };



/// Represents a color with four components: red, green, blue, alpha. Each 
/// component is represented by a 32 bit float value. The value 0 for the 
/// alpha means full transparency, while 1 means fully opaque.

class MBDLL_DECL Color

{
public:

    /// Constructs a color object with specified values. If no parameters used, 
    /// the color will be white.
    Color( float fRed = 1.0f, float fGreen = 1.0f, float fBlue = 1.0f, float fAlpha = 1.0f ) 
    { m_fRed = fRed; m_fGreen = fGreen; m_fBlue = fBlue, m_fAlpha = fAlpha; };

#ifdef QT_VERSION

    Color( const QColor &c ) 
    { r = c.red()  *(1.0f/255.0f); 
      g = c.green()*(1.0f/255.0f); 
      b = c.blue() *(1.0f/255.0f); 
      a = 1.0f; };

#endif

    /// Sets the current value of the color.
    inline void Set( float fRed, float fGreen, float fBlue, float fAlpha = 1.0f ) 
    { r = fRed; g = fGreen; b = fBlue; a = fAlpha; };


    /// Returns a pointer to the color data, which consists of four 
    /// floats (R, G, B, and A).  Do not delete this pointer.
    inline operator const float *( void ) const { return &m_fRed; };

    /// Returns a color component based on its index.
    inline float &operator[]( unsigned int iChannel ) 
    { MB_ASSERT( iChannel < 4 ); return m_fData[iChannel]; };

    /// Converts the color value into a singe 32 bit integer, where each component 
    /// takes eight bits. This format is used by some external libraries.
    inline operator unsigned int( void ) const 
        { return (unsigned int)(0xff*m_fRed)+(((unsigned int)(0xff*m_fGreen))<<8)+
            (((unsigned int)(0xff*m_fBlue))<<16)+(((unsigned int)(0xff*m_fAlpha))<<24); };


    /// Multiplies each component of the color with a single scalar value. 
    /// The alpha value is unchanged.  The result is returned.
    Color &operator *=(const float f) { r*=f; g*=f; b*=f; return *this; };

    /// Mutliplies two colors and returns the result.
    Color operator *( const Color &c ) const 
        { return Color( r*c.r, g*c.g, b*c.b, a*c.a ); };

    /// Mutliplies two colors, puts the result into the current 
    /// object, and returns it.
    Color &operator *=( const Color &c ) 
    { r *= c.r; g *= c.g; b *= c.b; a *= c.a; return *this; };

    /// Adds two colors and returns the result.
    Color operator +( const Color &c ) const 
        { return Color( r+c.r, g+c.g, b+c.b, a+c.a ); };

    /// Subtracts two colors and returns the result.
    Color operator -( const Color &c ) const 
        { return Color( r-c.r, g-c.g, b-c.b, a-c.a ); };

    /// Adds two colors, puts the result into the current object, and returns it.
    Color &operator +=( const Color &c ) 
    { r += c.r; g += c.g; b += c.b; a += c.a; return *this; };

    /// Returns \b true if the two colors are identical, \b false otherwise.
    bool operator ==( const Color &c ) const 
        { return r == c.r && g == c.g && b == c.b && a == c.a; };

    /// Returns \b true if the two colors are different, \b false otherwise.
    inline bool operator !=( const Color &c ) const { return !operator ==( c ); };
    

    /// \brief Mix two colors based on a scalar value which should be within 
    /// the range 0 and 1.  Return the result.
    ///
    /// The scalar value controls how much of this color, and how much of 
    /// the passed-in color are included in the mix. Setting the \b f value 
    /// closer to 1 biases the result towards this color;  setting the \b f 
    /// value closer to zero biases the result towards the passed-in colour.
    Color Mix( const Color &c, float f ) const
    { return Color( r*f+c.r*(1-f), g*f+c.g*(1-f), b*f+c.b*(1-f), a*f+c.a*(1-f) ); };

    /// Returns the luminance value for the color.
    inline float Luminance() const 
        { return 0.299f * r + 0.587f * g + 0.114f * b; }

    

#ifdef QT_VERSION
    operator QColor( void ) const { return QColor( int(r*255.0), int(g*255.0), int(b*255.0) ); };
    QColor ToQColor( void ) const { return QColor( int(r*255.0), int(g*255.0), int(b*255.0) ); };
#endif

    union {
        struct { float m_fRed, m_fGreen, m_fBlue, m_fAlpha; };
        struct { float r, g, b, a; };
        float  m_fData[4];
    };

    static Color black;
    static Color white;
    static Color red;
    static Color green;
    static Color blue;
    static Color gray;
};



/// Multiplies a scalar float value by a Color.
inline Color operator *( float f, const Color &c ) 
{ return Color( c.r*f, c.g*f, c.b*f, c.a*f ); };


typedef AttributeInstance<Color> acolor;

MBDLL_DECL AttributeWidget *CreateNewColorWidget( QWidget *pParent, int iWidth, acolor *pAttribute );

template <> inline
AttributeWidget *acolor::CreateEditorWidget( QWidget *pParent, int iWidth ) 
{ return CreateNewColorWidget( pParent, iWidth, this ); };

template <> inline
Attribute::AttributeType acolor::Type( void ) const { return typeColor; };

template <> inline
QString acolor::AsString( void ) 
const { return QString("%1 %2 %3 %4").arg(m_cValue.r).arg(m_cValue.g).arg(m_cValue.b).arg(m_cValue.a); };

template <> inline

void acolor::SetFromString( const QString &s ) {
    m_cValue.r = s.section( ' ', 0, 0 ).toFloat(); 
    m_cValue.g = s.section( ' ', 1, 1 ).toFloat(); 
    m_cValue.b = s.section( ' ', 2, 2 ).toFloat(); 
    m_cValue.a = s.section( ' ', 3, 3 ).toFloat();
};



/// Represents a bounding box whose axes are aligned with the coordinate system.
/// The box is usually referred by two corners, the start corner means the one 
/// whose coordinates are the smallest, while the end corner means the opposite.
class MBDLL_DECL AxisAlignedBoundingBox
{
public:
    /// Creates an empty bounding box.
    AxisAlignedBoundingBox( void ) { Reset(); };

    /// Creates an object by specifying two corners of the box.
    AxisAlignedBoundingBox( const Vector &vStart, const Vector &vEnd ) :
        m_vStart( vStart ),
        m_vEnd( vEnd ) {};

    /// Creates an object by specifying the center of it and the distance 
    /// of the sides from the center. This will be a cube.
    AxisAlignedBoundingBox( const Vector &vCenter, float fSize )
    {
        Vector v( fSize, fSize, fSize );
        m_vStart = vCenter-v;
        m_vEnd   = vCenter+v;
    };

    /// Creates an object by cloning another one.
    AxisAlignedBoundingBox( const AxisAlignedBoundingBox &cA ) :
    m_vStart( cA.m_vStart ),
    m_vEnd( cA.m_vEnd ) {};

    /// Assigns the value of a box object to another one.
    AxisAlignedBoundingBox &operator =( const AxisAlignedBoundingBox &cBB )
    {
        m_vStart = cBB.m_vStart;
        m_vEnd = cBB.m_vEnd;
        return *this;
    };

    /// Extends the box to contain another one.
    AxisAlignedBoundingBox &operator +=( const AxisAlignedBoundingBox &cBB )
    {
        for ( int i = 0; i < 8; i++ ) Extend( cBB[i] );
        return *this;
    };

    /// Returns \b true if two boxes are identical, \b false otherwise.
    bool operator ==( const AxisAlignedBoundingBox &cBB ) const
    {
        return m_vStart == cBB.m_vStart && m_vEnd == cBB.m_vEnd;
    };

    /// Makes the box empty.
    void Reset( void )
    {
        m_vStart.Set( 0, 0, 0 );
        m_vEnd.Set( -1, -1, -1 );
    };

    /// Writes/reads the object data to/from a stream.
    void Serialize( Stream &s );


    /// returns \b true if the two boxes are different, \b false otherwise.
    bool operator !=( const AxisAlignedBoundingBox &cBox ) const 
        { return !(operator ==(cBox)); };


    /// Extends the box to contain the passed point.
    void Extend( const Vector & );

    /// Extends the box to contain another one.
    void Extend( const AxisAlignedBoundingBox &bb )
    {
        if ( !bb.IsEmpty() ) {
            Extend( bb.m_vStart );
            Extend( bb.m_vEnd );
        };
    };

    
    /// Transforms the box with the passed-in matrix, and returns the smallest 
    /// box which contains the result. This is usually larger than the 
    /// original box, because the transformation might rotate the box out 
    /// of axis alignment.
    void Transform( const class Matrix &mMatrix );

    /// Returns the corners of the box. Valid indexes are 0-7.
    Vector operator []( int iCornerIndex ) const;

    /// Returns the maximum edge length of the box.
    float Size( void ) const { return Max( Max( XSize(), YSize() ), ZSize() ); };

    /// Returns the length of the box along the X axis.
    float XSize( void ) const { return m_vEnd.m_fX-m_vStart.m_fX; };

    /// Returns the length of the box along the Y axis.
    float YSize( void ) const { return m_vEnd.m_fY-m_vStart.m_fY; };

    /// Returns the length of the box along the Y axis.
    float ZSize( void ) const { return m_vEnd.m_fZ-m_vStart.m_fZ; };

    /// Returns the volume of the box.
    float Volume( void ) const { return XSize()*YSize()*ZSize(); };

    /// Returns the center of the box.
    Vector Center( void ) const { return (m_vStart+m_vEnd)*0.5f; };

    /// Returns \b true if the passed-in box contains this box.
    bool IsPartOf( const AxisAlignedBoundingBox &cBB ) const
    {
        return (
            m_vStart.m_fX >= cBB.m_vStart.m_fX && m_vEnd.m_fX <= cBB.m_vEnd.m_fX &&
            m_vStart.m_fY >= cBB.m_vStart.m_fY && m_vEnd.m_fY <= cBB.m_vEnd.m_fY &&
            m_vStart.m_fZ >= cBB.m_vStart.m_fZ && m_vEnd.m_fZ <= cBB.m_vEnd.m_fZ );
    };

    /// Returns \b true if the two boxes intersect at all.
    bool IsTouching( const AxisAlignedBoundingBox &cBB ) const
    {
        return !(
            m_vStart.m_fX >= cBB.m_vEnd.m_fX || m_vEnd.m_fX <= cBB.m_vStart.m_fX ||
            m_vStart.m_fY >= cBB.m_vEnd.m_fY || m_vEnd.m_fY <= cBB.m_vStart.m_fY ||
            m_vStart.m_fZ >= cBB.m_vEnd.m_fZ || m_vEnd.m_fZ <= cBB.m_vStart.m_fZ );
    };
    

    /// Returns \b true if the box intersects any part of a specified line.
    ///
    /// If there is an intersection, then a point guaranteed to be 
    /// inside the box is returned in the third argument (fPlace).  That 
    /// argument represents a location along the line
    /// from vStart to vEnd.  (Location = vStart + fPlace*vEnd)
    bool IsTouching(
        const Vector &vStart,   ///< [in] A point (represented as a Vector) defining the start of the line
        const Vector &vEnd,     ///< [in] A point (represented as a Vector) defining the end of the line
        float &fPlace           ///< [out] A number between 0.0 and 1.0, defining a position along 
                                /// the line that is guaranteed to be inside the box (if \b true was returned).
        ) const;

    /// Returns \b true if the box contains the specified point.
    bool IsContaining( const Vector &cV ) const
    {
        return (
            m_vStart.m_fX <= cV.m_fX && m_vEnd.m_fX >= cV.m_fX &&
            m_vStart.m_fY <= cV.m_fY && m_vEnd.m_fY >= cV.m_fY &&
            m_vStart.m_fZ <= cV.m_fZ && m_vEnd.m_fZ >= cV.m_fZ );
    };
    

    /// Returns \b true if the box contains the specified box.
    bool IsContaining( const AxisAlignedBoundingBox &b ) const 
        { return IsContaining( b.m_vStart ) && IsContaining( b.m_vEnd ); };
    

    /// Returns \b true if the box is empy. Note that when the start and end 
    /// corners are equal then the box is not treated as empty.
    bool IsEmpty( void ) const { return m_vStart.x > m_vEnd.x; };

    /// Multiplies the box coordinates with a scalar value.
    AxisAlignedBoundingBox operator *( float fFactor )
    {
        return AxisAlignedBoundingBox( m_vStart*fFactor, m_vEnd*fFactor );
    };

    Vector m_vStart;
    Vector m_vEnd;
};



/// Represents a local coordinate basis comprising three axes that define a 
/// coordinate system. The axes don't have to be normalized or
/// orthogonal, but no pair of them should be parallel.
class MBDLL_DECL Base
{

public:
    /// Creates a empty base with no valid axises.
    Base( void );

    /// Creates a base with the three specified vector axes.
    Base( const Vector &vA, const Vector &vB, const Vector &vC );
    

    /// Derives one axis from the two others. (The new axis will be orthagonal to the other two)
    void Derive(
        unsigned int iIndex,    ///< [in] The axis to be recalculated.  0 for x, 1 for y, and 2 for z
        bool bRightHand = true  ///< [in] If \b true, make this a right-handed coordinate system
        );


    /// Force one basis axis to be orthagonal to another (or both other) basis axes.

    void Orthogonalize(
        unsigned int iIndex,        ///< [in]  Specifies which axis to orthogonalize.  0 for x, 1 for y, and 2 for z.
        unsigned int iSource = -1   ///< [in]  Specifies which axis to use as a reference.  
                                    /// 0 for x, 1 for y, and 2 for z -- and -1 means "use both other axes"
        );

    /// Normalize all the three axes.
    void Normalize( void ) { a.Normalize(); b.Normalize(); c.Normalize(); };


    /// Converts a point (represented as a vector) from basis space to world space and returns it.
    Vector TransformFrom( const Vector &cSource ) const;

    /// Converts a point (represented as a vector) from world space to this basis space and returns it.
    Vector TransformTo( const Vector &cSource ) const;

    /// Multiplies the base vectors with a scalar value and returns the result.
    Base operator *( float fFactor ) const;

    /// Adds two bases.
    Base operator +( const Base &bOther ) const;

    /// Returns a reference to a basis axis.
    Vector& Axis(
        unsigned int iIndex ///< [in] 0 for x; 1 for y; 2 for z
        );


    /// Returns a reference to a basis axis.
    const Vector& Axis(
        unsigned int iIndex ///< [in] 0 for x; 1 for y; 2 for z
        ) const;

    Vector a, b, c;
};



/// This class will be removed from the SDK.
class SubSpace : public Node

{
    DECLARE_CLASS;

public:
    virtual void Initialize( const class Mesh *pMesh, Store<unsigned int> aFaceList, float fAClip, float fBClip );
    virtual bool IsOutside( const Vector &vPos, float fRange ) const;
    virtual AxisAlignedBoundingBox BoundingBox( void ) const;
};



/// This class represents a 4x4 transformation matrix.
class MBDLL_DECL Matrix
{
public:

    /// Construct a matrix without initializing its elements. The values stored in the matrix are undefined.
    Matrix( void ) {};

    Matrix( const Matrix &m ) :
        _11(m._11), _12(m._12), _13(m._13), _14(m._14), 
        _21(m._21), _22(m._22), _23(m._23), _24(m._24), 
        _31(m._31), _32(m._32), _33(m._33), _34(m._34), 
        _41(m._41), _42(m._42), _43(m._43), _44(m._44) {};

    /// Construct the matrix by passing all the 16 values.
    Matrix( float f11, float f12, float f13, float f14,
            float f21, float f22, float f23, float f24,
            float f31, float f32, float f33, float f34,
            float f41, float f42, float f43, float f44 ) :
        _11(f11), _12(f12), _13(f13), _14(f14), 
        _21(f21), _22(f22), _23(f23), _24(f24), 
        _31(f31), _32(f32), _33(f33), _34(f34), 
        _41(f41), _42(f42), _43(f43), _44(f44) {};

    /// Construct a matrix from an array of double values. At least 16 values should be contained in the array.
    Matrix( const double *pMatrix );

    /// Returns a reference to a specific element in the matrix.
    float &operator()( int iRow, int iColumn ) 
    { 
        return m_fData[iRow*4+iColumn]; 
    };
    
    /// Returns the value of a specific element in the matrix.
    float operator()( int iRow, int iColumn ) const 
    { 
        return m_fData[iRow*4+iColumn]; 
    };
    
    /// Returns a pointer to the matrix data as a pointer to float values.  
    /// Do not delete this pointer.
    operator const float *( void ) const { return m_fData; };
    
    /// Returns a pointer to the constant matrix data as a pointer to 
    /// float values.
    operator float *( void ) { return m_fData; };

    /// Sets this matrix to be the identity matrix.
    Matrix &SetIdentity( void );

    /// Return \b true if the matrix is the identity matrix.
    bool IsIdentity( void ) const;

	/// Returns true if the transformation represented by the matrix is rigid (contains only translation and rotation, not scale).
	bool IsRigid( void ) const;
    
    /// Multiplies the matrix with a scalar value.
    Matrix &operator *=( float );

    /// Multiplies two matrices.
    Matrix operator *( const Matrix &m ) const;

	/// Returns the multiplication of a matrix and a scalar.
	Matrix operator *( float ) const;

	/// Returns the sum of two matrices.
	Matrix operator +( const Matrix & ) const;

    /// Multiplies the matrix with another matrix.
    Matrix &operator *=( const Matrix &m );

    /// Return \b true if the two matrices are identical.
    bool operator ==( const Matrix &m ) const;

    /// Sets the values in a row of the matrix. The last value in the row 
    /// remains unchanged.
    void SetRow( int iRowIndex, const Vector &vValue );

    /// Transposes the matrix and returns it.
    Matrix &Transpose( void );

    /// Inverts the matrix and returns it.
    Matrix &Invert( void );

    /// Creates a rotation matrix from the given euler values stored in 
    /// the vector and returns it.
    Matrix &FromEuler( const Vector &vAngles );

    /// Converts a rotation matrix to euler values returns them in a vector
    Vector ToEuler( void ) const;
    
    /// Calculates a rotation matrix from an axis and angle and returns it.
    Matrix &FromAxisAngle( const Vector &vAxis, float fAngle );

    /// \brief Transforms a vector by the matrix and returns the result.
    /// The fourth component of the vector (if you are using homogeneous 
    /// coordinates) can be passed in the fW parameter.
    Vector Transform(
        const Vector &v,    ///< [in] A Vector containing the x, y, z components of the point
        float fW = 1.0f     ///< [in] The w component of the point
        ) const
    {
        return Vector( 
            v.m_fX*_11+v.m_fY*_21+v.m_fZ*_31+fW*_41,
            v.m_fX*_12+v.m_fY*_22+v.m_fZ*_32+fW*_42,
            v.m_fX*_13+v.m_fY*_23+v.m_fZ*_33+fW*_43 );
    };

    /// \brief Transforms a point (represented by a Vector) by the matrix and 
    /// returns the result. This point is assumed to be represented in homogenous 
    /// coordinates, with a fourth (W) value. After the transformation the result 
    /// vector will be divided by the resulting W component.
    Vector ProjectedTransform(
        const Vector &v,    ///< [in] A Vector containing the x, y, z components of the point
        float fW = 1.0f     ///< [in] The w component of the point
        ) const
    {
        float fRW = v.m_fX*_14+v.m_fY*_24+v.m_fZ*_34+fW*_44;
        return (1/fRW)*Vector( 
            v.m_fX*_11+v.m_fY*_21+v.m_fZ*_31+fW*_41,
            v.m_fX*_12+v.m_fY*_22+v.m_fZ*_32+fW*_42,
            v.m_fX*_13+v.m_fY*_23+v.m_fZ*_33+fW*_43 );
    };


    /// \brief Transforms a point (represented by a Vector) by the matrix, and returns all 
    /// four homogeneous coordinates.
    ///
    /// Since Vectors only hold 3 coordinates, the W coordinate is passed 
    /// in and out through parameters.
    Vector Transform(
        const Vector &v,    ///< [in] A Vector containing the x, y, z components of the point
        float fW,           ///< [in] The w component of the point
        float &fRW          ///< [out] The w component of the transformed point
        ) const
    {
        fRW = v.m_fX*_14+v.m_fY*_24+v.m_fZ*_34+fW*_44;
        return Vector( 
            v.m_fX*_11+v.m_fY*_21+v.m_fZ*_31+fW*_41,
            v.m_fX*_12+v.m_fY*_22+v.m_fZ*_32+fW*_42,
            v.m_fX*_13+v.m_fY*_23+v.m_fZ*_33+fW*_43 );
    };

    /// \brief Transform a direction vector by the matrix.
    ///
    /// Vector transformation is different than point transformation, in that it 
    /// ignores the last row (translation) of the matrix during the transformation.
    Vector TransformDirection( const Vector &v ) const
    {
        return Vector( 
            v.m_fX*_11+v.m_fY*_21+v.m_fZ*_31,
            v.m_fX*_12+v.m_fY*_22+v.m_fZ*_32,
            v.m_fX*_13+v.m_fY*_23+v.m_fZ*_33 );
    };

    union {
        float m_fData[16];
        struct {
            float _11, _12, _13, _14;
            float _21, _22, _23, _24;
            float _31, _32, _33, _34;
            float _41, _42, _43, _44;
        };
    };
};

/// \brief The Quaternion class is used to represent rotations in most cases. 
///
/// It is an alternative to the Matrix class to store transformations which has only
/// rotation part. In this case the quaternion is unit, the value returned by the Length()
/// function is 1. The advantage of the quaternion representation over the matrices is that
/// it is easier to do transformation blending, and it only needs 16 bytes in the memory.
/// Disadvangate is that it is limited to rotation only.
class MBDLL_DECL Quaternion
{
public:
	/// Constructs a quaternion which represents the identical transformation.
    inline Quaternion( void ) { SetIdentity(); };

	/// Constructs a quaternion by passing the real part as a scalar, and the rest as a vector.
    inline Quaternion( 
		float fW, ///<[in] Real part.
		const Vector &vXYZ ///<[in] Nonreal part as a vector.
		)
    { m_fW = fW; m_fX = vXYZ.x; m_fY = vXYZ.y; m_fZ = vXYZ.z; };

	/// Constructs a quaternion by passing all the four components as a scalar.
    inline Quaternion( float fW, float fX, float fY, float fZ )
    { m_fW = fW; m_fX = fX; m_fY = fY; m_fZ = fZ; };

	/// Constructs a quaternion which represents a rotation around an axis with a given angle. Center of the rotation is the origo.
	Quaternion( 
		const Vector &vAxis, ///< [in] Rotation axis.
		float fAngle ///< [in] Angle of the rotation in radian.
		);

	/// Constructs a quaternion from a rotation matrix. If the matrix is not a valid rotation matrix, the result will be undefined.  @see Matrix::IsRigid()
	Quaternion( const Matrix &mRotation );

	/// Returns the square of the length of the quaternion.
	float LengthSquare( void ) const;

	/// Returns the length of the quaternion. For quaternions which represent rotation the length is
	/// 1, means that the quaternion is a unit quaternion.
	float Length( void ) const;

	/// Converts the quaternion into a matrix which represents the same transformation as the quaternion.
    Matrix ToMatrix( void ) const;

	/// Transform a given point by a quaternion.
	Vector Transform( 
		const Vector &vPoint ///< [in] Point to be transformed.
		) const;

	/// Returns the product of the quaternion and a scalar value.
    inline Quaternion operator *( float fMultiplier ) const
	{ return Quaternion( m_fW*fMultiplier, m_fX*fMultiplier, m_fY*fMultiplier, m_fZ*fMultiplier ); };

	/// Multiplies the quaternion by a scalar value.
	inline Quaternion &operator *=( float fMultiplier ) 
	{ *this = operator *( fMultiplier ); return *this; };

	/// Returns the negative of a quaternion.
	inline Quaternion operator -( void ) const 
	{ return Quaternion( -m_fW, -m_fX, -m_fY, -m_fZ ); };

	/// Returns the sum of two quaternions.
    Quaternion operator +( const Quaternion &vAddition ) const;

	/// Adds a quaternion to this quaternion.
    Quaternion &operator +=( const Quaternion &vAddition );

	/// Returns the substraction of two quaternions.
    Quaternion operator -( const Quaternion &vAddition ) const;

	/// Substracts a quaternion from this quaternion.
    Quaternion &operator -=( const Quaternion &vAddition );

	/// Returns the multiplication of two quaternions. The result is representing the transformation which is 
	/// the concatenation of the two transformation represented by the two quaternions.
    Quaternion operator *( const Quaternion &vMultiplier ) const;

	/// Multiplies a quaternion by another one.
    Quaternion &operator *=( const Quaternion &vMultiplier );

	/// Returns the scalar product of two quaternions.
	float operator |( const Quaternion &vMultiplier ) const;

	/// Normalizes the quaternion. This converts the quaternion into a unit quaternion which is a representation
	/// of a rotation.
    Quaternion &Normalize( void );

	/// Conjugates the quaternion. The conjugate is the same as the inverse for unit quaternions.
    Quaternion &Conjugate( void );

	/// Invert the quaternion. The transformation represented by the inverted quaternion will be the inverse of the
	/// transformation represented by the original quaternion.
	Quaternion &Invert( void );

	/// Calculates the weighted average of two quaternion. This is a high quality but slow blending function.
    Quaternion Slerp( const Quaternion &vTarget, float fWeight ) const;

	/// Sets the quaternion to represents the identical transformation.
    inline void SetIdentity( void ) 
	{ m_fW = 1.0; m_fX = m_fY = m_fZ = 0.0f; };

	/// Sets the quaternion to represents the zero transformation.
    void SetZero( void ) { m_fW = m_fX = m_fY = m_fZ = 0.0f; };

	/// Returns a given value stored in a quaternion. 
	float operator []( 
		int iIndex ///< [in] Index of the value, must be less than 4.
		) const;

	/// \brief Content of the quaternion represented by four scalar values.
	///
	/// These data members can be freely accessed. m_fW means the real part of the quaternion, while m_fX, m_fY and m_fZ
	/// are the components usually referred as i, j and k.
    float m_fW, m_fX, m_fY, m_fZ;
};

/// \brief The DualQuaternion class is used to represent rigid transformations in most cases. 
///
/// It is an alternative to the Matrix class to store transformations which are rigid, i.e. has only
/// rotation and translation part. In this case the dual quaternion is unit.
/// The advantage of the dual quaternion representation over the matrices is that
/// it is easier to do transformation blending, and it only needs 32 bytes in the memory.
/// Disadvangate is that it is limited to rigid transformations only (scaling is not supported).
class MBDLL_DECL DualQuaternion
{
public:
	/// Constructs a dual quaternion which represents the identical transformation.
    inline DualQuaternion( void ) { SetIdentity(); };

	/// Constructs a dual quaternion from two quaternions, using one as the real and the other one as the dual part.
    inline DualQuaternion( 
		const Quaternion &vReal, ///< [in] Real part.
		const Quaternion &vDual  ///< [in] Dual part.
		)
    { m_vReal = vReal; m_vDual = vDual; };

	/// Constructs a dual quaternion which represents a transformation which is a rotation around a given point
	/// in the space with a given rotation axis and a given vector.
    DualQuaternion( 
		const Vector &vPivot, ///< [in] Point in the space which is the center of the rotation.
		const Vector &vAxis, ///< [in] Axis of the rotation.
		float fAngle ///< [in] Angle of the rotation in radian.
		);

	/// Constructs a dual quaternion which represents a screw motion.
	DualQuaternion(
		float fAngle, ///< [in] Angle of the rotation in radian.
		float fPitch, ///< [in] 
		const Vector &vDirection,
		const Vector &vMoment 
		);

	/// Construct a dual quaternion which represents a rotation and a translation.
	DualQuaternion( 
		const Vector &vTranslation, ///< [in] Translation part of the transformation.
		const Quaternion &vRotation ///< [in] Rotation part of the transformation.
		);

	/// Constructs a dual quaternion from a matrix which represents a rigid transformation. @see Matrix::IsRigid()
	DualQuaternion( const Matrix &mRigid );

	/// Converts the dual quaternion into a matrix which represents the same transformation as the quaternion.
    Matrix ToMatrix( void ) const;

	/// Returns the translation represented by this dual quaternion.
	Vector Translation( void ) const;

	/// Transform a given point by the dual quaternion.
	Vector Transform( const Vector &vPoint ) const;

   	/// Returns the sum of two dual quaternions.
    DualQuaternion operator +( const DualQuaternion &vAddition ) const;

	/// Adds a dual quaternion to this dual quaternion.
    DualQuaternion &operator +=( const DualQuaternion &vAddition );

	/// Returns the substraction of two dual quaternions.
    DualQuaternion operator -( const DualQuaternion &vAddition ) const;

	/// Substracts a dual quaternion from this dual quaternion.
    DualQuaternion &operator -=( const DualQuaternion &vAddition );

	/// Returns the multiplication of two dual quaternions. The result is representing the transformation which is 
	/// the concatenation of the two transformation represented by the two dual quaternions.
    DualQuaternion operator *( const DualQuaternion &vMultiplier ) const;

	/// Multiplies a quaternion by another one.
    DualQuaternion &operator *=( const DualQuaternion &vMultiplier );

	/// Returns the product of the dual quaternion and a scalar value.
    DualQuaternion operator *( float fMultiplier ) const;

	/// Normalizes the dual quaternions. Only normalized dual quaternions are valid representations of
	/// rigid transformations.
    DualQuaternion &Normalize( void );

	/// Converts the transfomation represented by the qual quaternion into a screw motion.
	void ToScrew( float &fAngle, float &fPitch, Vector &vDirection, Vector &vMoment ) const;

	/// Calculates the power of the dual quaternion.
	DualQuaternion &Power( float fExponent );

	/// Calculates the weighted average of two dual quaternions. This is a good quality but slow blending
	/// function.
    DualQuaternion Slerp( const DualQuaternion &vTarget, float fWeight ) const;

	/// Conjugates the dual quaternion using the quaternion conjugation.
	DualQuaternion &Conjugate( void );

	/// Conjugates the dual quaternion using the dual conjugation.
	DualQuaternion &DualConjugate( void );

	/// Conjugates the dual quaternion by both the quaternion and dual conjugation. For unit dual quaternions 
	/// this is the same as Invert().
	inline DualQuaternion &DoubleConjugate( void ) { Conjugate(); DualConjugate(); return *this; };

	/// Inverts the dual quaternion. The result will represent a transformation which is the inverse of the transformation
	/// represented by the original dual quaternion.
	DualQuaternion &Invert( void );

	/// Sets the dual quaternion to represents the identical transformaion.
    void SetIdentity( void ) { m_vReal.SetIdentity(); m_vDual.SetZero(); };

	/// Returns the stored value inside the dual quaternion.
	float operator []( 
		int iIndex ///< [in] Index of the dual quaternion value, must be smaller than 8.
		) const;

	/// \brief Content of the dual quaterion as two regular quaternions.
	/// 
	/// These data members of the class can be accessed freely. The dual quaterion is represented with two quaternions, one beeing as
	/// the real part and the other is the dual part. In other words, m_vReal holds the rotation component, while the dual part is 
	/// responsible for the translation part.
    Quaternion m_vReal, m_vDual;

private:
	/// Creates a dual quaternion which represents a point in the space. This dual quaternion is
	/// used in some special operations.
	DualQuaternion( const Vector &vPoint );

};

/// Represents a line segment in 3d space.
class MBDLL_DECL Line
{
    Vector m_vStart, m_vEnd, m_vDirection;
    float m_fFactor;

public:

    /// Constructor, based on start and end points.
    Line( const Vector &vStart, const Vector &vEnd );

    /// \brief Returns the shortest distance between a given 
    /// point and this line.
    ///
    /// \b Note: The line is not logically extended to infinity 
    /// in this function.  Only points

    /// between the start and end point are considered part of the line.

    float RangeFrom( const Vector &vPoint );

};

/// \brief This base class represents any shape in 3d space.  Used for selection.
///
/// From this base class, there is no way to get information about what this 
/// object looks like, or how big it is. It is used primarily to determine if 
/// selection operations have touched the object in question.  Classes
/// derived from Selector must implement the IsTouchedBy() method.

///

/// Mudbox uses this class to provide
/// information about specific regions in the space. 
/// See MeshRenderer::Render for an example.

class MBDLL_DECL Selector : virtual public Node
{
    DECLARE_CLASS;

public:
    enum EState
    {
        eInside,
        eOutside,
        eTouching
    };

    /// Determines if a bounding box is touching this object or not.
    virtual EState IsTouchedBy( const AxisAlignedBoundingBox &cArea ) const;
};


inline MBDLL_DECL Vector operator *( const Vector &v, const Matrix &m )
{
    return Vector( 
        v.m_fX*m._11+v.m_fY*m._21+v.m_fZ*m._31+m._41,
        v.m_fX*m._12+v.m_fY*m._22+v.m_fZ*m._32+m._42,
        v.m_fX*m._13+v.m_fY*m._23+v.m_fZ*m._33+m._43 );
};

inline MBDLL_DECL Vector operator *( const Matrix &m, const Vector &v ) 
{
    return Vector( 
        v.m_fX*m._11+v.m_fY*m._12+v.m_fZ*m._13+m._14,
        v.m_fX*m._21+v.m_fY*m._22+v.m_fZ*m._23+m._24,
        v.m_fX*m._31+v.m_fY*m._32+v.m_fZ*m._33+m._34 );
};


/// A container class that holds a boolean and a float value. Can be used to
/// to enable/disable the usage of the float value. Typically represented by
/// a checkbox and a slider below that where the state of the checkbox enables
/// or disables the slider.
class CheckableFloat
{
public:
	CheckableFloat( void ) { m_bState = true; m_fValue = 0.0f; };
	CheckableFloat( bool bState, float fValue ) { m_bState = bState; m_fValue = fValue; };
	
	/// Sets the associated float value
	void SetValue( float f ) { m_fValue = f; };
	
	/// Retrieves the associated float value
	float Value( void ) const { return m_fValue; };
	
	/// Sets the associated boolean value 
	void SetState( bool b ) { m_bState = b; };
	
	/// Retrieves the associated boolean value
	bool State( void ) const { return m_bState; };
	
	inline bool operator ==( const CheckableFloat &cf ) const throw() { return State() == cf.State() && Value() == cf.Value(); };
	inline bool operator !=( const CheckableFloat &cf ) const throw() { return !operator ==( cf ); };
	inline CheckableFloat &operator =( const CheckableFloat &cf ) { m_bState = cf.m_bState; m_fValue = cf.m_fValue; return *this; };

	void Serialize( Stream &s )
	{
		s == m_bState == m_fValue;
	};


protected:
	bool m_bState;
	float m_fValue;
};

MBDLL_DECL AttributeWidget *CreateNewCheckableFloatWidget( QWidget *pParent, int iWidth, class AttributeCheckableFloat *pAttribute );

class AttributeCheckableFloat : public AttributeInstance<CheckableFloat>
{
public:
	AttributeCheckableFloat( Node *pOwner = 0, const QString &sID = "", const QString &sValueName = "" ) : AttributeInstance<CheckableFloat>( pOwner, sID )
		{ m_iSize = sizeof(CheckableFloat); m_sValueName = sValueName; };
	void SetValueName( const QString &sValueName ) { m_sValueName = sValueName; };
	QString ValueName( void ) const { return m_sValueName; };

	Attribute::AttributeType Type( void ) const { return typeUnknown; };
	AttributeWidget *CreateEditorWidget( QWidget *pParent, int iWidth ) { return CreateNewCheckableFloatWidget( pParent, iWidth, (AttributeCheckableFloat *)this ); };
	QString AsString( void ) const { return QString("%1 %2").arg(m_cValue.State() ? "true" : "false").arg(m_cValue.Value()); };
	void SetFromString( const QString &s )
	{
		m_cValue.SetState( s.section( ' ', 0, 0 ) == "true" ? true : false );
		m_cValue.SetValue( s.section( ' ', 1, 1 ).toFloat() );
	};

protected:
	QString m_sValueName;
};

typedef AttributeCheckableFloat acheckablefloat;

}; // end of namespace mudbox


#if defined(_MSC_VER)
#pragma warning(pop)
#endif
