TuttleOFX
1
|
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