/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield 
 *
 * This library is open source and may be redistributed and/or modified under  
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 * OpenSceneGraph Public License for more details.
*/
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//created by Sasa Bistrovic
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.

#ifndef OSG_DOFTRANSFORM
#define OSG_DOFTRANSFORM 1

//base class:
#include <osg/Transform>

namespace osg{
/** DOFTransform - encapsulates Multigen DOF behavior*/
class SG_EXPORT DOFTransform : public Transform
{
    public:
        /** constructor*/
        DOFTransform();

        /**copy constructor*/
        DOFTransform(const DOFTransform& dof, const CopyOp& copyop=CopyOp::SHALLOW_COPY):
            Transform(dof, copyop),
            _minHPR(dof._minHPR),
            _maxHPR(dof._maxHPR),
            _currentHPR(dof._currentHPR),
            _incrementHPR(dof._incrementHPR),
            _minTranslate(dof._minTranslate),
            _maxTranslate(dof._maxTranslate),
            _currentTranslate(dof._currentTranslate),
            _incrementTranslate(dof._incrementTranslate),
            _minScale(dof._minScale),
            _maxScale(dof._maxScale),
            _currentScale(dof._currentScale),
            _incrementScale(dof._incrementScale),
            _Put(dof._Put),
            _inversePut(dof._inversePut),
            _limitationFlags(dof._limitationFlags),
            _animationOn(dof._animationOn),
            _increasingFlags(dof._increasingFlags) {}

        META_Node(osg, DOFTransform);

        virtual DOFTransform* asDOFTransform() { return this; }
        virtual const DOFTransform* asDOFTransform() const { return this; }

        virtual void traverse(NodeVisitor& nv);

        void setMinHPR(const Vec3& hpr) { _minHPR = hpr;}
        const Vec3& getMinHPR() const { return _minHPR;}

        void setMaxHPR(const Vec3& hpr) {_maxHPR = hpr;}
        const Vec3& getMaxHPR() const { return _maxHPR;}

        void setIncrementHPR(const Vec3& hpr) {_incrementHPR = hpr;}
        const Vec3& getIncrementHPR() const { return _incrementHPR;}

        void setCurrentHPR(const Vec3& hpr) {_currentHPR = hpr;}
        const Vec3& getCurrentHPR() const {return _currentHPR;}

        void updateCurrentHPR(const Vec3& hpr);
        

        void setMinTranslate(const Vec3& translate) {_minTranslate = translate;}
        const Vec3& getMinTranslate() const { return _minTranslate;}
        
        void setMaxTranslate(const Vec3& translate) {_maxTranslate = translate;}
        const Vec3& getMaxTranslate() const { return _maxTranslate;}
        
        void setIncrementTranslate(const Vec3& translate) { _incrementTranslate = translate;}
        const Vec3& getIncrementTranslate() const { return _incrementTranslate;}

        void setCurrentTranslate(const Vec3& translate){ _currentTranslate = translate;}
        inline const Vec3& getCurrentTranslate() const { return _currentTranslate;}

        void updateCurrentTranslate(const Vec3& translate);


        void setMinScale(const Vec3& scale) { _minScale = scale;}
        const Vec3& getMinScale() const { return _minScale;}

        void setMaxScale(const Vec3& scale) { _maxScale = scale;}
        const Vec3& getMaxScale() const { return _maxScale;}

        void setIncrementScale(const Vec3& scale) { _incrementScale = scale;}
        const Vec3& getIncrementScale() const { return _incrementScale;}

        void setCurrentScale(const Vec3& scale) { _currentScale = scale;}
        inline const Vec3& getCurrentScale() const { return _currentScale;}

        void updateCurrentScale(const Vec3& scale);


        void setPutMatrix(const Matrix& put) { _Put = put;}
        inline const Matrix& getPutMatrix() const {return _Put;}

        void setInversePutMatrix(const Matrix& inversePut) { _inversePut = inversePut;}
        inline const Matrix& getInversePutMatrix() const {return _inversePut;}

        void setLimitationFlags(unsigned long flags) { _limitationFlags = flags;}
        inline unsigned long getLimitationFlags() const {return _limitationFlags;}


        inline void setAnimationOn(bool do_animate) {_animationOn = do_animate;}
        inline bool getAnimationOn() const {return _animationOn;}

        void animate();

        virtual bool computeLocalToWorldMatrix(Matrix& matrix,NodeVisitor* nv) const;

        virtual bool computeWorldToLocalMatrix(Matrix& matrix,NodeVisitor* nv) const;

    protected:

        virtual ~DOFTransform() {}

        Vec3 _minHPR;
        Vec3 _maxHPR;
        Vec3 _currentHPR;
        Vec3 _incrementHPR;

        Vec3 _minTranslate;
        Vec3 _maxTranslate;
        Vec3 _currentTranslate;
        Vec3 _incrementTranslate;

        Vec3 _minScale;
        Vec3 _maxScale;
        Vec3 _currentScale;
        Vec3 _incrementScale;

        Matrix _Put;
        Matrix _inversePut;

        unsigned long _limitationFlags;
        /* bits from left to right
        0 = x translation limited (2^31)
        1 = y translation limited (2^30)
        2 = z translation limited (2^29)
        3 = pitch limited (2^28)
        4 = roll limited (2^27)
        5 = yaw limited (2^26)
        6 = x scale limited (2^25)
        7 = y scale limited (2^24)
        8 = z scale limited (2^23)

        else reserved
        */

        bool _animationOn;
        /** flags indicating whether value is incerasing or decreasing in animation
        bits form right to left, 1 means increasing while 0 is decreasing
        0 = x translation
        1 = y translation
        2 = z translation
        3 = pitch
        4 = roll
        5 = yaw
        6 = x scale
        7 = y scale
        8 = z scale
        */
        unsigned short _increasingFlags;
};

}
#endif
