nux-1.14.0
|
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 }