TuttleOFX  1
TuttleOFX/libraries/tuttle/src/tuttle/host/ofx/attribute/OfxhMultiDimParam.hpp
Go to the documentation of this file.
00001 #ifndef _TUTTLE_HOST_OFX_PARAM_MULTIDIMPARAM_HPP_
00002 #define _TUTTLE_HOST_OFX_PARAM_MULTIDIMPARAM_HPP_
00003 
00004 #include "OfxhParam.hpp"
00005 #include "OfxhKeyframeParam.hpp"
00006 #include "OfxhParamDescriptor.hpp"
00007 #include "OfxhParamSet.hpp"
00008 
00009 #include <boost/program_options/parsers.hpp>
00010 #include <boost/ptr_container/ptr_array.hpp>
00011 #include <boost/functional/hash.hpp>
00012 
00013 #include <string>
00014 #include <vector>
00015 
00016 namespace tuttle {
00017 namespace host {
00018 namespace ofx {
00019 namespace attribute {
00020 
00021 template <class T, std::size_t DIM>
00022 class OfxhMultiDimParam : public OfxhParam
00023         , public OfxhKeyframeParam
00024 {
00025 public:
00026         typedef T Type;
00027         typedef typename T::BaseType BaseType;
00028 
00029 protected:
00030         boost::ptr_array<T, DIM> _controls; // owns the sub-parameters
00031 
00032 #ifndef SWIG
00033         BOOST_STATIC_ASSERT( DIM != 0 );
00034 #endif
00035 
00036 public:
00037         OfxhMultiDimParam( const OfxhParamDescriptor& descriptor, const std::string& name, OfxhParamSet& setInstance )
00038         : OfxhParam( descriptor, name, setInstance )
00039         {}
00040 
00041         virtual ~OfxhMultiDimParam()
00042         {}
00043 
00044         inline std::size_t getSize() const
00045         {
00046                 return _controls.size();
00047         }
00048 
00049         void setValueFromExpression( const std::string& value, const ofx::attribute::EChange change ) OFX_EXCEPTION_SPEC
00050         {
00051                 std::vector<std::string> allExp = boost::program_options::split_unix( value, "," );
00052 
00053                 if( allExp.size() == 1 )
00054                 {
00055                         for( std::size_t i = 0; i < getSize(); ++i )
00056                         {
00057                                 _controls[i].setValueFromExpression( value, change );
00058                         }
00059                 }
00060                 else
00061                 {
00062                         if( getSize() != allExp.size() )
00063                         {
00064                                 BOOST_THROW_EXCEPTION( exception::Value()
00065                                         << exception::user() + "Set " + allExp.size() + " values on a multidimensional parameter of size " + DIM + "."
00066                                         );
00067                         }
00068                         for( std::size_t i = 0; i < getSize(); ++i )
00069                         {
00070                                 _controls[i].setValueFromExpression( allExp[i], change );
00071                         }
00072                 }
00073                 this->paramChanged( change );
00074         }
00075 
00076 
00077 protected:
00078         // Deriving implementatation needs to overide these
00079         inline virtual void getValueAtIndex( const std::size_t index, BaseType& outDst ) const OFX_EXCEPTION_SPEC
00080         {
00081                 if( index >= getSize() )
00082                 {
00083                         BOOST_THROW_EXCEPTION( exception::BadIndex()
00084                                 << exception::user() + "Get value at index "+index+" on a multidimensional parameter of size " + DIM + "."
00085                                 );
00086                 }
00087                 _controls[index].getValue( outDst );
00088         }
00089 
00090         inline virtual void getValueAtTimeAndIndex( const OfxTime time, const std::size_t index, BaseType& outDst ) const OFX_EXCEPTION_SPEC
00091         {
00092                 if( index >= getSize() )
00093                 {
00094                         BOOST_THROW_EXCEPTION( exception::BadIndex()
00095                                 << exception::user() + "Get value at index "+index+" on a multidimensional parameter of size " + DIM + "."
00096                                 );
00097                 }
00098                 _controls[index].getValueAtTime( time, outDst );
00099         }
00100 
00101 public:
00102 #ifndef SWIG
00103         void copy( const OfxhMultiDimParam& p ) OFX_EXCEPTION_SPEC
00104         {
00105                 for( std::size_t index = 0; index < DIM; ++index )
00106                 {
00107                         _controls[index].copy( p._controls[index] );
00108                 }
00109         }
00110 
00111         void copy( const OfxhParam& p ) OFX_EXCEPTION_SPEC
00112         {
00113                 const OfxhMultiDimParam& param = dynamic_cast<const OfxhMultiDimParam&>( p );
00114 
00115                 copy( param );
00116         }
00117 #endif
00118 
00119         inline void setValue( const BaseType& value, const ofx::attribute::EChange change ) OFX_EXCEPTION_SPEC
00120         {
00121                 for( std::size_t i = 0; i < getSize(); ++i )
00122                 {
00123                         _controls[i].setValue( value, eChangeNone );
00124                 }
00125                 this->paramChanged( change );
00126         }
00127         
00128         inline void setValueAtTime( const OfxTime time, const BaseType& value, const ofx::attribute::EChange change ) OFX_EXCEPTION_SPEC
00129         {
00130                 for( std::size_t i = 0; i < getSize(); ++i )
00131                 {
00132                         _controls[i].setValueAtTime( time, value, eChangeNone );
00133                 }
00134                 this->paramChanged( change );
00135         }
00136 
00137         inline virtual void setValueAtIndex( const std::size_t index, const BaseType& value, const EChange change ) OFX_EXCEPTION_SPEC
00138         {
00139                 if( index >= getSize() )
00140                 {
00141                         BOOST_THROW_EXCEPTION( exception::BadIndex()
00142                                 << exception::user() + "Get value at index "+index+" on a multidimensional parameter of size " + DIM + "."
00143                                 );
00144                 }
00145                 _controls[index].setValue( value, eChangeNone );
00146                 this->paramChanged( change );
00147         }
00148 
00149         inline virtual void setValueAtTimeAndIndex( const OfxTime time, const std::size_t index, const BaseType& value, const EChange change ) OFX_EXCEPTION_SPEC
00150         {
00151                 if( index >= getSize() )
00152                 {
00153                         BOOST_THROW_EXCEPTION( exception::BadIndex()
00154                                 << exception::user() + "Get value at index "+index+" on a multidimensional parameter of size " + DIM + "."
00155                                 );
00156                 }
00157                 _controls[index].setValueAtTime( time, value, eChangeNone );
00158                 this->paramChanged( change );
00159         }
00160 
00161         inline virtual void setValue( const std::vector<BaseType>& values, const EChange change ) OFX_EXCEPTION_SPEC
00162         {
00163                 if( values.size() != getSize() )
00164                 {
00165                         BOOST_THROW_EXCEPTION( exception::BadIndex()
00166                                 << exception::user() + "Set "+values.size()+" values on a multidimensional parameter of size " + DIM + "."
00167                                 );
00168                 }
00169                 for( std::size_t i = 0; i < getSize(); ++i )
00170                 {
00171                         _controls[i].setValue( values[i], eChangeNone );
00172                 }
00173                 this->paramChanged( change );
00174         }
00175 
00176         inline virtual void setValueAtTime( const OfxTime time, const std::vector<BaseType>& values, const EChange change ) OFX_EXCEPTION_SPEC
00177         {
00178                 if( values.size() != getSize() )
00179                 {
00180                         BOOST_THROW_EXCEPTION( exception::BadIndex()
00181                                 << exception::user() + "Set "+values.size()+" values on a multidimensional parameter of size " + DIM + "."
00182                                 );
00183                 }
00184                 for( std::size_t i = 0; i < getSize(); ++i )
00185                 {
00186                         _controls[i].setValueAtTime( time, values[i], eChangeNone );
00187                 }
00188                 this->paramChanged( change );
00189         }
00190         
00191         // derived class does not need to implement, default is an approximation
00192         inline virtual void deriveAtIndex( const OfxTime time, const std::size_t index, BaseType& outDst ) const OFX_EXCEPTION_SPEC
00193         {
00194                 if( index >= getSize() )
00195                 {
00196                         BOOST_THROW_EXCEPTION( exception::BadIndex()
00197                                 << exception::user() + "Derive value at index "+index+" on a multidimensional parameter of size " + DIM + "."
00198                                 );
00199                 }
00200                 _controls[index].derive( time, outDst );
00201         }
00202 
00203         inline virtual void integrateAtIndex( const OfxTime time1, const OfxTime time2, const std::size_t index, BaseType& outDst ) const OFX_EXCEPTION_SPEC
00204         {
00205                 if( index >= getSize() )
00206                 {
00207                         BOOST_THROW_EXCEPTION( exception::BadIndex()
00208                                 << exception::user() + "Integrate value at index "+index+" on a multidimensional parameter of size " + DIM + "."
00209                                 );
00210                 }
00211                 _controls[index].integrate( time1, time2, outDst );
00212         }
00213 
00214 #ifndef SWIG
00215         /// implementation of var args function
00216         virtual void getV( va_list arg ) const OFX_EXCEPTION_SPEC
00217         {
00218                 for( std::size_t index = 0; index < DIM; ++index )
00219                 {
00220                         BaseType* v = va_arg( arg, BaseType* );
00221                         BOOST_ASSERT( v );
00222                         _controls[index].getValue( *v );
00223                 }
00224         }
00225 
00226         /// implementation of var args function
00227         virtual void getV( const OfxTime time, va_list arg ) const OFX_EXCEPTION_SPEC
00228         {
00229                 for( std::size_t index = 0; index < DIM; ++index )
00230                 {
00231                         BaseType* v = va_arg( arg, BaseType* );
00232                         _controls[index].getValueAtTime( time, *v );
00233                 }
00234         }
00235 
00236         /// implementation of var args function
00237         virtual void setV( va_list arg, const EChange change ) OFX_EXCEPTION_SPEC
00238         {
00239                 for( std::size_t index = 0; index < DIM; ++index )
00240                 {
00241                         BaseType v = va_arg( arg, BaseType );
00242                         _controls[index].setValue( v, eChangeNone );
00243                 }
00244                 this->paramChanged( change );
00245         }
00246 
00247         /// implementation of var args function
00248         virtual void setV( const OfxTime time, va_list arg, const EChange change ) OFX_EXCEPTION_SPEC
00249         {
00250                 for( std::size_t index = 0; index < DIM; ++index )
00251                 {
00252                         BaseType v = va_arg( arg, BaseType );
00253                         _controls[index].setValueAtTime( time, v, eChangeNone );
00254                 }
00255                 this->paramChanged( change );
00256         }
00257 
00258         /// implementation of var args function
00259         virtual void deriveV( const OfxTime time, va_list arg ) const OFX_EXCEPTION_SPEC
00260         {
00261                 for( std::size_t index = 0; index < DIM; ++index )
00262                 {
00263                         BaseType* v = va_arg( arg, BaseType* );
00264                         _controls[index].derive( time, *v );
00265                 }
00266         }
00267 
00268         /// implementation of var args function
00269         virtual void integrateV( const OfxTime time1, const OfxTime time2, va_list arg ) const OFX_EXCEPTION_SPEC
00270         {
00271                 for( std::size_t index = 0; index < DIM; ++index )
00272                 {
00273                         BaseType* v = va_arg( arg, BaseType* );
00274                         BOOST_ASSERT( v );
00275                         _controls[index].integrate( time1, time2, *v );
00276                 }
00277         }
00278 #endif
00279 
00280         bool paramTypeHasData() const { return true; }
00281         
00282         std::size_t getHashAtTime( const OfxTime time ) const
00283         {
00284                 std::size_t seed = 0;
00285                 for( std::size_t i = 0; i < getSize(); ++i )
00286                 {
00287                         BaseType value = 0;
00288                         getValueAtTimeAndIndex( time, i, value );
00289                         boost::hash_combine( seed, value );
00290                 }
00291                 return seed;
00292         }
00293         
00294         std::ostream& displayValues( std::ostream& os ) const
00295         {
00296                 os << "[";
00297                 for( std::size_t index = 0; index < DIM-1; ++index )
00298                 {
00299                         _controls[index].displayValues( os );
00300                         os << ",";
00301                 }
00302                 _controls[DIM-1].displayValues( os );
00303                 os << "]";
00304                 return os;
00305         }
00306 
00307 };
00308 
00309 }
00310 }
00311 }
00312 }
00313 
00314 #endif
00315