2
* Copyright 2010 Inalogic Inc.
4
* This program is free software: you can redistribute it and/or modify it
5
* under the terms of the GNU Lesser General Public License version 3, as
6
* published by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranties of
10
* MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
11
* PURPOSE. See the applicable version of the GNU Lesser General Public
12
* License for more details.
14
* You should have received a copy of both the GNU Lesser General Public
15
* License version 3 along with this program. If not, see
16
* <http://www.gnu.org/licenses/>
18
* Authored by: Jay Taoko <jay.taoko_AT_gmail_DOT_com>
25
#include "BezierCurveControl2.h"
26
#include "NuxCore/Math/Bezier.h"
31
static const int KNOT_SIZE = 2;
32
static const int KNOT_HIT_TEST = 4;
33
static const int CURVE_DEGREE = 3;
34
static const int GRAPH_MARGIN = 2;
35
static const int UNIT_REFERENCE = 15;
37
unsigned long S_KEY = 0;
39
BezierCurveControl2::BezierCurveControl2 (NUX_FILE_LINE_DECL)
40
: View (NUX_FILE_LINE_PARAM)
45
m_FunctionCallback (0),
46
m_bControlPointSelected (0),
47
m_bPanningEnabled (true),
48
m_bZoomingEnabled (true)
50
SetMinimumSize (180, 180);
52
m_control_knot.push_back (Knot2 (0.0f, 0.0f) );
53
m_control_knot.push_back (Knot2 (0.1f, 0.0f) );
54
m_control_knot.push_back (Knot2 (0.7f, 0.9f) );
55
m_control_knot.push_back (Knot2 (1.0f, 1.0f) );
57
OnMouseDown.connect (sigc::mem_fun (this, &BezierCurveControl2::RecvMouseDown) );
58
OnMouseUp.connect (sigc::mem_fun (this, &BezierCurveControl2::RecvMouseUp) );
59
OnMouseDrag.connect (sigc::mem_fun (this, &BezierCurveControl2::RecvMouseDrag) );
61
OnKeyEvent.connect (sigc::mem_fun (this, &BezierCurveControl2::RecvKeyEvent) );
64
MakeCheckBoardImage (image.GetSurface (0), 64, 64, Color (0xff323232), Color (0xff535353), 8, 8);
65
BaseTexture* m_CheckboardPattern = GetThreadGLDeviceFactory()->CreateSystemCapableTexture ();
66
m_CheckboardPattern->Update (&image);
68
TexCoordXForm texxform;
69
texxform.SetTexCoordType (TexCoordXForm::OFFSET_COORD);
70
texxform.SetWrap (TEXWRAP_REPEAT, TEXWRAP_REPEAT);
71
m_Background = new TextureLayer (m_CheckboardPattern->GetDeviceTexture(), texxform, Color::White);
73
m_CheckboardPattern->UnReference ();
76
BezierCurveControl2::~BezierCurveControl2()
78
NUX_SAFE_DELETE (m_Background);
82
long BezierCurveControl2::ProcessEvent (IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
84
long ret = TraverseInfo;
86
if (ievent.e_event == NUX_MOUSE_PRESSED)
88
if (!m_Geometry.IsPointInside (ievent.e_x, ievent.e_y) )
90
//ProcEvInfo = eDoNotProcess;
91
//return TraverseInfo;
95
S_KEY = ievent.GetVirtualKeyState (NUX_VK_S);
96
ret = PostProcessEvent2 (ievent, ret, ProcessEventInfo);
101
void BezierCurveControl2::Draw (GraphicsEngine &GfxContext, bool force_draw)
103
Geometry base = GetGeometry();
105
GetPainter().PaintBackground (GfxContext, base);
106
GetPainter().Paint2DQuadColor (GfxContext, base, Color (COLOR_BACKGROUND_PRIMARY) );
107
base.OffsetPosition (GRAPH_MARGIN, GRAPH_MARGIN);
108
base.OffsetSize (-2 * GRAPH_MARGIN, -2 * GRAPH_MARGIN);
110
int W = GetBaseWidth() - 2 * GRAPH_MARGIN;
111
int H = GetBaseHeight() - 2 * GRAPH_MARGIN;
112
int X = GetBaseX() + GRAPH_MARGIN;
113
int Y = GetBaseY() + GRAPH_MARGIN;
116
int nsample = base.GetWidth();
118
t_u32 nbKnot = (t_u32) m_control_knot.size();
120
GfxContext.PushClippingRectangle (base);
122
GetPainter().PushDrawLayer (GfxContext, base, m_Background);
123
GetPainter().PopBackground();
125
//DrawGrid(GfxContext);
126
DrawCoordinateSystem (GfxContext);
130
double *xcon = new double[nbKnot];
132
double *ycon = new double[nbKnot];
136
for (i = 0; i < nbKnot; i++)
138
xcon[i] = m_control_knot[i].m_X;
139
ycon[i] = m_control_knot[i].m_Y;
143
Bezier_XY (CURVE_DEGREE, 0.0, xcon, ycon, &xprev, &yprev);
145
int X0, Y0, X1, Y1, X2, Y2;
147
glEnable (GL_POINT_SMOOTH);
148
glEnable (GL_LINE_SMOOTH);
150
glHint (GL_POINT_SMOOTH_HINT, GL_NICEST); // Make round points, not square points
151
glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); // Antialias the lines
152
GfxContext.GetRenderStates().SetBlend (TRUE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
154
for (i = 1; i < (t_u32) nsample; i++ )
156
t = ( double ) ( i ) / ( double ) ( nsample - 1 );
157
Bezier_XY ( CURVE_DEGREE, t, xcon, ycon, &xval, &yval );
159
X0 = X + W * (xprev - m_minX) / (m_maxX - m_minX);
160
Y0 = Y + H * ( 1 - (yprev - m_minY) / (m_maxY - m_minY) );
161
X1 = X + W * (xval - m_minX) / (m_maxX - m_minX);
162
Y1 = Y + H * ( 1 - (yval - m_minY) / (m_maxY - m_minY) );
164
GetPainter().Draw2DLine (GfxContext, X0, Y0, X1, Y1, Color (0xFFFFFFFF) );
170
if (m_control_knot[0].m_X > m_minX)
172
// draw line from the left border to the left most control point.
174
X0 = X + W * (m_control_knot[0].m_X - m_minX) / (m_maxX - m_minX);
175
Y0 = Y + H * ( 1 - (m_control_knot[0].m_Y - m_minY) / (m_maxY - m_minY) );
177
GetPainter().Draw2DLine (GfxContext, base.x, Y0, X0, Y0, Color (0xFFFFFFFF) );
180
if (m_control_knot[nbKnot-1].m_X < m_maxX)
182
// draw line from the right most control point to the left border.
184
X0 = X + W * (m_control_knot[nbKnot-1].m_X - m_minX) / (m_maxX - m_minX);
185
Y0 = Y + H * ( 1 - (m_control_knot[nbKnot-1].m_Y - m_minY) / (m_maxY - m_minY) );
187
GetPainter().Draw2DLine (GfxContext, X0, Y0, base.x + base.GetWidth(), Y0, Color (0xFFFFFFFF) );
190
glDisable (GL_POINT_SMOOTH);
191
glDisable (GL_LINE_SMOOTH);
192
GfxContext.GetRenderStates().SetBlend (FALSE);
194
for (i = 0; i <= nbKnot - 1; i += CURVE_DEGREE)
196
// Only the endpoint of cubic bezier.
198
X0 = X + W * (m_control_knot[i].m_X - m_minX) / (m_maxX - m_minX);
199
Y0 = Y + H * ( 1 - (m_control_knot[i].m_Y - m_minY) / (m_maxY - m_minY) );
203
X1 = X + W * (m_control_knot[i+1].m_X - m_minX) / (m_maxX - m_minX);
204
Y1 = Y + H * ( 1 - (m_control_knot[i+1].m_Y - m_minY) / (m_maxY - m_minY) );
206
GetPainter().Draw2DLine (GfxContext, X0, Y0, X1, Y1, Color (0xFF0000FF) );
211
X2 = X + W * (m_control_knot[i-1].m_X - m_minX) / (m_maxX - m_minX);
212
Y2 = Y + H * ( 1 - (m_control_knot[i-1].m_Y - m_minY) / (m_maxY - m_minY) );
214
GetPainter().Draw2DLine (GfxContext, X0, Y0, X2, Y2, Color (0xFF0000FF) );
218
Geometry ShapeGeo = GetTheme().GetImageGeometry (eDOT6x6);
220
for (i = 0; i < nbKnot; i++)
223
X0 = X + W * (m_control_knot[i].m_X - m_minX) / (m_maxX - m_minX);
224
Y0 = Y + H * ( 1 - (m_control_knot[i].m_Y - m_minY) / (m_maxY - m_minY) );
226
if (m_control_knot[i].m_IsSelected)
228
GetPainter().PaintShape (GfxContext,
229
Geometry (X0 - ShapeGeo.GetWidth() / 2, Y0 - ShapeGeo.GetHeight() / 2, ShapeGeo.GetWidth(), ShapeGeo.GetHeight() ),
230
Color (0xFF44FF44), eDOT6x6);
234
GetPainter().PaintShape (GfxContext,
235
Geometry (X0 - ShapeGeo.GetWidth() / 2, Y0 - ShapeGeo.GetHeight() / 2, ShapeGeo.GetWidth(), ShapeGeo.GetHeight() ),
236
Color (0xFFFFFFFF), eDOT6x6);
244
GetPainter().Paint2DQuadWireframe (GfxContext, base, Color (0xFF000000) );
246
DrawRuler (GfxContext);
247
GfxContext.PopClippingRectangle();
250
void BezierCurveControl2::DrawRuler (GraphicsEngine &GfxContext)
252
Geometry base = GetGeometry();
254
base.OffsetPosition (GRAPH_MARGIN, GRAPH_MARGIN);
255
base.OffsetSize (-2 * GRAPH_MARGIN, -2 * GRAPH_MARGIN);
257
// Draw Horizontal ruler
259
static float Funit = 1.0;
260
float rangex = m_maxX - m_minX;
261
int Iunit = Funit * base.GetWidth() / rangex;
263
if (Iunit > 2 * UNIT_REFERENCE)
265
Funit = rangex * UNIT_REFERENCE / base.GetWidth();
267
else if (Iunit < UNIT_REFERENCE)
269
Funit = rangex * 2 * UNIT_REFERENCE / base.GetWidth();
272
if ( (m_minX < 0) && (m_maxX > 0) )
274
int center = (0 - m_minX) * (float) base.GetWidth() / (float) (m_maxX - m_minX);
275
int start_x = base.x + center - Funit * base.GetWidth() / rangex;
278
while (start_x > base.x)
280
GetPainter().Draw2DLine (GfxContext, start_x, base.y + base.GetHeight(), start_x, base.y + base.GetHeight() - 5, Color (0xFF000000) );
282
start_x -= Funit * base.GetWidth() / rangex;
285
start_x = base.x + center + Funit * base.GetWidth() / rangex;
288
while (start_x < base.x + base.GetWidth() )
290
GetPainter().Draw2DLine (GfxContext, start_x, base.y + base.GetHeight(), start_x, base.y + base.GetHeight() - 5, Color (0xFF000000) );
292
start_x += Funit * base.GetWidth() / rangex;
298
int center = (m_minX - 0) * (float) base.GetWidth() / (float) (m_maxX - m_minX);
299
int start_x = base.x - center + Funit * base.GetWidth() / rangex;
302
while (start_x < base.x + base.GetWidth() )
304
GetPainter().Draw2DLine (GfxContext, start_x, base.y + base.GetHeight(), start_x, base.y + base.GetHeight() - 5, Color (0xFF000000) );
306
start_x += Funit * base.GetWidth() / rangex;
312
int center = (0 - m_minX) * (float) base.GetWidth() / (float) (m_maxX - m_minX);
313
int start_x = base.x + center - Funit * base.GetWidth() / rangex;
316
while (start_x > base.x)
318
GetPainter().Draw2DLine (GfxContext, start_x, base.y + base.GetHeight(), start_x, base.y + base.GetHeight() - 5, Color (0xFF000000) );
320
start_x -= Funit * base.GetWidth() / rangex;
324
// Draw Vertical ruler
326
static float FunitY = 1.0;
327
float rangey = m_maxY - m_minY;
328
int IunitY = FunitY * base.GetHeight() / rangey;
330
if (IunitY > 2 * UNIT_REFERENCE)
332
FunitY = rangey * UNIT_REFERENCE / base.GetHeight();
334
else if (IunitY < UNIT_REFERENCE)
336
FunitY = rangey * 2 * UNIT_REFERENCE / base.GetHeight();
339
if ( (m_minY < 0) && (m_maxY > 0) )
341
int center = (0 - m_minY) * (float) base.GetHeight() / (float) (m_maxY - m_minY);
342
int start_y = base.y + base.GetHeight() - center - FunitY * base.GetHeight() / rangey;
345
while (start_y > base.y)
347
GetPainter().Draw2DLine (GfxContext, base.x, start_y , base.x + 5, start_y, Color (0xFF000000) );
349
start_y -= FunitY * base.GetHeight() / rangey;
352
start_y = base.y + base.GetHeight() - center + FunitY * base.GetHeight() / rangey;
355
while (start_y < base.y + base.GetHeight() )
357
GetPainter().Draw2DLine (GfxContext, base.x, start_y , base.x + 5, start_y, Color (0xFF000000) );
359
start_y += FunitY * base.GetHeight() / rangey;
365
int center = (m_minY - 0) * (float) base.GetHeight() / (float) (m_maxY - m_minY);
366
int start_y = base.y + base.GetHeight() + center - FunitY * base.GetHeight() / rangey;
369
while (start_y > base.y)
371
GetPainter().Draw2DLine (GfxContext, base.x, start_y , base.x + 5, start_y, Color (0xFF000000) );
373
start_y -= FunitY * base.GetHeight() / rangey;
379
int center = (0 - m_minY) * (float) base.GetHeight() / (float) (m_maxY - m_minY);
380
int start_y = base.y + base.GetHeight() - center + FunitY * base.GetHeight() / rangey;
383
while (start_y < base.y + base.GetHeight() )
385
GetPainter().Draw2DLine (GfxContext, base.x, start_y , base.x + 5, start_y, Color (0xFF000000) );
387
start_y += FunitY * base.GetHeight() / rangey;
392
void BezierCurveControl2::DrawGrid (GraphicsEngine &GfxContext)
394
Geometry base = GetGeometry();
396
base.OffsetPosition (GRAPH_MARGIN, GRAPH_MARGIN);
397
base.OffsetSize (-2 * GRAPH_MARGIN, -2 * GRAPH_MARGIN);
399
// Draw Vertical Grid
401
static float Funit = 1.0;
402
float rangex = m_maxX - m_minX;
403
int Iunit = Funit * base.GetWidth() / rangex;
405
if (Iunit > 2 * UNIT_REFERENCE)
407
Funit = rangex * UNIT_REFERENCE / base.GetWidth();
409
else if (Iunit < UNIT_REFERENCE)
411
Funit = rangex * 2 * UNIT_REFERENCE / base.GetWidth();
414
if ( (m_minX < 0) && (m_maxX > 0) )
416
int center = (0 - m_minX) * (float) base.GetWidth() / (float) (m_maxX - m_minX);
417
int start_x = base.x + center - Funit * base.GetWidth() / rangex;
420
while (start_x > base.x)
423
GetPainter().Draw2DLine (GfxContext, start_x, base.y,
424
start_x, base.y + base.GetHeight(), Color (0xFF5F5F5F) );
427
start_x -= Funit * base.GetWidth() / rangex;
430
start_x = base.x + center + Funit * base.GetWidth() / rangex;
433
while (start_x < base.x + base.GetWidth() )
436
GetPainter().Draw2DLine (GfxContext, start_x, base.y,
437
start_x, base.y + base.GetHeight(), Color (0xFF5F5F5F) );
440
start_x += Funit * base.GetWidth() / rangex;
446
int center = (m_minX - 0) * (float) base.GetWidth() / (float) (m_maxX - m_minX);
447
int start_x = base.x - center + Funit * base.GetWidth() / rangex;
450
while (start_x < base.x + base.GetWidth() )
453
GetPainter().Draw2DLine (GfxContext, start_x, base.y,
454
start_x, base.y + base.GetHeight(), Color (0xFF5F5F5F) );
457
start_x += Funit * base.GetWidth() / rangex;
463
int center = (0 - m_minX) * (float) base.GetWidth() / (float) (m_maxX - m_minX);
464
int start_x = base.x + center - Funit * base.GetWidth() / rangex;
467
while (start_x > base.x)
470
GetPainter().Draw2DLine (GfxContext, start_x, base.y,
471
start_x, base.y + base.GetHeight(), Color (0xFF5F5F5F) );
474
start_x -= Funit * base.GetWidth() / rangex;
478
// Draw Horizontal Grid
480
static float FunitY = 1.0;
481
float rangey = m_maxY - m_minY;
482
int IunitY = FunitY * base.GetHeight() / rangey;
484
if (IunitY > 2 * UNIT_REFERENCE)
486
FunitY = rangey * UNIT_REFERENCE / base.GetHeight();
488
else if (IunitY < UNIT_REFERENCE)
490
FunitY = rangey * 2 * UNIT_REFERENCE / base.GetHeight();
493
if ( (m_minY < 0) && (m_maxY > 0) )
495
int center = (0 - m_minY) * (float) base.GetHeight() / (float) (m_maxY - m_minY);
496
int start_y = base.y + base.GetHeight() - center - FunitY * base.GetHeight() / rangey;
499
while (start_y > base.y)
502
GetPainter().Draw2DLine (GfxContext, base.x, start_y,
503
base.x + base.GetWidth(), start_y, Color (0xFF5F5F5F) );
506
start_y -= FunitY * base.GetHeight() / rangey;
509
start_y = base.y + base.GetHeight() - center + FunitY * base.GetHeight() / rangey;
512
while (start_y < base.y + base.GetHeight() )
514
GetPainter().Draw2DLine (GfxContext, base.x, start_y,
515
base.x + base.GetWidth(), start_y, Color (0xFF5F5F5F) );
518
start_y += FunitY * base.GetHeight() / rangey;
524
int center = (m_minY - 0) * (float) base.GetHeight() / (float) (m_maxY - m_minY);
525
int start_y = base.y + base.GetHeight() + center - FunitY * base.GetHeight() / rangey;
528
while (start_y > base.y)
530
GetPainter().Draw2DLine (GfxContext, base.x, start_y,
531
base.x + base.GetWidth(), start_y, Color (0xFF5F5F5F) );
534
start_y -= FunitY * base.GetHeight() / rangey;
540
int center = (0 - m_minY) * (float) base.GetHeight() / (float) (m_maxY - m_minY);
541
int start_y = base.y + base.GetHeight() - center + FunitY * base.GetHeight() / rangey;
544
while (start_y < base.y + base.GetHeight() )
546
GetPainter().Draw2DLine (GfxContext, base.x, start_y,
547
base.x + base.GetWidth(), start_y, Color (0xFF5F5F5F) );
550
start_y += FunitY * base.GetHeight() / rangey;
555
void BezierCurveControl2::DrawCoordinateSystem (GraphicsEngine &GfxContext)
557
int W = GetBaseWidth() - 2 * GRAPH_MARGIN;
558
int H = GetBaseHeight() - 2 * GRAPH_MARGIN;
559
int X = GetBaseX() + GRAPH_MARGIN;
560
int Y = GetBaseY() + GRAPH_MARGIN;
563
X0 = X + W * (0 - m_minX) / (m_maxX - m_minX);
564
Y0 = Y + H * ( 1 - (0 - m_minY) / (m_maxY - m_minY) );
566
GetPainter().Draw2DLine (GfxContext, X0, Y, X0, Y + H, Color (0xFF222222) );
567
GetPainter().Draw2DLine (GfxContext, X, Y0, X + W, Y0, Color (0xFF000000) );
570
void BezierCurveControl2::DrawContent (GraphicsEngine &GfxContext, bool force_draw)
575
void BezierCurveControl2::PostDraw (GraphicsEngine &GfxContext, bool force_draw)
581
void BezierCurveControl2::SetXAxisBounds (float minX, float maxX)
588
void BezierCurveControl2::SetYAxisBounds (float minY, float maxY)
595
void BezierCurveControl2::SetFunctionCallback (FunctionCallback f)
597
m_FunctionCallback = f;
601
float BezierCurveControl2::EvalFunction (float x)
603
if (m_FunctionCallback != 0)
604
return (*m_FunctionCallback) (x);
609
void BezierCurveControl2::UpdateGraph()
615
// check if a value lies within a closed interval
616
#ifndef INSIDE_BOUNDS
617
#define INSIDE_BOUNDS( x, lo, hi ) ( (x) >= (lo) && (x) <= (hi) )
620
//check if a 2D point lies within a 2D box
621
#ifndef PT_INSIDE_BOX
622
#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) )
625
void BezierCurveControl2::RecvMouseUp (int x, int y, unsigned long button_flags, unsigned long key_flags)
630
void BezierCurveControl2::RecvMouseDown (int x, int y, unsigned long button_flags, unsigned long key_flags)
632
if (! (button_flags & NUX_EVENT_BUTTON1) )
637
m_bControlPointSelected = false;
638
t_u32 nbKnot = (t_u32) m_control_knot.size();
640
for (t_u32 i = 0; i < nbKnot; i++)
642
m_control_knot[i].m_IsSelected = false;
645
int W = GetBaseWidth() - 2 * GRAPH_MARGIN;
646
int H = GetBaseHeight() - 2 * GRAPH_MARGIN;
647
int X = GetBaseX() + GRAPH_MARGIN;
648
int Y = GetBaseY() + GRAPH_MARGIN;
650
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);
657
for (t_u32 i = 0; i < nbKnot; i++)
660
Xp = X + W * (m_control_knot[i].m_X - m_minX) / (m_maxX - m_minX);
661
Yp = Y + H * ( 1 - (m_control_knot[i].m_Y - m_minY) / (m_maxY - m_minY) );
664
tx = X + x - GRAPH_MARGIN;
665
ty = Y + y - GRAPH_MARGIN;
667
if (PT_INSIDE_BOX (tx, ty, Xp - KNOT_HIT_TEST, Xp + KNOT_HIT_TEST, Yp - KNOT_HIT_TEST, Yp + KNOT_HIT_TEST) )
669
m_control_knot[i].m_IsSelected = true;
670
hit_point_dx = (tx) - Xp;
671
hit_point_dy = Yp - (ty);
673
m_bControlPointSelected = true;
675
if ( (i % CURVE_DEGREE) == 0)
677
// this is a control point at the begining of a cubic bezier curve
678
// Also select the control points defining the entering and exiting tangent at this point.
688
int ClosestCubicBezierEndPoint (int i)
690
if ( (i % CURVE_DEGREE) == 0)
695
if ( ( (i + 1) % CURVE_DEGREE) == 0)
700
if ( ( (i - 1) % CURVE_DEGREE) == 0)
708
void BezierCurveControl2::RecvKeyEvent (
709
GraphicsEngine &GfxContext , /*Graphics Context for text operation*/
710
unsigned long eventType , /*event type*/
711
unsigned long keysym , /*event keysym*/
712
unsigned long state , /*event state*/
713
TCHAR character , /*character*/
714
unsigned short keyCount /*key repeat count*/
720
void BezierCurveControl2::RecvMouseDrag (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
722
if ( (m_bControlPointSelected == false) && (button_flags & NUX_STATE_BUTTON1_DOWN) && S_KEY)
724
if (m_bPanningEnabled)
726
ProcessPanning (x, y, dx, dy, button_flags, key_flags);
731
if ( (m_bControlPointSelected == false) && (button_flags & NUX_STATE_BUTTON3_DOWN) && S_KEY)
733
if (m_bZoomingEnabled)
735
ProcessZooming (x, y, dx, dy, button_flags, key_flags);
740
if (button_flags & NUX_STATE_BUTTON1_DOWN)
741
ManipulateBezier (x, y, dx, dy, button_flags, key_flags);
744
void BezierCurveControl2::ManipulateBezier (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
747
int W = GetBaseWidth() - 2 * GRAPH_MARGIN;
748
int H = GetBaseHeight() - 2 * GRAPH_MARGIN;
749
int X = GetBaseX() + GRAPH_MARGIN;
750
int Y = GetBaseY() + GRAPH_MARGIN;
752
t_s32 nbKnot = (t_s32) m_control_knot.size();
754
xp = /*m_minX +*/ dx * (m_maxX - m_minX) / W;
755
yp = /*m_minY +*/ dy * (m_maxY - m_minY) / H;
757
nuxAssert (nbKnot >= CURVE_DEGREE);
761
for (t_s32 i = 0; i < nbKnot; i++)
763
if (m_control_knot[i].m_IsSelected)
766
tempx = X + x - GRAPH_MARGIN;
767
tempy = Y + y - GRAPH_MARGIN;
770
Xp = X + W * (m_control_knot[i].m_X - m_minX) / (m_maxX - m_minX);
771
Yp = Y + H * ( 1 - (m_control_knot[i].m_Y - m_minY) / (m_maxY - m_minY) );
775
if (tempx > Xp + hit_point_dx)
777
xp = /*m_minX +*/ (m_maxX - m_minX) * (tempx - Xp - hit_point_dx) / W;
786
if (tempx < Xp + hit_point_dx)
788
xp = /*m_minX +*/ (m_maxX - m_minX) * (tempx - Xp - hit_point_dx) / W;
798
if (tempy > Yp - hit_point_dy)
800
yp = /*m_minY +*/ (m_maxY - m_minY) * (tempy - Yp + hit_point_dy) / H;
809
if (tempy < Yp - hit_point_dy)
811
yp = /*m_minY +*/ (m_maxY - m_minY) * (tempy - Yp + hit_point_dy) / H;
819
if (m_bPanningEnabled == false)
821
if (m_control_knot[i].m_X + xp < m_minX)
823
xp = m_minX - m_control_knot[i].m_X;
826
else if (m_control_knot[i].m_X + xp > m_maxX)
828
xp = m_maxX - m_control_knot[i].m_X;
832
if (m_control_knot[i].m_Y - yp < m_minY)
834
yp = m_control_knot[i].m_Y - m_minY;
837
else if (m_control_knot[i].m_Y - yp > m_maxY)
839
yp = m_control_knot[i].m_Y - m_maxY;
845
if ( (i % CURVE_DEGREE) == 0)
848
m_control_knot[i].m_Y -= yp;
849
else if (y_border == -1)
850
m_control_knot[i].m_Y = m_minY;
851
else if (y_border == +1)
852
m_control_knot[i].m_Y = m_maxY;
854
// Only endpoint of cubic bezier curves.
859
if ( m_control_knot[i].m_X + xp > m_control_knot[i + CURVE_DEGREE].m_X - 0.01)
861
xp = (m_control_knot[i + CURVE_DEGREE].m_X - 0.01) - m_control_knot[i].m_X;
862
m_control_knot[i].m_X = m_control_knot[i + CURVE_DEGREE].m_X - 0.01;
866
m_control_knot[i].m_X += xp;
872
m_control_knot[i].m_X = m_minX;
873
else if (x_border == +1)
874
m_control_knot[i].m_X = m_maxX;
876
if ( m_control_knot[i].m_X > m_control_knot[i + CURVE_DEGREE].m_X - 0.01)
878
xp += (m_control_knot[i + CURVE_DEGREE].m_X - 0.01) - m_control_knot[i].m_X;
879
m_control_knot[i].m_X = m_control_knot[i + CURVE_DEGREE].m_X - 0.01;
883
// move the right tangent points
885
m_control_knot[i+1].m_X += xp;
886
m_control_knot[i+1].m_Y -= yp;
888
if (m_control_knot[i+1].m_X < m_control_knot[i].m_X)
890
m_control_knot[i+1].m_X = m_control_knot[i].m_X;
894
else if (i == nbKnot - 1)
898
if (m_control_knot[i].m_X + xp < m_control_knot[i - CURVE_DEGREE].m_X + 0.01)
900
xp = - (m_control_knot[i].m_X - (m_control_knot[i - CURVE_DEGREE].m_X + 0.01) );
901
m_control_knot[i].m_X = m_control_knot[i - CURVE_DEGREE].m_X + 0.01;
905
m_control_knot[i].m_X += xp;
911
m_control_knot[i].m_X = m_minX;
912
else if (x_border == +1)
913
m_control_knot[i].m_X = m_maxX;
915
if (m_control_knot[i].m_X < m_control_knot[i - CURVE_DEGREE].m_X + 0.01)
917
xp += (m_control_knot[i - CURVE_DEGREE].m_X + 0.01) - m_control_knot[i].m_X;
918
m_control_knot[i].m_X = m_control_knot[i - CURVE_DEGREE].m_X + 0.01;
922
// move the left tangent points
924
m_control_knot[i-1].m_X += xp;
925
m_control_knot[i-1].m_Y -= yp;
927
if (m_control_knot[i-1].m_X > m_control_knot[i].m_X)
929
m_control_knot[i-1].m_X = m_control_knot[i].m_X;
935
if (m_control_knot[i].m_X + xp > m_control_knot[i + CURVE_DEGREE].m_X - 0.01)
937
xp = (m_control_knot[i + CURVE_DEGREE].m_X - 0.01) - m_control_knot[i].m_X;
938
m_control_knot[i].m_X = m_control_knot[i + CURVE_DEGREE].m_X - 0.01;
940
else if (m_control_knot[i].m_X + xp < m_control_knot[i - CURVE_DEGREE].m_X + 0.01)
942
xp = m_control_knot[i].m_X - (m_control_knot[i - CURVE_DEGREE].m_X + 0.01);
943
m_control_knot[i].m_X = m_control_knot[i - CURVE_DEGREE].m_X + 0.01;
947
m_control_knot[i].m_X += xp;
950
// move the left and right tangent points
952
m_control_knot[i-1].m_X += xp;
953
m_control_knot[i+1].m_X += xp;
954
m_control_knot[i-1].m_Y -= yp;
955
m_control_knot[i+1].m_Y -= yp;
957
if (m_control_knot[i-1].m_X > m_control_knot[i].m_X)
959
m_control_knot[i-1].m_X = m_control_knot[i].m_X;
962
if (m_control_knot[i+1].m_X < m_control_knot[i].m_X)
964
m_control_knot[i+1].m_X = m_control_knot[i].m_X;
971
m_control_knot[i].m_X += xp;
972
m_control_knot[i].m_Y -= yp;
974
t_s32 index = (t_s32) ClosestCubicBezierEndPoint (i);
978
if (m_control_knot[i].m_X > m_control_knot[index].m_X)
980
m_control_knot[i].m_X = m_control_knot[index].m_X;
985
if (m_control_knot[i].m_X < m_control_knot[index].m_X)
987
m_control_knot[i].m_X = m_control_knot[index].m_X;
999
void BezierCurveControl2::ProcessPanning (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
1002
int W = GetBaseWidth() - 2 * GRAPH_MARGIN;
1003
int H = GetBaseHeight() - 2 * GRAPH_MARGIN;
1005
xp = /*m_minX +*/ dx * (m_maxX - m_minX) / W;
1006
yp = /*m_minY +*/ dy * (m_maxY - m_minY) / H;
1008
if (m_bControlPointSelected == false)
1010
if (m_bPanningEnabled)
1023
void BezierCurveControl2::ProcessZooming (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
1026
int W = GetBaseWidth() - 2 * GRAPH_MARGIN;
1027
int H = GetBaseHeight() - 2 * GRAPH_MARGIN;
1029
xp = /*m_minX +*/ dx * (m_maxX - m_minX) / W;
1030
yp = /*m_minY +*/ dy * (m_maxY - m_minY) / H;
1032
if ( (m_minX + yp >= m_maxX - yp) || (m_minY + yp >= m_maxY - yp) )
1037
if (m_bControlPointSelected == false)
1039
if (m_bZoomingEnabled)
2
* Copyright 2010 Inalogic Inc.
4
* This program is free software: you can redistribute it and/or modify it
5
* under the terms of the GNU Lesser General Public License version 3, as
6
* published by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranties of
10
* MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
11
* PURPOSE. See the applicable version of the GNU Lesser General Public
12
* License for more details.
14
* You should have received a copy of both the GNU Lesser General Public
15
* License version 3 along with this program. If not, see
16
* <http://www.gnu.org/licenses/>
18
* Authored by: Jay Taoko <jaytaoko@inalogic.com>
25
#include "BezierCurveControl2.h"
26
#include "NuxCore/Math/Bezier.h"
31
static const int KNOT_SIZE = 2;
32
static const int KNOT_HIT_TEST = 4;
33
static const int CURVE_DEGREE = 3;
34
static const int GRAPH_MARGIN = 2;
35
static const int UNIT_REFERENCE = 15;
37
unsigned long S_KEY = 0;
39
BezierCurveControl2::BezierCurveControl2 (NUX_FILE_LINE_DECL)
40
: View (NUX_FILE_LINE_PARAM)
45
m_FunctionCallback (0),
46
m_bControlPointSelected (0),
47
m_bPanningEnabled (true),
48
m_bZoomingEnabled (true)
50
SetMinimumSize (180, 180);
52
m_control_knot.push_back (Knot2 (0.0f, 0.0f) );
53
m_control_knot.push_back (Knot2 (0.1f, 0.0f) );
54
m_control_knot.push_back (Knot2 (0.7f, 0.9f) );
55
m_control_knot.push_back (Knot2 (1.0f, 1.0f) );
57
OnMouseDown.connect (sigc::mem_fun (this, &BezierCurveControl2::RecvMouseDown) );
58
OnMouseUp.connect (sigc::mem_fun (this, &BezierCurveControl2::RecvMouseUp) );
59
OnMouseDrag.connect (sigc::mem_fun (this, &BezierCurveControl2::RecvMouseDrag) );
61
OnKeyEvent.connect (sigc::mem_fun (this, &BezierCurveControl2::RecvKeyEvent) );
64
MakeCheckBoardImage (image.GetSurface (0), 64, 64, Color (0xff323232), Color (0xff535353), 8, 8);
65
BaseTexture* m_CheckboardPattern = GetThreadGLDeviceFactory()->CreateSystemCapableTexture ();
66
m_CheckboardPattern->Update (&image);
68
TexCoordXForm texxform;
69
texxform.SetTexCoordType (TexCoordXForm::OFFSET_COORD);
70
texxform.SetWrap (TEXWRAP_REPEAT, TEXWRAP_REPEAT);
71
m_Background = new TextureLayer (m_CheckboardPattern->GetDeviceTexture(), texxform, Color::White);
73
m_CheckboardPattern->UnReference ();
76
BezierCurveControl2::~BezierCurveControl2()
78
NUX_SAFE_DELETE (m_Background);
82
long BezierCurveControl2::ProcessEvent (IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
84
long ret = TraverseInfo;
86
if (ievent.e_event == NUX_MOUSE_PRESSED)
88
if (!m_Geometry.IsPointInside (ievent.e_x, ievent.e_y) )
90
//ProcEvInfo = eDoNotProcess;
91
//return TraverseInfo;
95
S_KEY = ievent.GetVirtualKeyState (NUX_VK_S);
96
ret = PostProcessEvent2 (ievent, ret, ProcessEventInfo);
101
void BezierCurveControl2::Draw (GraphicsEngine &GfxContext, bool force_draw)
103
Geometry base = GetGeometry();
105
GetPainter().PaintBackground (GfxContext, base);
106
GetPainter().Paint2DQuadColor (GfxContext, base, Color (COLOR_BACKGROUND_PRIMARY) );
107
base.OffsetPosition (GRAPH_MARGIN, GRAPH_MARGIN);
108
base.OffsetSize (-2 * GRAPH_MARGIN, -2 * GRAPH_MARGIN);
110
int W = GetBaseWidth() - 2 * GRAPH_MARGIN;
111
int H = GetBaseHeight() - 2 * GRAPH_MARGIN;
112
int X = GetBaseX() + GRAPH_MARGIN;
113
int Y = GetBaseY() + GRAPH_MARGIN;
116
int nsample = base.GetWidth();
118
t_u32 nbKnot = (t_u32) m_control_knot.size();
120
GfxContext.PushClippingRectangle (base);
122
GetPainter().PushDrawLayer (GfxContext, base, m_Background);
123
GetPainter().PopBackground();
125
//DrawGrid(GfxContext);
126
DrawCoordinateSystem (GfxContext);
130
double *xcon = new double[nbKnot];
132
double *ycon = new double[nbKnot];
136
for (i = 0; i < nbKnot; i++)
138
xcon[i] = m_control_knot[i].m_X;
139
ycon[i] = m_control_knot[i].m_Y;
143
Bezier_XY (CURVE_DEGREE, 0.0, xcon, ycon, &xprev, &yprev);
145
int X0, Y0, X1, Y1, X2, Y2;
147
glEnable (GL_POINT_SMOOTH);
148
glEnable (GL_LINE_SMOOTH);
150
glHint (GL_POINT_SMOOTH_HINT, GL_NICEST); // Make round points, not square points
151
glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); // Antialias the lines
152
GfxContext.GetRenderStates().SetBlend (TRUE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
154
for (i = 1; i < (t_u32) nsample; i++ )
156
t = ( double ) ( i ) / ( double ) ( nsample - 1 );
157
Bezier_XY ( CURVE_DEGREE, t, xcon, ycon, &xval, &yval );
159
X0 = X + W * (xprev - m_minX) / (m_maxX - m_minX);
160
Y0 = Y + H * ( 1 - (yprev - m_minY) / (m_maxY - m_minY) );
161
X1 = X + W * (xval - m_minX) / (m_maxX - m_minX);
162
Y1 = Y + H * ( 1 - (yval - m_minY) / (m_maxY - m_minY) );
164
GetPainter().Draw2DLine (GfxContext, X0, Y0, X1, Y1, Color (0xFFFFFFFF) );
170
if (m_control_knot[0].m_X > m_minX)
172
// draw line from the left border to the left most control point.
174
X0 = X + W * (m_control_knot[0].m_X - m_minX) / (m_maxX - m_minX);
175
Y0 = Y + H * ( 1 - (m_control_knot[0].m_Y - m_minY) / (m_maxY - m_minY) );
177
GetPainter().Draw2DLine (GfxContext, base.x, Y0, X0, Y0, Color (0xFFFFFFFF) );
180
if (m_control_knot[nbKnot-1].m_X < m_maxX)
182
// draw line from the right most control point to the left border.
184
X0 = X + W * (m_control_knot[nbKnot-1].m_X - m_minX) / (m_maxX - m_minX);
185
Y0 = Y + H * ( 1 - (m_control_knot[nbKnot-1].m_Y - m_minY) / (m_maxY - m_minY) );
187
GetPainter().Draw2DLine (GfxContext, X0, Y0, base.x + base.GetWidth(), Y0, Color (0xFFFFFFFF) );
190
glDisable (GL_POINT_SMOOTH);
191
glDisable (GL_LINE_SMOOTH);
192
GfxContext.GetRenderStates().SetBlend (FALSE);
194
for (i = 0; i <= nbKnot - 1; i += CURVE_DEGREE)
196
// Only the endpoint of cubic bezier.
198
X0 = X + W * (m_control_knot[i].m_X - m_minX) / (m_maxX - m_minX);
199
Y0 = Y + H * ( 1 - (m_control_knot[i].m_Y - m_minY) / (m_maxY - m_minY) );
203
X1 = X + W * (m_control_knot[i+1].m_X - m_minX) / (m_maxX - m_minX);
204
Y1 = Y + H * ( 1 - (m_control_knot[i+1].m_Y - m_minY) / (m_maxY - m_minY) );
206
GetPainter().Draw2DLine (GfxContext, X0, Y0, X1, Y1, Color (0xFF0000FF) );
211
X2 = X + W * (m_control_knot[i-1].m_X - m_minX) / (m_maxX - m_minX);
212
Y2 = Y + H * ( 1 - (m_control_knot[i-1].m_Y - m_minY) / (m_maxY - m_minY) );
214
GetPainter().Draw2DLine (GfxContext, X0, Y0, X2, Y2, Color (0xFF0000FF) );
218
Geometry ShapeGeo = GetTheme().GetImageGeometry (eDOT6x6);
220
for (i = 0; i < nbKnot; i++)
223
X0 = X + W * (m_control_knot[i].m_X - m_minX) / (m_maxX - m_minX);
224
Y0 = Y + H * ( 1 - (m_control_knot[i].m_Y - m_minY) / (m_maxY - m_minY) );
226
if (m_control_knot[i].m_IsSelected)
228
GetPainter().PaintShape (GfxContext,
229
Geometry (X0 - ShapeGeo.GetWidth() / 2, Y0 - ShapeGeo.GetHeight() / 2, ShapeGeo.GetWidth(), ShapeGeo.GetHeight() ),
230
Color (0xFF44FF44), eDOT6x6);
234
GetPainter().PaintShape (GfxContext,
235
Geometry (X0 - ShapeGeo.GetWidth() / 2, Y0 - ShapeGeo.GetHeight() / 2, ShapeGeo.GetWidth(), ShapeGeo.GetHeight() ),
236
Color (0xFFFFFFFF), eDOT6x6);
244
GetPainter().Paint2DQuadWireframe (GfxContext, base, Color (0xFF000000) );
246
DrawRuler (GfxContext);
247
GfxContext.PopClippingRectangle();
250
void BezierCurveControl2::DrawRuler (GraphicsEngine &GfxContext)
252
Geometry base = GetGeometry();
254
base.OffsetPosition (GRAPH_MARGIN, GRAPH_MARGIN);
255
base.OffsetSize (-2 * GRAPH_MARGIN, -2 * GRAPH_MARGIN);
257
// Draw Horizontal ruler
259
static float Funit = 1.0;
260
float rangex = m_maxX - m_minX;
261
int Iunit = Funit * base.GetWidth() / rangex;
263
if (Iunit > 2 * UNIT_REFERENCE)
265
Funit = rangex * UNIT_REFERENCE / base.GetWidth();
267
else if (Iunit < UNIT_REFERENCE)
269
Funit = rangex * 2 * UNIT_REFERENCE / base.GetWidth();
272
if ( (m_minX < 0) && (m_maxX > 0) )
274
int center = (0 - m_minX) * (float) base.GetWidth() / (float) (m_maxX - m_minX);
275
int start_x = base.x + center - Funit * base.GetWidth() / rangex;
278
while (start_x > base.x)
280
GetPainter().Draw2DLine (GfxContext, start_x, base.y + base.GetHeight(), start_x, base.y + base.GetHeight() - 5, Color (0xFF000000) );
282
start_x -= Funit * base.GetWidth() / rangex;
285
start_x = base.x + center + Funit * base.GetWidth() / rangex;
288
while (start_x < base.x + base.GetWidth() )
290
GetPainter().Draw2DLine (GfxContext, start_x, base.y + base.GetHeight(), start_x, base.y + base.GetHeight() - 5, Color (0xFF000000) );
292
start_x += Funit * base.GetWidth() / rangex;
298
int center = (m_minX - 0) * (float) base.GetWidth() / (float) (m_maxX - m_minX);
299
int start_x = base.x - center + Funit * base.GetWidth() / rangex;
302
while (start_x < base.x + base.GetWidth() )
304
GetPainter().Draw2DLine (GfxContext, start_x, base.y + base.GetHeight(), start_x, base.y + base.GetHeight() - 5, Color (0xFF000000) );
306
start_x += Funit * base.GetWidth() / rangex;
312
int center = (0 - m_minX) * (float) base.GetWidth() / (float) (m_maxX - m_minX);
313
int start_x = base.x + center - Funit * base.GetWidth() / rangex;
316
while (start_x > base.x)
318
GetPainter().Draw2DLine (GfxContext, start_x, base.y + base.GetHeight(), start_x, base.y + base.GetHeight() - 5, Color (0xFF000000) );
320
start_x -= Funit * base.GetWidth() / rangex;
324
// Draw Vertical ruler
326
static float FunitY = 1.0;
327
float rangey = m_maxY - m_minY;
328
int IunitY = FunitY * base.GetHeight() / rangey;
330
if (IunitY > 2 * UNIT_REFERENCE)
332
FunitY = rangey * UNIT_REFERENCE / base.GetHeight();
334
else if (IunitY < UNIT_REFERENCE)
336
FunitY = rangey * 2 * UNIT_REFERENCE / base.GetHeight();
339
if ( (m_minY < 0) && (m_maxY > 0) )
341
int center = (0 - m_minY) * (float) base.GetHeight() / (float) (m_maxY - m_minY);
342
int start_y = base.y + base.GetHeight() - center - FunitY * base.GetHeight() / rangey;
345
while (start_y > base.y)
347
GetPainter().Draw2DLine (GfxContext, base.x, start_y , base.x + 5, start_y, Color (0xFF000000) );
349
start_y -= FunitY * base.GetHeight() / rangey;
352
start_y = base.y + base.GetHeight() - center + FunitY * base.GetHeight() / rangey;
355
while (start_y < base.y + base.GetHeight() )
357
GetPainter().Draw2DLine (GfxContext, base.x, start_y , base.x + 5, start_y, Color (0xFF000000) );
359
start_y += FunitY * base.GetHeight() / rangey;
365
int center = (m_minY - 0) * (float) base.GetHeight() / (float) (m_maxY - m_minY);
366
int start_y = base.y + base.GetHeight() + center - FunitY * base.GetHeight() / rangey;
369
while (start_y > base.y)
371
GetPainter().Draw2DLine (GfxContext, base.x, start_y , base.x + 5, start_y, Color (0xFF000000) );
373
start_y -= FunitY * base.GetHeight() / rangey;
379
int center = (0 - m_minY) * (float) base.GetHeight() / (float) (m_maxY - m_minY);
380
int start_y = base.y + base.GetHeight() - center + FunitY * base.GetHeight() / rangey;
383
while (start_y < base.y + base.GetHeight() )
385
GetPainter().Draw2DLine (GfxContext, base.x, start_y , base.x + 5, start_y, Color (0xFF000000) );
387
start_y += FunitY * base.GetHeight() / rangey;
392
void BezierCurveControl2::DrawGrid (GraphicsEngine &GfxContext)
394
Geometry base = GetGeometry();
396
base.OffsetPosition (GRAPH_MARGIN, GRAPH_MARGIN);
397
base.OffsetSize (-2 * GRAPH_MARGIN, -2 * GRAPH_MARGIN);
399
// Draw Vertical Grid
401
static float Funit = 1.0;
402
float rangex = m_maxX - m_minX;
403
int Iunit = Funit * base.GetWidth() / rangex;
405
if (Iunit > 2 * UNIT_REFERENCE)
407
Funit = rangex * UNIT_REFERENCE / base.GetWidth();
409
else if (Iunit < UNIT_REFERENCE)
411
Funit = rangex * 2 * UNIT_REFERENCE / base.GetWidth();
414
if ( (m_minX < 0) && (m_maxX > 0) )
416
int center = (0 - m_minX) * (float) base.GetWidth() / (float) (m_maxX - m_minX);
417
int start_x = base.x + center - Funit * base.GetWidth() / rangex;
420
while (start_x > base.x)
423
GetPainter().Draw2DLine (GfxContext, start_x, base.y,
424
start_x, base.y + base.GetHeight(), Color (0xFF5F5F5F) );
427
start_x -= Funit * base.GetWidth() / rangex;
430
start_x = base.x + center + Funit * base.GetWidth() / rangex;
433
while (start_x < base.x + base.GetWidth() )
436
GetPainter().Draw2DLine (GfxContext, start_x, base.y,
437
start_x, base.y + base.GetHeight(), Color (0xFF5F5F5F) );
440
start_x += Funit * base.GetWidth() / rangex;
446
int center = (m_minX - 0) * (float) base.GetWidth() / (float) (m_maxX - m_minX);
447
int start_x = base.x - center + Funit * base.GetWidth() / rangex;
450
while (start_x < base.x + base.GetWidth() )
453
GetPainter().Draw2DLine (GfxContext, start_x, base.y,
454
start_x, base.y + base.GetHeight(), Color (0xFF5F5F5F) );
457
start_x += Funit * base.GetWidth() / rangex;
463
int center = (0 - m_minX) * (float) base.GetWidth() / (float) (m_maxX - m_minX);
464
int start_x = base.x + center - Funit * base.GetWidth() / rangex;
467
while (start_x > base.x)
470
GetPainter().Draw2DLine (GfxContext, start_x, base.y,
471
start_x, base.y + base.GetHeight(), Color (0xFF5F5F5F) );
474
start_x -= Funit * base.GetWidth() / rangex;
478
// Draw Horizontal Grid
480
static float FunitY = 1.0;
481
float rangey = m_maxY - m_minY;
482
int IunitY = FunitY * base.GetHeight() / rangey;
484
if (IunitY > 2 * UNIT_REFERENCE)
486
FunitY = rangey * UNIT_REFERENCE / base.GetHeight();
488
else if (IunitY < UNIT_REFERENCE)
490
FunitY = rangey * 2 * UNIT_REFERENCE / base.GetHeight();
493
if ( (m_minY < 0) && (m_maxY > 0) )
495
int center = (0 - m_minY) * (float) base.GetHeight() / (float) (m_maxY - m_minY);
496
int start_y = base.y + base.GetHeight() - center - FunitY * base.GetHeight() / rangey;
499
while (start_y > base.y)
502
GetPainter().Draw2DLine (GfxContext, base.x, start_y,
503
base.x + base.GetWidth(), start_y, Color (0xFF5F5F5F) );
506
start_y -= FunitY * base.GetHeight() / rangey;
509
start_y = base.y + base.GetHeight() - center + FunitY * base.GetHeight() / rangey;
512
while (start_y < base.y + base.GetHeight() )
514
GetPainter().Draw2DLine (GfxContext, base.x, start_y,
515
base.x + base.GetWidth(), start_y, Color (0xFF5F5F5F) );
518
start_y += FunitY * base.GetHeight() / rangey;
524
int center = (m_minY - 0) * (float) base.GetHeight() / (float) (m_maxY - m_minY);
525
int start_y = base.y + base.GetHeight() + center - FunitY * base.GetHeight() / rangey;
528
while (start_y > base.y)
530
GetPainter().Draw2DLine (GfxContext, base.x, start_y,
531
base.x + base.GetWidth(), start_y, Color (0xFF5F5F5F) );
534
start_y -= FunitY * base.GetHeight() / rangey;
540
int center = (0 - m_minY) * (float) base.GetHeight() / (float) (m_maxY - m_minY);
541
int start_y = base.y + base.GetHeight() - center + FunitY * base.GetHeight() / rangey;
544
while (start_y < base.y + base.GetHeight() )
546
GetPainter().Draw2DLine (GfxContext, base.x, start_y,
547
base.x + base.GetWidth(), start_y, Color (0xFF5F5F5F) );
550
start_y += FunitY * base.GetHeight() / rangey;
555
void BezierCurveControl2::DrawCoordinateSystem (GraphicsEngine &GfxContext)
557
int W = GetBaseWidth() - 2 * GRAPH_MARGIN;
558
int H = GetBaseHeight() - 2 * GRAPH_MARGIN;
559
int X = GetBaseX() + GRAPH_MARGIN;
560
int Y = GetBaseY() + GRAPH_MARGIN;
563
X0 = X + W * (0 - m_minX) / (m_maxX - m_minX);
564
Y0 = Y + H * ( 1 - (0 - m_minY) / (m_maxY - m_minY) );
566
GetPainter().Draw2DLine (GfxContext, X0, Y, X0, Y + H, Color (0xFF222222) );
567
GetPainter().Draw2DLine (GfxContext, X, Y0, X + W, Y0, Color (0xFF000000) );
570
void BezierCurveControl2::DrawContent (GraphicsEngine &GfxContext, bool force_draw)
575
void BezierCurveControl2::PostDraw (GraphicsEngine &GfxContext, bool force_draw)
581
void BezierCurveControl2::SetXAxisBounds (float minX, float maxX)
588
void BezierCurveControl2::SetYAxisBounds (float minY, float maxY)
595
void BezierCurveControl2::SetFunctionCallback (FunctionCallback f)
597
m_FunctionCallback = f;
601
float BezierCurveControl2::EvalFunction (float x)
603
if (m_FunctionCallback != 0)
604
return (*m_FunctionCallback) (x);
609
void BezierCurveControl2::UpdateGraph()
615
// check if a value lies within a closed interval
616
#ifndef INSIDE_BOUNDS
617
#define INSIDE_BOUNDS( x, lo, hi ) ( (x) >= (lo) && (x) <= (hi) )
620
//check if a 2D point lies within a 2D box
621
#ifndef PT_INSIDE_BOX
622
#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) )
625
void BezierCurveControl2::RecvMouseUp (int x, int y, unsigned long button_flags, unsigned long key_flags)
630
void BezierCurveControl2::RecvMouseDown (int x, int y, unsigned long button_flags, unsigned long key_flags)
632
if (! (button_flags & NUX_EVENT_BUTTON1) )
637
m_bControlPointSelected = false;
638
t_u32 nbKnot = (t_u32) m_control_knot.size();
640
for (t_u32 i = 0; i < nbKnot; i++)
642
m_control_knot[i].m_IsSelected = false;
645
int W = GetBaseWidth() - 2 * GRAPH_MARGIN;
646
int H = GetBaseHeight() - 2 * GRAPH_MARGIN;
647
int X = GetBaseX() + GRAPH_MARGIN;
648
int Y = GetBaseY() + GRAPH_MARGIN;
650
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);
657
for (t_u32 i = 0; i < nbKnot; i++)
660
Xp = X + W * (m_control_knot[i].m_X - m_minX) / (m_maxX - m_minX);
661
Yp = Y + H * ( 1 - (m_control_knot[i].m_Y - m_minY) / (m_maxY - m_minY) );
664
tx = X + x - GRAPH_MARGIN;
665
ty = Y + y - GRAPH_MARGIN;
667
if (PT_INSIDE_BOX (tx, ty, Xp - KNOT_HIT_TEST, Xp + KNOT_HIT_TEST, Yp - KNOT_HIT_TEST, Yp + KNOT_HIT_TEST) )
669
m_control_knot[i].m_IsSelected = true;
670
hit_point_dx = (tx) - Xp;
671
hit_point_dy = Yp - (ty);
673
m_bControlPointSelected = true;
675
if ( (i % CURVE_DEGREE) == 0)
677
// this is a control point at the begining of a cubic bezier curve
678
// Also select the control points defining the entering and exiting tangent at this point.
688
int ClosestCubicBezierEndPoint (int i)
690
if ( (i % CURVE_DEGREE) == 0)
695
if ( ( (i + 1) % CURVE_DEGREE) == 0)
700
if ( ( (i - 1) % CURVE_DEGREE) == 0)
708
void BezierCurveControl2::RecvKeyEvent (
709
GraphicsEngine &GfxContext , /*Graphics Context for text operation*/
710
unsigned long eventType , /*event type*/
711
unsigned long keysym , /*event keysym*/
712
unsigned long state , /*event state*/
713
TCHAR character , /*character*/
714
unsigned short keyCount /*key repeat count*/
720
void BezierCurveControl2::RecvMouseDrag (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
722
if ( (m_bControlPointSelected == false) && (button_flags & NUX_STATE_BUTTON1_DOWN) && S_KEY)
724
if (m_bPanningEnabled)
726
ProcessPanning (x, y, dx, dy, button_flags, key_flags);
731
if ( (m_bControlPointSelected == false) && (button_flags & NUX_STATE_BUTTON3_DOWN) && S_KEY)
733
if (m_bZoomingEnabled)
735
ProcessZooming (x, y, dx, dy, button_flags, key_flags);
740
if (button_flags & NUX_STATE_BUTTON1_DOWN)
741
ManipulateBezier (x, y, dx, dy, button_flags, key_flags);
744
void BezierCurveControl2::ManipulateBezier (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
747
int W = GetBaseWidth() - 2 * GRAPH_MARGIN;
748
int H = GetBaseHeight() - 2 * GRAPH_MARGIN;
749
int X = GetBaseX() + GRAPH_MARGIN;
750
int Y = GetBaseY() + GRAPH_MARGIN;
752
t_s32 nbKnot = (t_s32) m_control_knot.size();
754
xp = /*m_minX +*/ dx * (m_maxX - m_minX) / W;
755
yp = /*m_minY +*/ dy * (m_maxY - m_minY) / H;
757
nuxAssert (nbKnot >= CURVE_DEGREE);
761
for (t_s32 i = 0; i < nbKnot; i++)
763
if (m_control_knot[i].m_IsSelected)
766
tempx = X + x - GRAPH_MARGIN;
767
tempy = Y + y - GRAPH_MARGIN;
770
Xp = X + W * (m_control_knot[i].m_X - m_minX) / (m_maxX - m_minX);
771
Yp = Y + H * ( 1 - (m_control_knot[i].m_Y - m_minY) / (m_maxY - m_minY) );
775
if (tempx > Xp + hit_point_dx)
777
xp = /*m_minX +*/ (m_maxX - m_minX) * (tempx - Xp - hit_point_dx) / W;
786
if (tempx < Xp + hit_point_dx)
788
xp = /*m_minX +*/ (m_maxX - m_minX) * (tempx - Xp - hit_point_dx) / W;
798
if (tempy > Yp - hit_point_dy)
800
yp = /*m_minY +*/ (m_maxY - m_minY) * (tempy - Yp + hit_point_dy) / H;
809
if (tempy < Yp - hit_point_dy)
811
yp = /*m_minY +*/ (m_maxY - m_minY) * (tempy - Yp + hit_point_dy) / H;
819
if (m_bPanningEnabled == false)
821
if (m_control_knot[i].m_X + xp < m_minX)
823
xp = m_minX - m_control_knot[i].m_X;
826
else if (m_control_knot[i].m_X + xp > m_maxX)
828
xp = m_maxX - m_control_knot[i].m_X;
832
if (m_control_knot[i].m_Y - yp < m_minY)
834
yp = m_control_knot[i].m_Y - m_minY;
837
else if (m_control_knot[i].m_Y - yp > m_maxY)
839
yp = m_control_knot[i].m_Y - m_maxY;
845
if ( (i % CURVE_DEGREE) == 0)
848
m_control_knot[i].m_Y -= yp;
849
else if (y_border == -1)
850
m_control_knot[i].m_Y = m_minY;
851
else if (y_border == +1)
852
m_control_knot[i].m_Y = m_maxY;
854
// Only endpoint of cubic bezier curves.
859
if ( m_control_knot[i].m_X + xp > m_control_knot[i + CURVE_DEGREE].m_X - 0.01)
861
xp = (m_control_knot[i + CURVE_DEGREE].m_X - 0.01) - m_control_knot[i].m_X;
862
m_control_knot[i].m_X = m_control_knot[i + CURVE_DEGREE].m_X - 0.01;
866
m_control_knot[i].m_X += xp;
872
m_control_knot[i].m_X = m_minX;
873
else if (x_border == +1)
874
m_control_knot[i].m_X = m_maxX;
876
if ( m_control_knot[i].m_X > m_control_knot[i + CURVE_DEGREE].m_X - 0.01)
878
xp += (m_control_knot[i + CURVE_DEGREE].m_X - 0.01) - m_control_knot[i].m_X;
879
m_control_knot[i].m_X = m_control_knot[i + CURVE_DEGREE].m_X - 0.01;
883
// move the right tangent points
885
m_control_knot[i+1].m_X += xp;
886
m_control_knot[i+1].m_Y -= yp;
888
if (m_control_knot[i+1].m_X < m_control_knot[i].m_X)
890
m_control_knot[i+1].m_X = m_control_knot[i].m_X;
894
else if (i == nbKnot - 1)
898
if (m_control_knot[i].m_X + xp < m_control_knot[i - CURVE_DEGREE].m_X + 0.01)
900
xp = - (m_control_knot[i].m_X - (m_control_knot[i - CURVE_DEGREE].m_X + 0.01) );
901
m_control_knot[i].m_X = m_control_knot[i - CURVE_DEGREE].m_X + 0.01;
905
m_control_knot[i].m_X += xp;
911
m_control_knot[i].m_X = m_minX;
912
else if (x_border == +1)
913
m_control_knot[i].m_X = m_maxX;
915
if (m_control_knot[i].m_X < m_control_knot[i - CURVE_DEGREE].m_X + 0.01)
917
xp += (m_control_knot[i - CURVE_DEGREE].m_X + 0.01) - m_control_knot[i].m_X;
918
m_control_knot[i].m_X = m_control_knot[i - CURVE_DEGREE].m_X + 0.01;
922
// move the left tangent points
924
m_control_knot[i-1].m_X += xp;
925
m_control_knot[i-1].m_Y -= yp;
927
if (m_control_knot[i-1].m_X > m_control_knot[i].m_X)
929
m_control_knot[i-1].m_X = m_control_knot[i].m_X;
935
if (m_control_knot[i].m_X + xp > m_control_knot[i + CURVE_DEGREE].m_X - 0.01)
937
xp = (m_control_knot[i + CURVE_DEGREE].m_X - 0.01) - m_control_knot[i].m_X;
938
m_control_knot[i].m_X = m_control_knot[i + CURVE_DEGREE].m_X - 0.01;
940
else if (m_control_knot[i].m_X + xp < m_control_knot[i - CURVE_DEGREE].m_X + 0.01)
942
xp = m_control_knot[i].m_X - (m_control_knot[i - CURVE_DEGREE].m_X + 0.01);
943
m_control_knot[i].m_X = m_control_knot[i - CURVE_DEGREE].m_X + 0.01;
947
m_control_knot[i].m_X += xp;
950
// move the left and right tangent points
952
m_control_knot[i-1].m_X += xp;
953
m_control_knot[i+1].m_X += xp;
954
m_control_knot[i-1].m_Y -= yp;
955
m_control_knot[i+1].m_Y -= yp;
957
if (m_control_knot[i-1].m_X > m_control_knot[i].m_X)
959
m_control_knot[i-1].m_X = m_control_knot[i].m_X;
962
if (m_control_knot[i+1].m_X < m_control_knot[i].m_X)
964
m_control_knot[i+1].m_X = m_control_knot[i].m_X;
971
m_control_knot[i].m_X += xp;
972
m_control_knot[i].m_Y -= yp;
974
t_s32 index = (t_s32) ClosestCubicBezierEndPoint (i);
978
if (m_control_knot[i].m_X > m_control_knot[index].m_X)
980
m_control_knot[i].m_X = m_control_knot[index].m_X;
985
if (m_control_knot[i].m_X < m_control_knot[index].m_X)
987
m_control_knot[i].m_X = m_control_knot[index].m_X;
999
void BezierCurveControl2::ProcessPanning (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
1002
int W = GetBaseWidth() - 2 * GRAPH_MARGIN;
1003
int H = GetBaseHeight() - 2 * GRAPH_MARGIN;
1005
xp = /*m_minX +*/ dx * (m_maxX - m_minX) / W;
1006
yp = /*m_minY +*/ dy * (m_maxY - m_minY) / H;
1008
if (m_bControlPointSelected == false)
1010
if (m_bPanningEnabled)
1023
void BezierCurveControl2::ProcessZooming (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
1026
int W = GetBaseWidth() - 2 * GRAPH_MARGIN;
1027
int H = GetBaseHeight() - 2 * GRAPH_MARGIN;
1029
xp = /*m_minX +*/ dx * (m_maxX - m_minX) / W;
1030
yp = /*m_minY +*/ dy * (m_maxY - m_minY) / H;
1032
if ( (m_minX + yp >= m_maxX - yp) || (m_minY + yp >= m_maxY - yp) )
1037
if (m_bControlPointSelected == false)
1039
if (m_bZoomingEnabled)