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