nux-1.16.0
BezierCurveControl2.cpp
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 #include "Nux.h"
00024 
00025 #include "BezierCurveControl2.h"
00026 #include "NuxCore/Math/Bezier.h"
00027 
00028 namespace nux
00029 {
00030 
00031   static const int KNOT_SIZE = 2;
00032   static const int KNOT_HIT_TEST = 4;
00033   static const int CURVE_DEGREE = 3;
00034   static const int GRAPH_MARGIN = 2;
00035   static const int UNIT_REFERENCE = 15;
00036 
00037   unsigned long S_KEY = 0;
00038 
00039   BezierCurveControl2::BezierCurveControl2 (NUX_FILE_LINE_DECL)
00040     :   View (NUX_FILE_LINE_PARAM)
00041     ,   m_minX (-0.10f),
00042     m_minY (-0.100f),
00043     m_maxX (1.100f),
00044     m_maxY (1.100f),
00045     m_FunctionCallback (0),
00046     m_bControlPointSelected (0),
00047     m_bPanningEnabled (true),
00048     m_bZoomingEnabled (true)
00049   {
00050     SetMinimumSize (180, 180);
00051 
00052     m_control_knot.push_back (Knot2 (0.0f, 0.0f) );
00053     m_control_knot.push_back (Knot2 (0.1f, 0.0f) );
00054     m_control_knot.push_back (Knot2 (0.7f, 0.9f) );
00055     m_control_knot.push_back (Knot2 (1.0f, 1.0f) );
00056 
00057     mouse_down.connect (sigc::mem_fun (this, &BezierCurveControl2::RecvMouseDown) );
00058     mouse_up.connect (sigc::mem_fun (this, &BezierCurveControl2::RecvMouseUp) );
00059     mouse_drag.connect (sigc::mem_fun (this, &BezierCurveControl2::RecvMouseDrag) );
00060 
00061     key_down.connect (sigc::mem_fun (this, &BezierCurveControl2::RecvKeyEvent) );
00062 
00063     NTextureData image;
00064     MakeCheckBoardImage (image.GetSurface (0), 64, 64, Color (0xff323232), Color (0xff535353), 8, 8);
00065     BaseTexture* m_CheckboardPattern = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableTexture ();
00066     m_CheckboardPattern->Update (&image);
00067 
00068     TexCoordXForm texxform;
00069     texxform.SetTexCoordType (TexCoordXForm::OFFSET_COORD);
00070     texxform.SetWrap (TEXWRAP_REPEAT, TEXWRAP_REPEAT);
00071     m_Background = new TextureLayer (m_CheckboardPattern->GetDeviceTexture(), texxform, color::White);
00072 
00073     m_CheckboardPattern->UnReference ();
00074   }
00075 
00076   BezierCurveControl2::~BezierCurveControl2()
00077   {
00078     delete m_Background;
00079   }
00080 
00081   long BezierCurveControl2::ProcessEvent (IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
00082   {
00083     long ret = TraverseInfo;
00084 
00085     if (ievent.e_event == NUX_MOUSE_PRESSED)
00086     {
00087       if (!GetGeometry().IsPointInside (ievent.e_x, ievent.e_y) )
00088       {
00089         //ProcEvInfo = eDoNotProcess;
00090         //return TraverseInfo;
00091       }
00092     }
00093 
00094     S_KEY = ievent.GetVirtualKeyState (NUX_VK_S);
00095     ret = PostProcessEvent2 (ievent, ret, ProcessEventInfo);
00096     return ret;
00097   }
00098 
00099 
00100   void BezierCurveControl2::Draw (GraphicsEngine &GfxContext, bool force_draw)
00101   {
00102     Geometry base = GetGeometry();
00103 
00104     GetPainter().PaintBackground (GfxContext, base);
00105     GetPainter().Paint2DQuadColor (GfxContext, base, Color (COLOR_BACKGROUND_PRIMARY) );
00106     base.OffsetPosition (GRAPH_MARGIN, GRAPH_MARGIN);
00107     base.OffsetSize (-2 * GRAPH_MARGIN, -2 * GRAPH_MARGIN);
00108 
00109     int W = GetBaseWidth() - 2 * GRAPH_MARGIN;
00110     int H = GetBaseHeight() - 2 * GRAPH_MARGIN;
00111     int X = GetBaseX() + GRAPH_MARGIN;
00112     int Y = GetBaseY() + GRAPH_MARGIN;
00113 
00114     t_u32 i;
00115     int nsample = base.GetWidth();
00116     double t;
00117     t_u32 nbKnot = (t_u32) m_control_knot.size();
00118 
00119     GfxContext.PushClippingRectangle (base);
00120 
00121     GetPainter().PushDrawLayer (GfxContext, base, m_Background);
00122     GetPainter().PopBackground();
00123 
00124     //DrawGrid(GfxContext);
00125     DrawCoordinateSystem (GfxContext);
00126 
00127     if (nbKnot > 0)
00128     {
00129       double *xcon = new double[nbKnot];
00130       double xval;
00131       double *ycon = new double[nbKnot];
00132       double yval;
00133 
00134 
00135       for (i = 0; i < nbKnot; i++)
00136       {
00137         xcon[i] = m_control_knot[i].m_X;
00138         ycon[i] = m_control_knot[i].m_Y;
00139       }
00140 
00141       double xprev, yprev;
00142       Bezier_XY (CURVE_DEGREE, 0.0, xcon, ycon, &xprev, &yprev);
00143 
00144       int X0, Y0, X1, Y1, X2, Y2;
00145 
00146       glEnable (GL_POINT_SMOOTH);
00147       glEnable (GL_LINE_SMOOTH);
00148       glLineWidth (1);
00149       glHint (GL_POINT_SMOOTH_HINT, GL_NICEST); // Make round points, not square points
00150       glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);          // Antialias the lines
00151       GfxContext.GetRenderStates().SetBlend (TRUE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00152 
00153       for (i = 1; i < (t_u32) nsample; i++ )
00154       {
00155         t = ( double ) ( i ) / ( double ) ( nsample - 1 );
00156         Bezier_XY ( CURVE_DEGREE, t, xcon, ycon, &xval, &yval );
00157 
00158         X0 = X + W * (xprev - m_minX) / (m_maxX - m_minX);
00159         Y0 = Y + H * ( 1 - (yprev - m_minY) / (m_maxY - m_minY) );
00160         X1 = X + W * (xval - m_minX) / (m_maxX - m_minX);
00161         Y1 = Y + H * ( 1 - (yval - m_minY) / (m_maxY - m_minY) );
00162 
00163         GetPainter().Draw2DLine (GfxContext, X0, Y0, X1, Y1, Color (0xFFFFFFFF) );
00164 
00165         xprev = xval;
00166         yprev = yval;
00167       }
00168 
00169       if (m_control_knot[0].m_X > m_minX)
00170       {
00171         // draw line from the left border to the left most control point.
00172 
00173         X0 = X + W * (m_control_knot[0].m_X - m_minX) / (m_maxX - m_minX);
00174         Y0 = Y + H * ( 1 - (m_control_knot[0].m_Y - m_minY) / (m_maxY - m_minY) );
00175 
00176         GetPainter().Draw2DLine (GfxContext, base.x, Y0, X0, Y0, Color (0xFFFFFFFF) );
00177       }
00178 
00179       if (m_control_knot[nbKnot-1].m_X < m_maxX)
00180       {
00181         // draw line from the right most control point to the left border.
00182 
00183         X0 = X + W * (m_control_knot[nbKnot-1].m_X - m_minX) / (m_maxX - m_minX);
00184         Y0 = Y + H * ( 1 - (m_control_knot[nbKnot-1].m_Y - m_minY) / (m_maxY - m_minY) );
00185 
00186         GetPainter().Draw2DLine (GfxContext, X0, Y0, base.x + base.GetWidth(), Y0, Color (0xFFFFFFFF) );
00187       }
00188 
00189       glDisable (GL_POINT_SMOOTH);
00190       glDisable (GL_LINE_SMOOTH);
00191       GfxContext.GetRenderStates().SetBlend (FALSE);
00192 
00193       for (i = 0; i <= nbKnot - 1; i += CURVE_DEGREE)
00194       {
00195         // Only the endpoint of cubic bezier.
00196 
00197         X0 = X + W * (m_control_knot[i].m_X - m_minX) / (m_maxX - m_minX);
00198         Y0 = Y + H * ( 1 - (m_control_knot[i].m_Y - m_minY) / (m_maxY - m_minY) );
00199 
00200         if (i < nbKnot - 1)
00201         {
00202           X1 = X + W * (m_control_knot[i+1].m_X - m_minX) / (m_maxX - m_minX);
00203           Y1 = Y + H * ( 1 - (m_control_knot[i+1].m_Y - m_minY) / (m_maxY - m_minY) );
00204 
00205           GetPainter().Draw2DLine (GfxContext, X0, Y0, X1, Y1, Color (0xFF0000FF) );
00206         }
00207 
00208         if ( i > 0)
00209         {
00210           X2 = X + W * (m_control_knot[i-1].m_X - m_minX) / (m_maxX - m_minX);
00211           Y2 = Y + H * ( 1 - (m_control_knot[i-1].m_Y - m_minY) / (m_maxY - m_minY) );
00212 
00213           GetPainter().Draw2DLine (GfxContext, X0, Y0, X2, Y2, Color (0xFF0000FF) );
00214         }
00215       }
00216 
00217       Geometry ShapeGeo = GetTheme().GetImageGeometry (eDOT6x6);
00218 
00219       for (i = 0; i < nbKnot; i++)
00220       {
00221         int X0, Y0;
00222         X0 = X + W * (m_control_knot[i].m_X - m_minX) / (m_maxX - m_minX);
00223         Y0 = Y + H * ( 1 - (m_control_knot[i].m_Y - m_minY) / (m_maxY - m_minY) );
00224 
00225         if (m_control_knot[i].m_IsSelected)
00226         {
00227           GetPainter().PaintShape (GfxContext,
00228                                Geometry (X0 - ShapeGeo.GetWidth() / 2, Y0 - ShapeGeo.GetHeight() / 2, ShapeGeo.GetWidth(), ShapeGeo.GetHeight() ),
00229                                Color (0xFF44FF44), eDOT6x6);
00230         }
00231         else
00232         {
00233           GetPainter().PaintShape (GfxContext,
00234                                Geometry (X0 - ShapeGeo.GetWidth() / 2, Y0 - ShapeGeo.GetHeight() / 2, ShapeGeo.GetWidth(), ShapeGeo.GetHeight() ),
00235                                Color (0xFFFFFFFF), eDOT6x6);
00236         }
00237       }
00238 
00239       delete[] xcon;
00240       delete[] ycon;
00241     }
00242 
00243     GetPainter().Paint2DQuadWireframe (GfxContext, base, Color (0xFF000000) );
00244 
00245     DrawRuler (GfxContext);
00246     GfxContext.PopClippingRectangle();
00247   }
00248 
00249   void BezierCurveControl2::DrawRuler (GraphicsEngine &GfxContext)
00250   {
00251     Geometry base = GetGeometry();
00252 
00253     base.OffsetPosition (GRAPH_MARGIN, GRAPH_MARGIN);
00254     base.OffsetSize (-2 * GRAPH_MARGIN, -2 * GRAPH_MARGIN);
00255 
00256     // Draw Horizontal ruler
00257 
00258     static float Funit = 1.0;
00259     float rangex = m_maxX - m_minX;
00260     int Iunit = Funit * base.GetWidth() / rangex;
00261 
00262     if (Iunit > 2 * UNIT_REFERENCE)
00263     {
00264       Funit = rangex * UNIT_REFERENCE / base.GetWidth();
00265     }
00266     else if (Iunit < UNIT_REFERENCE)
00267     {
00268       Funit = rangex * 2 * UNIT_REFERENCE / base.GetWidth();
00269     }
00270 
00271     if ( (m_minX < 0) && (m_maxX > 0) )
00272     {
00273       int center = (0 - m_minX) * (float) base.GetWidth() / (float) (m_maxX - m_minX);
00274       int start_x = base.x + center - Funit * base.GetWidth() / rangex;
00275       int count = 0;
00276 
00277       while (start_x > base.x)
00278       {
00279         GetPainter().Draw2DLine (GfxContext, start_x, base.y + base.GetHeight(), start_x, base.y + base.GetHeight() - 5, Color (0xFF000000) );
00280         count++;
00281         start_x -= Funit * base.GetWidth() / rangex;
00282       }
00283 
00284       start_x = base.x + center + Funit * base.GetWidth() / rangex;
00285       count = 0;
00286 
00287       while (start_x < base.x + base.GetWidth() )
00288       {
00289         GetPainter().Draw2DLine (GfxContext, start_x, base.y + base.GetHeight(), start_x, base.y + base.GetHeight() - 5, Color (0xFF000000) );
00290         count++;
00291         start_x += Funit * base.GetWidth() / rangex;
00292       }
00293     }
00294 
00295     if (0 <= m_minX)
00296     {
00297       int center = (m_minX - 0) * (float) base.GetWidth() / (float) (m_maxX - m_minX);
00298       int start_x = base.x - center + Funit * base.GetWidth() / rangex;
00299       int count = 0;
00300 
00301       while (start_x < base.x + base.GetWidth() )
00302       {
00303         GetPainter().Draw2DLine (GfxContext, start_x, base.y + base.GetHeight(), start_x, base.y + base.GetHeight() - 5, Color (0xFF000000) );
00304         count++;
00305         start_x += Funit * base.GetWidth() / rangex;
00306       }
00307     }
00308 
00309     if (m_maxX <= 0)
00310     {
00311       int center = (0 - m_minX) * (float) base.GetWidth() / (float) (m_maxX - m_minX);
00312       int start_x = base.x + center - Funit * base.GetWidth() / rangex;
00313       int count = 0;
00314 
00315       while (start_x > base.x)
00316       {
00317         GetPainter().Draw2DLine (GfxContext, start_x, base.y + base.GetHeight(), start_x, base.y + base.GetHeight() - 5, Color (0xFF000000) );
00318         count++;
00319         start_x -= Funit * base.GetWidth() / rangex;
00320       }
00321     }
00322 
00323     // Draw Vertical ruler
00324 
00325     static float FunitY = 1.0;
00326     float rangey = m_maxY - m_minY;
00327     int IunitY = FunitY * base.GetHeight() / rangey;
00328 
00329     if (IunitY > 2 * UNIT_REFERENCE)
00330     {
00331       FunitY = rangey * UNIT_REFERENCE / base.GetHeight();
00332     }
00333     else if (IunitY < UNIT_REFERENCE)
00334     {
00335       FunitY = rangey * 2 * UNIT_REFERENCE / base.GetHeight();
00336     }
00337 
00338     if ( (m_minY < 0) && (m_maxY > 0) )
00339     {
00340       int center = (0 - m_minY) * (float) base.GetHeight() / (float) (m_maxY - m_minY);
00341       int start_y = base.y + base.GetHeight() - center - FunitY * base.GetHeight() / rangey;
00342       int count = 0;
00343 
00344       while (start_y > base.y)
00345       {
00346         GetPainter().Draw2DLine (GfxContext, base.x, start_y , base.x + 5, start_y, Color (0xFF000000) );
00347         count++;
00348         start_y -= FunitY * base.GetHeight() / rangey;
00349       }
00350 
00351       start_y = base.y + base.GetHeight() - center + FunitY * base.GetHeight() / rangey;
00352       count = 0;
00353 
00354       while (start_y < base.y + base.GetHeight() )
00355       {
00356         GetPainter().Draw2DLine (GfxContext, base.x, start_y , base.x + 5, start_y, Color (0xFF000000) );
00357         count++;
00358         start_y += FunitY * base.GetHeight() / rangey;
00359       }
00360     }
00361 
00362     if (0 <= m_minY)
00363     {
00364       int center = (m_minY - 0) * (float) base.GetHeight() / (float) (m_maxY - m_minY);
00365       int start_y = base.y + base.GetHeight() + center - FunitY * base.GetHeight() / rangey;
00366       int count = 0;
00367 
00368       while (start_y > base.y)
00369       {
00370         GetPainter().Draw2DLine (GfxContext, base.x, start_y , base.x + 5, start_y, Color (0xFF000000) );
00371         count++;
00372         start_y -= FunitY * base.GetHeight() / rangey;
00373       }
00374     }
00375 
00376     if (m_maxY <= 0)
00377     {
00378       int center = (0 - m_minY) * (float) base.GetHeight() / (float) (m_maxY - m_minY);
00379       int start_y = base.y + base.GetHeight() - center + FunitY * base.GetHeight() / rangey;
00380       int count = 0;
00381 
00382       while (start_y < base.y + base.GetHeight() )
00383       {
00384         GetPainter().Draw2DLine (GfxContext, base.x, start_y , base.x + 5, start_y, Color (0xFF000000) );
00385         count++;
00386         start_y += FunitY * base.GetHeight() / rangey;
00387       }
00388     }
00389   }
00390 
00391   void BezierCurveControl2::DrawGrid (GraphicsEngine &GfxContext)
00392   {
00393     Geometry base = GetGeometry();
00394 
00395     base.OffsetPosition (GRAPH_MARGIN, GRAPH_MARGIN);
00396     base.OffsetSize (-2 * GRAPH_MARGIN, -2 * GRAPH_MARGIN);
00397 
00398     // Draw Vertical Grid
00399 
00400     static float Funit = 1.0;
00401     float rangex = m_maxX - m_minX;
00402     int Iunit = Funit * base.GetWidth() / rangex;
00403 
00404     if (Iunit > 2 * UNIT_REFERENCE)
00405     {
00406       Funit = rangex * UNIT_REFERENCE / base.GetWidth();
00407     }
00408     else if (Iunit < UNIT_REFERENCE)
00409     {
00410       Funit = rangex * 2 * UNIT_REFERENCE / base.GetWidth();
00411     }
00412 
00413     if ( (m_minX < 0) && (m_maxX > 0) )
00414     {
00415       int center = (0 - m_minX) * (float) base.GetWidth() / (float) (m_maxX - m_minX);
00416       int start_x = base.x + center - Funit * base.GetWidth() / rangex;
00417       int count = 0;
00418 
00419       while (start_x > base.x)
00420       {
00421         // vertical grid
00422         GetPainter().Draw2DLine (GfxContext, start_x, base.y,
00423                              start_x, base.y + base.GetHeight(), Color (0xFF5F5F5F) );
00424 
00425         count++;
00426         start_x -= Funit * base.GetWidth() / rangex;
00427       }
00428 
00429       start_x = base.x + center + Funit * base.GetWidth() / rangex;
00430       count = 0;
00431 
00432       while (start_x < base.x + base.GetWidth() )
00433       {
00434         // vertical grid
00435         GetPainter().Draw2DLine (GfxContext, start_x, base.y,
00436                              start_x, base.y + base.GetHeight(), Color (0xFF5F5F5F) );
00437 
00438         count++;
00439         start_x += Funit * base.GetWidth() / rangex;
00440       }
00441     }
00442 
00443     if (0 <= m_minX)
00444     {
00445       int center = (m_minX - 0) * (float) base.GetWidth() / (float) (m_maxX - m_minX);
00446       int start_x = base.x - center + Funit * base.GetWidth() / rangex;
00447       int count = 0;
00448 
00449       while (start_x < base.x + base.GetWidth() )
00450       {
00451         // vertical grid
00452         GetPainter().Draw2DLine (GfxContext, start_x, base.y,
00453                              start_x, base.y + base.GetHeight(), Color (0xFF5F5F5F) );
00454 
00455         count++;
00456         start_x += Funit * base.GetWidth() / rangex;
00457       }
00458     }
00459 
00460     if (m_maxX <= 0)
00461     {
00462       int center = (0 - m_minX) * (float) base.GetWidth() / (float) (m_maxX - m_minX);
00463       int start_x = base.x + center - Funit * base.GetWidth() / rangex;
00464       int count = 0;
00465 
00466       while (start_x > base.x)
00467       {
00468         // vertical grid
00469         GetPainter().Draw2DLine (GfxContext, start_x, base.y,
00470                              start_x, base.y + base.GetHeight(), Color (0xFF5F5F5F) );
00471 
00472         count++;
00473         start_x -= Funit * base.GetWidth() / rangex;
00474       }
00475     }
00476 
00477     // Draw Horizontal Grid
00478 
00479     static float FunitY = 1.0;
00480     float rangey = m_maxY - m_minY;
00481     int IunitY = FunitY * base.GetHeight() / rangey;
00482 
00483     if (IunitY > 2 * UNIT_REFERENCE)
00484     {
00485       FunitY = rangey * UNIT_REFERENCE / base.GetHeight();
00486     }
00487     else if (IunitY < UNIT_REFERENCE)
00488     {
00489       FunitY = rangey * 2 * UNIT_REFERENCE / base.GetHeight();
00490     }
00491 
00492     if ( (m_minY < 0) && (m_maxY > 0) )
00493     {
00494       int center = (0 - m_minY) * (float) base.GetHeight() / (float) (m_maxY - m_minY);
00495       int start_y = base.y + base.GetHeight() - center - FunitY * base.GetHeight() / rangey;
00496       int count = 0;
00497 
00498       while (start_y > base.y)
00499       {
00500         // horizontal grid
00501         GetPainter().Draw2DLine (GfxContext, base.x, start_y,
00502                              base.x + base.GetWidth(), start_y, Color (0xFF5F5F5F) );
00503 
00504         count++;
00505         start_y -= FunitY * base.GetHeight() / rangey;
00506       }
00507 
00508       start_y = base.y + base.GetHeight() - center + FunitY * base.GetHeight() / rangey;
00509       count = 0;
00510 
00511       while (start_y < base.y + base.GetHeight() )
00512       {
00513         GetPainter().Draw2DLine (GfxContext, base.x, start_y,
00514                              base.x + base.GetWidth(), start_y, Color (0xFF5F5F5F) );
00515 
00516         count++;
00517         start_y += FunitY * base.GetHeight() / rangey;
00518       }
00519     }
00520 
00521     if (0 <= m_minY)
00522     {
00523       int center = (m_minY - 0) * (float) base.GetHeight() / (float) (m_maxY - m_minY);
00524       int start_y = base.y + base.GetHeight() + center - FunitY * base.GetHeight() / rangey;
00525       int count = 0;
00526 
00527       while (start_y > base.y)
00528       {
00529         GetPainter().Draw2DLine (GfxContext, base.x, start_y,
00530                              base.x + base.GetWidth(), start_y, Color (0xFF5F5F5F) );
00531 
00532         count++;
00533         start_y -= FunitY * base.GetHeight() / rangey;
00534       }
00535     }
00536 
00537     if (m_maxY <= 0)
00538     {
00539       int center = (0 - m_minY) * (float) base.GetHeight() / (float) (m_maxY - m_minY);
00540       int start_y = base.y + base.GetHeight() - center + FunitY * base.GetHeight() / rangey;
00541       int count = 0;
00542 
00543       while (start_y < base.y + base.GetHeight() )
00544       {
00545         GetPainter().Draw2DLine (GfxContext, base.x, start_y,
00546                              base.x + base.GetWidth(), start_y, Color (0xFF5F5F5F) );
00547 
00548         count++;
00549         start_y += FunitY * base.GetHeight() / rangey;
00550       }
00551     }
00552   }
00553 
00554   void BezierCurveControl2::DrawCoordinateSystem (GraphicsEngine &GfxContext)
00555   {
00556     int W = GetBaseWidth() - 2 * GRAPH_MARGIN;
00557     int H = GetBaseHeight() - 2 * GRAPH_MARGIN;
00558     int X = GetBaseX() + GRAPH_MARGIN;
00559     int Y = GetBaseY() + GRAPH_MARGIN;
00560 
00561     int X0, Y0;
00562     X0 = X + W * (0 - m_minX) / (m_maxX - m_minX);
00563     Y0 = Y + H * ( 1 - (0 - m_minY) / (m_maxY - m_minY) );
00564 
00565     GetPainter().Draw2DLine (GfxContext, X0, Y, X0, Y + H, Color (0xFF222222) );
00566     GetPainter().Draw2DLine (GfxContext, X, Y0, X + W, Y0, Color (0xFF000000) );
00567   }
00568 
00569   void BezierCurveControl2::DrawContent (GraphicsEngine &GfxContext, bool force_draw)
00570   {
00571 
00572   }
00573 
00574   void BezierCurveControl2::PostDraw (GraphicsEngine &GfxContext, bool force_draw)
00575   {
00576 
00577   }
00578 
00579 
00580   void BezierCurveControl2::SetXAxisBounds (float minX, float maxX)
00581   {
00582     m_minX = minX;
00583     m_maxX = maxX;
00584     QueueDraw();
00585   }
00586 
00587   void BezierCurveControl2::SetYAxisBounds (float minY, float maxY)
00588   {
00589     m_minY = minY;
00590     m_maxY = maxY;
00591     QueueDraw();
00592   }
00593 
00594   void BezierCurveControl2::SetFunctionCallback (FunctionCallback f)
00595   {
00596     m_FunctionCallback = f;
00597     QueueDraw();
00598   }
00599 
00600   float BezierCurveControl2::EvalFunction (float x)
00601   {
00602     if (m_FunctionCallback != 0)
00603       return (*m_FunctionCallback) (x);
00604 
00605     return 0;
00606   }
00607 
00608   void BezierCurveControl2::UpdateGraph()
00609   {
00610     QueueDraw();
00611   }
00612 
00613 
00614 // check if a value lies within a closed interval
00615 #ifndef INSIDE_BOUNDS
00616 #define INSIDE_BOUNDS( x, lo, hi ) ( (x) >= (lo) && (x) <= (hi) )
00617 #endif
00618 
00619 //check if a 2D point lies within a 2D box
00620 #ifndef PT_INSIDE_BOX
00621 #define PT_INSIDE_BOX( x, y, lo_x, hi_x, lo_y, hi_y ) ( INSIDE_BOUNDS(x,lo_x,hi_x) && INSIDE_BOUNDS(y,lo_y,hi_y) )
00622 #endif
00623 
00624   void BezierCurveControl2::RecvMouseUp (int x, int y, unsigned long button_flags, unsigned long key_flags)
00625   {
00626     QueueDraw();
00627   }
00628 
00629   void BezierCurveControl2::RecvMouseDown (int x, int y, unsigned long button_flags, unsigned long key_flags)
00630   {
00631     if (! (button_flags & NUX_EVENT_BUTTON1) )
00632     {
00633       return;
00634     }
00635 
00636     m_bControlPointSelected = false;
00637     t_u32 nbKnot = (t_u32) m_control_knot.size();
00638 
00639     for (t_u32 i = 0; i < nbKnot; i++)
00640     {
00641       m_control_knot[i].m_IsSelected = false;
00642     }
00643 
00644     int W = GetBaseWidth() - 2 * GRAPH_MARGIN;
00645     int H = GetBaseHeight() - 2 * GRAPH_MARGIN;
00646     int X = GetBaseX() + GRAPH_MARGIN;
00647     int Y = GetBaseY() + GRAPH_MARGIN;
00648 
00649     bool b = PT_INSIDE_BOX (X - GRAPH_MARGIN + x, Y - GRAPH_MARGIN + y, X - GRAPH_MARGIN, X + W + 2 * GRAPH_MARGIN, Y - GRAPH_MARGIN, Y + H + 2 * GRAPH_MARGIN);
00650 
00651     if (b == false)
00652       return;
00653 
00654 //    X = GetX();
00655 //    Y = GetY();
00656     for (t_u32 i = 0; i < nbKnot; i++)
00657     {
00658       int Xp, Yp;
00659       Xp = X + W * (m_control_knot[i].m_X - m_minX) / (m_maxX - m_minX);
00660       Yp = Y + H * ( 1 - (m_control_knot[i].m_Y - m_minY) / (m_maxY - m_minY) );
00661 
00662       int tx, ty;
00663       tx = X + x - GRAPH_MARGIN;
00664       ty = Y + y - GRAPH_MARGIN;
00665 
00666       if (PT_INSIDE_BOX (tx, ty, Xp - KNOT_HIT_TEST, Xp + KNOT_HIT_TEST, Yp - KNOT_HIT_TEST, Yp + KNOT_HIT_TEST) )
00667       {
00668         m_control_knot[i].m_IsSelected = true;
00669         hit_point_dx = (tx) - Xp;
00670         hit_point_dy = Yp - (ty);
00671 
00672         m_bControlPointSelected = true;
00673 
00674         if ( (i % CURVE_DEGREE) == 0)
00675         {
00676           // this is a control point at the begining of a cubic bezier curve
00677           // Also select the control points defining the entering and exiting tangent at this point.
00678         }
00679 
00680         break;
00681       }
00682     }
00683 
00684     QueueDraw();
00685   }
00686 
00687   int ClosestCubicBezierEndPoint (int i)
00688   {
00689     if ( (i % CURVE_DEGREE) == 0)
00690     {
00691       return i;
00692     }
00693 
00694     if ( ( (i + 1) % CURVE_DEGREE) == 0)
00695     {
00696       return i + 1;
00697     }
00698 
00699     if ( ( (i - 1) % CURVE_DEGREE) == 0)
00700     {
00701       return i - 1;
00702     }
00703 
00704     return 0;
00705   }
00706 
00707   void BezierCurveControl2::RecvKeyEvent (
00708     unsigned long   eventType  , /*event type*/
00709     unsigned long   keysym     , /*event keysym*/
00710     unsigned long   state      , /*event state*/
00711     const TCHAR*    character  , /*character*/
00712     unsigned short  keyCount     /*key repeat count*/
00713   )
00714   {
00715 
00716   }
00717 
00718   void BezierCurveControl2::RecvMouseDrag (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
00719   {
00720     if ( (m_bControlPointSelected == false) && (button_flags & NUX_STATE_BUTTON1_DOWN) && S_KEY)
00721     {
00722       if (m_bPanningEnabled)
00723       {
00724         ProcessPanning (x, y, dx, dy, button_flags, key_flags);
00725         return;
00726       }
00727     }
00728 
00729     if ( (m_bControlPointSelected == false) && (button_flags & NUX_STATE_BUTTON3_DOWN) && S_KEY)
00730     {
00731       if (m_bZoomingEnabled)
00732       {
00733         ProcessZooming (x, y, dx, dy, button_flags, key_flags);
00734         return;
00735       }
00736     }
00737 
00738     if (button_flags & NUX_STATE_BUTTON1_DOWN)
00739       ManipulateBezier (x, y, dx, dy, button_flags, key_flags);
00740   }
00741 
00742   void BezierCurveControl2::ManipulateBezier (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
00743   {
00744     float xp, yp;
00745     int W = GetBaseWidth() - 2 * GRAPH_MARGIN;
00746     int H = GetBaseHeight() - 2 * GRAPH_MARGIN;
00747     int X = GetBaseX() + GRAPH_MARGIN;
00748     int Y = GetBaseY() + GRAPH_MARGIN;
00749 
00750     t_s32 nbKnot = (t_s32) m_control_knot.size();
00751 
00752     xp = /*m_minX +*/ dx * (m_maxX - m_minX) / W;
00753     yp = /*m_minY +*/ dy * (m_maxY - m_minY) / H;
00754 
00755     nuxAssert (nbKnot >= CURVE_DEGREE);
00756     int x_border = 0;
00757     int y_border = 0;
00758 
00759     for (t_s32 i = 0; i < nbKnot; i++)
00760     {
00761       if (m_control_knot[i].m_IsSelected)
00762       {
00763         int tempx, tempy;
00764         tempx = X + x - GRAPH_MARGIN;
00765         tempy = Y + y - GRAPH_MARGIN;
00766 
00767         int Xp, Yp;
00768         Xp = X + W * (m_control_knot[i].m_X - m_minX) / (m_maxX - m_minX);
00769         Yp = Y + H * ( 1 - (m_control_knot[i].m_Y - m_minY) / (m_maxY - m_minY) );
00770 
00771         if (dx > 0)
00772         {
00773           if (tempx > Xp + hit_point_dx)
00774           {
00775             xp = /*m_minX +*/ (m_maxX - m_minX) * (tempx - Xp - hit_point_dx) / W;
00776           }
00777           else
00778           {
00779             xp = 0;
00780           }
00781         }
00782         else if (dx < 0)
00783         {
00784           if (tempx < Xp + hit_point_dx)
00785           {
00786             xp = /*m_minX +*/ (m_maxX - m_minX) * (tempx - Xp - hit_point_dx) / W;
00787           }
00788           else
00789           {
00790             xp = 0;
00791           }
00792         }
00793 
00794         if (dy > 0)
00795         {
00796           if (tempy > Yp - hit_point_dy)
00797           {
00798             yp = /*m_minY +*/ (m_maxY - m_minY) * (tempy - Yp + hit_point_dy) / H;
00799           }
00800           else
00801           {
00802             yp = 0;
00803           }
00804         }
00805         else if (dy < 0)
00806         {
00807           if (tempy < Yp - hit_point_dy)
00808           {
00809             yp = /*m_minY +*/ (m_maxY - m_minY) * (tempy - Yp + hit_point_dy) / H;
00810           }
00811           else
00812           {
00813             yp = 0;
00814           }
00815         }
00816 
00817         if (m_bPanningEnabled == false)
00818         {
00819           if (m_control_knot[i].m_X + xp < m_minX)
00820           {
00821             xp = m_minX - m_control_knot[i].m_X;
00822             x_border = -1;
00823           }
00824           else if (m_control_knot[i].m_X + xp > m_maxX)
00825           {
00826             xp = m_maxX - m_control_knot[i].m_X;
00827             x_border = +1;
00828           }
00829 
00830           if (m_control_knot[i].m_Y - yp < m_minY)
00831           {
00832             yp = m_control_knot[i].m_Y - m_minY;
00833             y_border = -1;
00834           }
00835           else if (m_control_knot[i].m_Y - yp > m_maxY)
00836           {
00837             yp = m_control_knot[i].m_Y - m_maxY;
00838             y_border = +1;
00839           }
00840         }
00841 
00842 
00843         if ( (i % CURVE_DEGREE) == 0)
00844         {
00845           if (y_border == 0)
00846             m_control_knot[i].m_Y -= yp;
00847           else if (y_border == -1)
00848             m_control_knot[i].m_Y = m_minY;
00849           else if (y_border == +1)
00850             m_control_knot[i].m_Y = m_maxY;
00851 
00852           // Only endpoint of cubic bezier curves.
00853           if (i == 0)
00854           {
00855             if (x_border == 0)
00856             {
00857               if ( m_control_knot[i].m_X + xp > m_control_knot[i + CURVE_DEGREE].m_X - 0.01)
00858               {
00859                 xp = (m_control_knot[i + CURVE_DEGREE].m_X - 0.01) - m_control_knot[i].m_X;
00860                 m_control_knot[i].m_X = m_control_knot[i + CURVE_DEGREE].m_X - 0.01;
00861               }
00862               else
00863               {
00864                 m_control_knot[i].m_X += xp;
00865               }
00866             }
00867             else
00868             {
00869               if (x_border == -1)
00870                 m_control_knot[i].m_X = m_minX;
00871               else if (x_border == +1)
00872                 m_control_knot[i].m_X = m_maxX;
00873 
00874               if ( m_control_knot[i].m_X > m_control_knot[i + CURVE_DEGREE].m_X - 0.01)
00875               {
00876                 xp += (m_control_knot[i + CURVE_DEGREE].m_X - 0.01) - m_control_knot[i].m_X;
00877                 m_control_knot[i].m_X = m_control_knot[i + CURVE_DEGREE].m_X - 0.01;
00878               }
00879             }
00880 
00881             // move the right tangent points
00882             {
00883               m_control_knot[i+1].m_X += xp;
00884               m_control_knot[i+1].m_Y -= yp;
00885 
00886               if (m_control_knot[i+1].m_X < m_control_knot[i].m_X)
00887               {
00888                 m_control_knot[i+1].m_X = m_control_knot[i].m_X;
00889               }
00890             }
00891           }
00892           else if (i == nbKnot - 1)
00893           {
00894             if (x_border == 0)
00895             {
00896               if (m_control_knot[i].m_X + xp < m_control_knot[i - CURVE_DEGREE].m_X + 0.01)
00897               {
00898                 xp = - (m_control_knot[i].m_X - (m_control_knot[i - CURVE_DEGREE].m_X + 0.01) );
00899                 m_control_knot[i].m_X = m_control_knot[i - CURVE_DEGREE].m_X + 0.01;
00900               }
00901               else
00902               {
00903                 m_control_knot[i].m_X += xp;
00904               }
00905             }
00906             else
00907             {
00908               if (x_border == -1)
00909                 m_control_knot[i].m_X = m_minX;
00910               else if (x_border == +1)
00911                 m_control_knot[i].m_X = m_maxX;
00912 
00913               if (m_control_knot[i].m_X < m_control_knot[i - CURVE_DEGREE].m_X + 0.01)
00914               {
00915                 xp += (m_control_knot[i - CURVE_DEGREE].m_X + 0.01) - m_control_knot[i].m_X;
00916                 m_control_knot[i].m_X = m_control_knot[i - CURVE_DEGREE].m_X + 0.01;
00917               }
00918             }
00919 
00920             // move the left tangent points
00921             {
00922               m_control_knot[i-1].m_X += xp;
00923               m_control_knot[i-1].m_Y -= yp;
00924 
00925               if (m_control_knot[i-1].m_X > m_control_knot[i].m_X)
00926               {
00927                 m_control_knot[i-1].m_X = m_control_knot[i].m_X;
00928               }
00929             }
00930           }
00931           else
00932           {
00933             if (m_control_knot[i].m_X + xp > m_control_knot[i + CURVE_DEGREE].m_X - 0.01)
00934             {
00935               xp = (m_control_knot[i + CURVE_DEGREE].m_X - 0.01) - m_control_knot[i].m_X;
00936               m_control_knot[i].m_X = m_control_knot[i + CURVE_DEGREE].m_X - 0.01;
00937             }
00938             else if (m_control_knot[i].m_X + xp < m_control_knot[i - CURVE_DEGREE].m_X + 0.01)
00939             {
00940               xp = m_control_knot[i].m_X - (m_control_knot[i - CURVE_DEGREE].m_X + 0.01);
00941               m_control_knot[i].m_X = m_control_knot[i - CURVE_DEGREE].m_X + 0.01;
00942             }
00943             else
00944             {
00945               m_control_knot[i].m_X += xp;
00946             }
00947 
00948             // move the left and right tangent points
00949             {
00950               m_control_knot[i-1].m_X += xp;
00951               m_control_knot[i+1].m_X += xp;
00952               m_control_knot[i-1].m_Y -= yp;
00953               m_control_knot[i+1].m_Y -= yp;
00954 
00955               if (m_control_knot[i-1].m_X > m_control_knot[i].m_X)
00956               {
00957                 m_control_knot[i-1].m_X = m_control_knot[i].m_X;
00958               }
00959 
00960               if (m_control_knot[i+1].m_X < m_control_knot[i].m_X)
00961               {
00962                 m_control_knot[i+1].m_X = m_control_knot[i].m_X;
00963               }
00964             }
00965           }
00966         }
00967         else
00968         {
00969           m_control_knot[i].m_X += xp;
00970           m_control_knot[i].m_Y -= yp;
00971 
00972           t_s32 index = (t_s32) ClosestCubicBezierEndPoint (i);
00973 
00974           if (index > i)
00975           {
00976             if (m_control_knot[i].m_X > m_control_knot[index].m_X)
00977             {
00978               m_control_knot[i].m_X = m_control_knot[index].m_X;
00979             }
00980           }
00981           else if ( index < i)
00982           {
00983             if (m_control_knot[i].m_X < m_control_knot[index].m_X)
00984             {
00985               m_control_knot[i].m_X = m_control_knot[index].m_X;
00986             }
00987           }
00988         }
00989 
00990         break;
00991       }
00992     }
00993 
00994     QueueDraw();
00995   }
00996 
00997   void BezierCurveControl2::ProcessPanning (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
00998   {
00999     float xp, yp;
01000     int W = GetBaseWidth() - 2 * GRAPH_MARGIN;
01001     int H = GetBaseHeight() - 2 * GRAPH_MARGIN;
01002 
01003     xp = /*m_minX +*/ dx * (m_maxX - m_minX) / W;
01004     yp = /*m_minY +*/ dy * (m_maxY - m_minY) / H;
01005 
01006     if (m_bControlPointSelected == false)
01007     {
01008       if (m_bPanningEnabled)
01009       {
01010         m_minX -= xp;
01011         m_maxX -= xp;
01012         m_minY += yp;
01013         m_maxY += yp;
01014 
01015         QueueDraw();
01016         return;
01017       }
01018     }
01019   }
01020 
01021   void BezierCurveControl2::ProcessZooming (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
01022   {
01023     int H = GetBaseHeight() - 2 * GRAPH_MARGIN;
01024 
01025     float yp = dy * (m_maxY - m_minY) / H;
01026 
01027     if ( (m_minX + yp >= m_maxX - yp) || (m_minY + yp >= m_maxY - yp) )
01028     {
01029       yp = yp / 2.0f;
01030     }
01031 
01032     if (m_bControlPointSelected == false)
01033     {
01034       if (m_bZoomingEnabled)
01035       {
01036         m_minX += yp;
01037         m_maxX -= yp;
01038         m_minY += yp;
01039         m_maxY -= yp;
01040 
01041         QueueDraw();
01042         return;
01043       }
01044     }
01045   }
01046 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends