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