TuttleOFX
1
|
00001 #ifndef _TUTTLE_PLUGIN_INTERACT_PARAMRECTANGLEFROMCENTERSIZE_HPP_ 00002 #define _TUTTLE_PLUGIN_INTERACT_PARAMRECTANGLEFROMCENTERSIZE_HPP_ 00003 00004 #include "InteractObject.hpp" 00005 #include "PointInteract.hpp" 00006 #include "ParamPoint.hpp" 00007 #include "overlay.hpp" 00008 #include <terry/globals.hpp> 00009 #include <tuttle/plugin/ofxToGil/point.hpp> 00010 00011 #include <ofxsParam.h> 00012 00013 #include <boost/lexical_cast.hpp> 00014 00015 namespace tuttle { 00016 namespace plugin { 00017 namespace interact { 00018 00019 template<ECoordinateSystem coord> 00020 struct CoordinateSystemNotCentered 00021 { 00022 static const ECoordinateSystem value = coord; 00023 }; 00024 template<> 00025 struct CoordinateSystemNotCentered<eCoordinateSystemXXcn> 00026 { 00027 static const ECoordinateSystem value = eCoordinateSystemXXn; 00028 }; 00029 template<> 00030 struct CoordinateSystemNotCentered<eCoordinateSystemXYc> 00031 { 00032 static const ECoordinateSystem value = eCoordinateSystemXYc; 00033 }; 00034 00035 template<class TFrame, ECoordinateSystem coord> 00036 class ParamRectangleFromCenterSize : public PointInteract 00037 { 00038 public: 00039 ParamRectangleFromCenterSize( const InteractInfos& infos, OFX::Double2DParam* paramCenter, OFX::Double2DParam* paramSize, const TFrame& frame ); 00040 ~ParamRectangleFromCenterSize(); 00041 00042 private: 00043 ParamPoint<TFrame, coord> _center; 00044 ParamPoint<TFrame, CoordinateSystemNotCentered<coord>::value> _size; 00045 TFrame _frame; 00046 00047 /** 00048 * T 00049 * TL___________ TR 00050 * | | 00051 * L | C | R 00052 * | | 00053 * |_________| 00054 * BL BR 00055 * B 00056 */ 00057 enum ESelectType 00058 { 00059 eSelectTypeNone, 00060 eSelectTypeT, 00061 eSelectTypeL, 00062 eSelectTypeR, 00063 eSelectTypeB, 00064 eSelectTypeTL, 00065 eSelectTypeTR, 00066 eSelectTypeBL, 00067 eSelectTypeBR, 00068 eSelectTypeC 00069 }; 00070 static std::string mapESelectTypeToString( const ESelectType& s ) 00071 { 00072 switch( s ) 00073 { 00074 case eSelectTypeNone: 00075 return "eSelectTypeNone"; 00076 case eSelectTypeT: 00077 return "eSelectTypeT"; 00078 case eSelectTypeL: 00079 return "eSelectTypeL"; 00080 case eSelectTypeR: 00081 return "eSelectTypeR"; 00082 case eSelectTypeB: 00083 return "eSelectTypeB"; 00084 case eSelectTypeTL: 00085 return "eSelectTypeTL"; 00086 case eSelectTypeTR: 00087 return "eSelectTypeTR"; 00088 case eSelectTypeBL: 00089 return "eSelectTypeBL"; 00090 case eSelectTypeBR: 00091 return "eSelectTypeBR"; 00092 case eSelectTypeC: 00093 return "eSelectTypeC"; 00094 } 00095 BOOST_THROW_EXCEPTION( std::invalid_argument( "ESelectType: " + boost::lexical_cast<std::string>( s ) ) ); 00096 return ""; 00097 } 00098 00099 ESelectType _selectType; 00100 00101 public: 00102 bool draw( const OFX::DrawArgs& args ) const; 00103 00104 ESelectType selectType( const OFX::PenArgs& args ) const; 00105 00106 MotionType intersect( const OFX::PenArgs& args ); 00107 bool isIn( const OfxRectD& ); 00108 00109 Point2 getPoint() const 00110 { 00111 return _center.getPoint(); 00112 } 00113 00114 void setPoint( const Scalar x, const Scalar y ) 00115 { 00116 if( _selectType == eSelectTypeC ) 00117 return _center.setPoint( x, y ); 00118 00119 Point2 pCenter = _center.getPoint(); 00120 Point2 pSize = _size.getPoint(); 00121 00122 OfxRectD frameRect = _frame.getFrame( this->getTime() ); 00123 Point2 mouse( x - frameRect.x1, y - frameRect.y1 ); // relative to frame 00124 mouse = mouse - pCenter; // relative to pointCenter 00125 switch( _selectType ) 00126 { 00127 case eSelectTypeL: 00128 { 00129 _size.setPoint( std::abs( mouse.x ), pSize.y ); 00130 break; 00131 } 00132 case eSelectTypeR: 00133 { 00134 _size.setPoint( std::abs( mouse.x ), pSize.y ); 00135 break; 00136 } 00137 case eSelectTypeT: 00138 { 00139 _size.setPoint( pSize.x, std::abs( mouse.y ) ); 00140 break; 00141 } 00142 case eSelectTypeB: 00143 { 00144 _size.setPoint( pSize.x, std::abs( mouse.y ) ); 00145 break; 00146 } 00147 case eSelectTypeTL: 00148 { 00149 // todo 00150 break; 00151 } 00152 case eSelectTypeTR: 00153 { 00154 // todo 00155 break; 00156 } 00157 case eSelectTypeBL: 00158 { 00159 // todo 00160 break; 00161 } 00162 case eSelectTypeBR: 00163 { 00164 // todo 00165 break; 00166 } 00167 case eSelectTypeC: 00168 { 00169 assert( false ); 00170 break; 00171 } 00172 case eSelectTypeNone: 00173 { 00174 assert( false ); 00175 break; 00176 } 00177 } 00178 } 00179 00180 }; 00181 00182 template<class TFrame, ECoordinateSystem coord> 00183 ParamRectangleFromCenterSize<TFrame, coord>::ParamRectangleFromCenterSize( const InteractInfos& infos, OFX::Double2DParam* paramCenter, OFX::Double2DParam* paramSize, const TFrame& frame ) 00184 : PointInteract( infos ) 00185 , _center( infos, paramCenter, frame ) 00186 , _size( infos, paramSize, frame ) 00187 , _frame( frame ) 00188 {} 00189 00190 template<class TFrame, ECoordinateSystem coord> 00191 ParamRectangleFromCenterSize<TFrame, coord>::~ParamRectangleFromCenterSize() {} 00192 00193 template<class TFrame, ECoordinateSystem coord> 00194 bool ParamRectangleFromCenterSize<TFrame, coord>::draw( const OFX::DrawArgs& args ) const 00195 { 00196 _center.draw( args ); 00197 overlay::displayPointRect( _center.getPoint(), _size.getPoint() ); 00198 return true; 00199 } 00200 00201 template<class TFrame, ECoordinateSystem coord> 00202 typename ParamRectangleFromCenterSize<TFrame, coord>::ESelectType ParamRectangleFromCenterSize<TFrame, coord>::selectType( const OFX::PenArgs& args ) const 00203 { 00204 const Point2 p = ofxToGil( args.penPosition ); 00205 const double margeCanonical = this->getMarge() * args.pixelScale.x; 00206 00207 TUTTLE_LOG_VAR( TUTTLE_TRACE, this->getMarge() ); 00208 TUTTLE_LOG_VAR( TUTTLE_TRACE, args.pixelScale.x ); 00209 TUTTLE_LOG_VAR( TUTTLE_TRACE, margeCanonical ); 00210 const OfxRectD rod = _frame.getFrame( this->getTime() ); 00211 //const Point2 rodSize( rod.x2 - rod.x1, rod.y2 - rod.y1 ); 00212 const Point2 pCenter = _center.getPoint(); 00213 const Point2 pSize = _size.getPoint(); 00214 const Point2 min = pCenter - pSize; 00215 const Point2 max = pCenter + pSize; 00216 00217 if( std::abs( min.x - p.x ) < margeCanonical ) // left 00218 { 00219 if( std::abs( min.y - p.y ) < margeCanonical ) // top 00220 return eSelectTypeTL; 00221 else if( std::abs( max.y - p.y ) < margeCanonical ) // bottom 00222 return eSelectTypeBL; 00223 else if( p.y > min.y && p.y < max.y ) 00224 return eSelectTypeL; 00225 } 00226 else if( std::abs( max.x - p.x ) < margeCanonical ) // right 00227 { 00228 if( std::abs( max.y - p.y ) < margeCanonical ) // bottom 00229 return eSelectTypeBR; 00230 else if( std::abs( min.y - p.y ) < margeCanonical ) // top 00231 return eSelectTypeTR; 00232 else if( p.y > min.y && p.y < max.y ) 00233 return eSelectTypeR; 00234 } 00235 else if( std::abs( min.y - p.y ) < margeCanonical && p.x > min.x && p.x < max.x ) 00236 return eSelectTypeT; 00237 else if( std::abs( max.y - p.y ) < margeCanonical && p.x > min.x && p.x < max.x ) 00238 return eSelectTypeB; 00239 return eSelectTypeNone; 00240 } 00241 00242 template<class TFrame, ECoordinateSystem coord> 00243 MotionType ParamRectangleFromCenterSize<TFrame, coord>::intersect( const OFX::PenArgs& args ) 00244 { 00245 // intersect center point 00246 MotionType m = _center.intersect( args ); 00247 if( m._mode != eMotionNone ) 00248 { 00249 TUTTLE_TLOG( TUTTLE_TRACE, "intersect center." ); 00250 _selectType = eSelectTypeC; 00251 return m; 00252 } 00253 // intersect borders 00254 _selectType = selectType( args ); 00255 TUTTLE_TLOG( TUTTLE_TRACE, "_selectType : " << mapESelectTypeToString( _selectType ) ); 00256 if( _selectType != eSelectTypeNone ) 00257 { 00258 m._mode = eMotionTranslate; 00259 m._axis = eAxisXY; 00260 return m; 00261 } 00262 m._mode = eMotionNone; 00263 m._axis = eAxisNone; 00264 return m; 00265 } 00266 00267 template<class TFrame, ECoordinateSystem coord> 00268 bool ParamRectangleFromCenterSize<TFrame, coord>::isIn( const OfxRectD& rect ) 00269 { 00270 _selectType = eSelectTypeNone; 00271 Point2 pCenter = _center.getPoint(); 00272 Point2 pSize = _size.getPoint(); 00273 Point2 min = pCenter - pSize; 00274 Point2 max = pCenter + pSize; 00275 if( rect.x1 <= min.x && rect.x2 >= max.x && 00276 rect.y1 <= min.y && rect.y2 >= max.y ) 00277 { 00278 return true; 00279 } 00280 return false; 00281 } 00282 00283 } 00284 } 00285 } 00286 00287 #endif 00288