nux-0.9.48
|
00001 /* 00002 * Copyright 2010 Inalogic® Inc. 00003 * 00004 * This program is free software: you can redistribute it and/or modify it 00005 * under the terms of the GNU Lesser General Public License, as 00006 * published by the Free Software Foundation; either version 2.1 or 3.0 00007 * of the License. 00008 * 00009 * This program is distributed in the hope that it will be useful, but 00010 * WITHOUT ANY WARRANTY; without even the implied warranties of 00011 * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR 00012 * PURPOSE. See the applicable version of the GNU Lesser General Public 00013 * License for more details. 00014 * 00015 * You should have received a copy of both the GNU Lesser General Public 00016 * License along with this program. If not, see <http://www.gnu.org/licenses/> 00017 * 00018 * Authored by: Jay Taoko <jaytaoko@inalogic.com> 00019 * 00020 */ 00021 00022 00023 #ifndef SPLINECURVEEDITOR_H 00024 #define SPLINECURVEEDITOR_H 00025 00026 #include "PaintLayer.h" 00027 00028 namespace nux 00029 { 00030 00031 class CubicSpline; 00032 class SplineKnot; 00033 class GLSh_DrawFunction; 00034 00035 class SplineKnot 00036 { 00037 public: 00038 class Knot 00039 { 00040 public: 00041 Knot (double kX, double kY, bool selected = false, bool excluded = false) 00042 : m_IsSelected (selected) 00043 , m_IsExcluded (excluded) 00044 { 00045 x = kX; 00046 y = kY; 00047 } 00048 00049 bool operator == (const Knot &knot) 00050 { 00051 return ( (x == knot.x) && (y == knot.y) ); 00052 } 00053 00054 bool operator != (const Knot &knot) 00055 { 00056 return ( (x != knot.x) || (y != knot.y) ); 00057 } 00058 00059 bool operator > (const Knot &knot) const 00060 { 00061 return (x > knot.x); 00062 } 00063 00064 bool operator < (const Knot &knot) const 00065 { 00066 return (x < knot.x); 00067 } 00068 00069 double GetX() const 00070 { 00071 return x; 00072 } 00073 double GetY() const 00074 { 00075 return y; 00076 } 00077 void SetX (double d) 00078 { 00079 x = d; 00080 } 00081 void SetY (double d) 00082 { 00083 y = d; 00084 } 00085 private: 00086 double x, y; 00087 bool m_IsSelected; 00088 bool m_IsExcluded; 00089 00090 friend class SplineKnot; 00091 }; 00092 00093 public : 00094 00095 SplineKnot() 00096 { 00097 // There must always be at least two points for the spline interpolation to work 00098 // m_knot.push_back(Knot(0.0, 0.0)); 00099 // m_knot.push_back(Knot(1.0, 1.0)); 00100 } 00101 00102 SplineKnot (const SplineKnot &Other) 00103 { 00104 m_knot = Other.m_knot; 00105 } 00106 00107 SplineKnot &operator = (const SplineKnot &Other) 00108 { 00109 Reset(); 00110 m_knot = Other.m_knot; 00111 return *this; 00112 } 00113 00114 // void operator = (const SplineKnot* Other) 00115 // { 00116 // if(Other == 0) 00117 // return 00118 // Reset(); 00119 // m_knot = Other->m_knot; 00120 // //return *this; 00121 // } 00122 00123 void AddKnot (double x, double y, bool selected = false) 00124 { 00125 std::vector<Knot>::iterator it; 00126 00127 // Check if the exacte same knot is already in. 00128 it = std::find (m_knot.begin(), m_knot.end(), Knot (x, y) ); 00129 00130 if (it != m_knot.end() ) 00131 { 00132 // already in 00133 return; 00134 } 00135 00136 // Check if a knot is already in with the same x. 00137 for (it = m_knot.begin(); it != m_knot.end(); it++) 00138 { 00139 if ( (*it).x == x) 00140 { 00141 (*it).y = y; 00142 (*it).m_IsSelected = selected; 00143 return; 00144 } 00145 } 00146 00147 m_knot.push_back (Knot (x, y, selected) ); 00148 std::sort (m_knot.begin(), m_knot.end(), std::less<SplineKnot::Knot>() ); 00149 } 00150 00151 bool isKnotSelected (int i) const 00152 { 00153 if (i >= GetNumKnot() || i < 0) 00154 { 00155 return false; 00156 } 00157 00158 return m_knot[i].m_IsSelected; 00159 } 00160 00161 const Knot &operator [] (int i) const 00162 { 00163 return m_knot[i]; 00164 } 00165 00166 Knot &operator [] (int i) 00167 { 00168 return m_knot[i]; 00169 } 00170 00171 void EraseKnot (int i) 00172 { 00173 if (m_knot.size() <= 2) 00174 { 00175 // There must always be at least two points for the spline interpolation to work 00176 return; 00177 } 00178 00179 if (i >= GetNumKnot() || i < 0) 00180 { 00181 return; 00182 } 00183 00184 std::vector<Knot>::iterator it = m_knot.begin(); 00185 it += i; 00186 m_knot.erase (it); 00187 } 00188 00189 void EraseSelectedKnot() 00190 { 00191 if (m_knot.size() <= 2) 00192 { 00193 // There must always be at least two points for the spline interpolation to work 00194 return; 00195 } 00196 00197 // Traverse the array and erase selected knots. 00198 bool finish = false; 00199 00200 do 00201 { 00202 // loop many times to avoid erasing iterators while traversing the array. This is not efficient! 00203 bool found = false; 00204 std::vector<Knot>::iterator it; 00205 00206 for (it = m_knot.begin(); it != m_knot.end(); it++) 00207 { 00208 if ( (*it).m_IsSelected) 00209 { 00210 m_knot.erase (it); 00211 found = TRUE; 00212 break; 00213 } 00214 } 00215 00216 if (!found) 00217 finish = TRUE; 00218 } 00219 while ( (!finish) && (m_knot.size() > 2) ); 00220 } 00221 00222 void SelectKnot (int i, bool b) 00223 { 00224 m_knot[i].m_IsSelected = b; 00225 } 00226 00227 t_u32 GetNumSelectedKnot() 00228 { 00229 t_u32 n = 0; 00230 std::vector<Knot>::iterator it; 00231 00232 for (t_u32 i = 0; i < (t_u32) m_knot.size(); i++) 00233 { 00234 if (m_knot[i].m_IsSelected) 00235 n++; 00236 } 00237 00238 return n; 00239 } 00240 00241 void SelectAllKnot() 00242 { 00243 std::vector<Knot>::iterator it; 00244 00245 for (it = m_knot.begin(); it != m_knot.end(); it++) 00246 { 00247 (*it).m_IsSelected = TRUE; 00248 } 00249 } 00250 00251 void UnSelectAllKnot() 00252 { 00253 std::vector<Knot>::iterator it; 00254 00255 for (it = m_knot.begin(); it != m_knot.end(); it++) 00256 { 00257 (*it).m_IsSelected = false; 00258 } 00259 } 00260 00261 const std::vector<double> GetXArray() 00262 { 00263 std::vector<double> array; 00264 std::vector<Knot>::iterator it; 00265 00266 for (it = m_knot.begin(); it != m_knot.end(); it++) 00267 { 00268 if (! (*it).m_IsExcluded) 00269 array.push_back ( (*it).x); 00270 } 00271 00272 return array; 00273 } 00274 00275 00276 const std::vector<double> GetYArray() 00277 { 00278 std::vector<double> array; 00279 std::vector<Knot>::iterator it; 00280 00281 for (it = m_knot.begin(); it != m_knot.end(); it++) 00282 { 00283 if (! (*it).m_IsExcluded) 00284 array.push_back ( (*it).y); 00285 } 00286 00287 return array; 00288 } 00289 00290 int GetNumKnot() const 00291 { 00292 return (int) m_knot.size(); 00293 } 00294 Knot GetKnot (int i) const 00295 { 00296 return m_knot[i]; 00297 } 00298 00302 void Reset() 00303 { 00304 m_knot.clear(); 00305 AddKnot (0, 0); 00306 AddKnot (1, 1); 00307 } 00308 private: 00309 std::vector<Knot> m_knot; 00310 }; 00311 00312 typedef float (*SplineFunctionCallback) (float); 00313 00314 class SplineCurveEditor : public View 00315 { 00316 public: 00317 SplineCurveEditor (NUX_FILE_LINE_PROTO); 00318 ~SplineCurveEditor(); 00319 void SetControlPoints (const SplineKnot &splineKnot); 00320 const SplineKnot &GetControlPoints() const; 00321 virtual long ProcessEvent (IEvent &ievent, long TraverseInfo, long ProcessEventInfo); 00322 virtual void Draw (GraphicsEngine &GfxContext, bool force_draw); 00323 virtual void DrawContent (GraphicsEngine &GfxContext, bool force_draw); 00324 virtual void PostDraw (GraphicsEngine &GfxContext, bool force_draw); 00325 00326 double Eval (double t); 00327 00328 void RecvMouseUp (int x, int y, unsigned long button_flags, unsigned long key_flags); 00329 void RecvMouseDown (int x, int y, unsigned long button_flags, unsigned long key_flags); 00330 void RecvMouseDrag (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags); 00331 void RecvKeyEvent ( 00332 GraphicsEngine &GfxContext, /*Graphics Context for text operation*/ 00333 unsigned long eventType , /*event type*/ 00334 unsigned long keysym , /*event keysym*/ 00335 unsigned long state , /*event state*/ 00336 const TCHAR* character , /*character*/ 00337 unsigned short keyCount /*key repeat count*/ 00338 ); 00339 00340 sigc::signal< void, SplineCurveEditor * > sigCurveChange; 00341 00345 void Reset(); 00346 00347 int GetNumKnot() const 00348 { 00349 return (int) m_control_knot.GetNumKnot(); 00350 } 00351 SplineKnot::Knot GetKnot (int i) const 00352 { 00353 return m_control_knot.GetKnot (i); 00354 } 00355 void AddKnot (double x, double y, bool selected = false); 00356 00357 protected: 00358 void InitializeWidgets(); 00359 void InitializeLayout(); 00360 void DestroyLayout(); 00361 00362 private: 00363 ObjectPtr<IOpenGLBaseTexture> m_Texture; 00364 GLSh_DrawFunction *m_DrawFunctionShader; 00365 AbstractPaintLayer *m_Background; 00366 00367 void SetXAxisBounds (float minX, float maxX); 00368 void SetYAxisBounds (float minY, float maxY); 00369 void SetFunctionCallback (SplineFunctionCallback f); 00370 float EvalFunction (float x); 00371 void UpdateGraph(); 00372 00373 SplineKnot m_control_knot; 00374 00375 float m_minX, m_minY, m_maxX, m_maxY; 00376 SplineFunctionCallback m_FunctionCallback; 00377 00378 float hit_point_dx; 00379 float hit_point_dy; 00380 00381 CubicSpline m_CubicSpline; 00382 }; 00383 00384 } 00385 00386 #endif // SPLINECURVEEDITOR_H