~ubuntu-branches/ubuntu/oneiric/nux/oneiric

« back to all changes in this revision

Viewing changes to Nux/BezierCurveControl2.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2010-12-09 19:56:53 UTC
  • mto: This revision was merged to the branch mainline in revision 6.
  • Revision ID: james.westby@ubuntu.com-20101209195653-lsc4objqdxs9exp3
Tags: upstream-0.9.10
ImportĀ upstreamĀ versionĀ 0.9.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright 2010 Inalogic Inc.
3
 
 *
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.
7
 
 *
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.
13
 
 *
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/>
17
 
 *
18
 
 * Authored by: Jay Taoko <jay.taoko_AT_gmail_DOT_com>
19
 
 *
20
 
 */
21
 
 
22
 
 
23
 
#include "Nux.h"
24
 
 
25
 
#include "BezierCurveControl2.h"
26
 
#include "NuxCore/Math/Bezier.h"
27
 
 
28
 
namespace nux
29
 
{
30
 
 
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;
36
 
 
37
 
  unsigned long S_KEY = 0;
38
 
 
39
 
  BezierCurveControl2::BezierCurveControl2 (NUX_FILE_LINE_DECL)
40
 
    :   View (NUX_FILE_LINE_PARAM)
41
 
    ,   m_minX (-0.10f),
42
 
    m_minY (-0.100f),
43
 
    m_maxX (1.100f),
44
 
    m_maxY (1.100f),
45
 
    m_FunctionCallback (0),
46
 
    m_bControlPointSelected (0),
47
 
    m_bPanningEnabled (true),
48
 
    m_bZoomingEnabled (true)
49
 
  {
50
 
    SetMinimumSize (180, 180);
51
 
 
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) );
56
 
 
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) );
60
 
 
61
 
    OnKeyEvent.connect (sigc::mem_fun (this, &BezierCurveControl2::RecvKeyEvent) );
62
 
 
63
 
    NTextureData image;
64
 
    MakeCheckBoardImage (image.GetSurface (0), 64, 64, Color (0xff323232), Color (0xff535353), 8, 8);
65
 
    BaseTexture* m_CheckboardPattern = GetThreadGLDeviceFactory()->CreateSystemCapableTexture ();
66
 
    m_CheckboardPattern->Update (&image);
67
 
 
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);
72
 
 
73
 
    m_CheckboardPattern->UnReference ();
74
 
  }
75
 
 
76
 
  BezierCurveControl2::~BezierCurveControl2()
77
 
  {
78
 
    NUX_SAFE_DELETE (m_Background);
79
 
  }
80
 
 
81
 
 
82
 
  long BezierCurveControl2::ProcessEvent (IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
83
 
  {
84
 
    long ret = TraverseInfo;
85
 
 
86
 
    if (ievent.e_event == NUX_MOUSE_PRESSED)
87
 
    {
88
 
      if (!m_Geometry.IsPointInside (ievent.e_x, ievent.e_y) )
89
 
      {
90
 
        //ProcEvInfo = eDoNotProcess;
91
 
        //return TraverseInfo;
92
 
      }
93
 
    }
94
 
 
95
 
    S_KEY = ievent.GetVirtualKeyState (NUX_VK_S);
96
 
    ret = PostProcessEvent2 (ievent, ret, ProcessEventInfo);
97
 
    return ret;
98
 
  }
99
 
 
100
 
 
101
 
  void BezierCurveControl2::Draw (GraphicsEngine &GfxContext, bool force_draw)
102
 
  {
103
 
    Geometry base = GetGeometry();
104
 
 
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);
109
 
 
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;
114
 
 
115
 
    t_u32 i;
116
 
    int nsample = base.GetWidth();
117
 
    double t;
118
 
    t_u32 nbKnot = (t_u32) m_control_knot.size();
119
 
 
120
 
    GfxContext.PushClippingRectangle (base);
121
 
 
122
 
    GetPainter().PushDrawLayer (GfxContext, base, m_Background);
123
 
    GetPainter().PopBackground();
124
 
 
125
 
    //DrawGrid(GfxContext);
126
 
    DrawCoordinateSystem (GfxContext);
127
 
 
128
 
    if (nbKnot > 0)
129
 
    {
130
 
      double *xcon = new double[nbKnot];
131
 
      double xval;
132
 
      double *ycon = new double[nbKnot];
133
 
      double yval;
134
 
 
135
 
 
136
 
      for (i = 0; i < nbKnot; i++)
137
 
      {
138
 
        xcon[i] = m_control_knot[i].m_X;
139
 
        ycon[i] = m_control_knot[i].m_Y;
140
 
      }
141
 
 
142
 
      double xprev, yprev;
143
 
      Bezier_XY (CURVE_DEGREE, 0.0, xcon, ycon, &xprev, &yprev);
144
 
 
145
 
      int X0, Y0, X1, Y1, X2, Y2;
146
 
 
147
 
      glEnable (GL_POINT_SMOOTH);
148
 
      glEnable (GL_LINE_SMOOTH);
149
 
      glLineWidth (1);
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);
153
 
 
154
 
      for (i = 1; i < (t_u32) nsample; i++ )
155
 
      {
156
 
        t = ( double ) ( i ) / ( double ) ( nsample - 1 );
157
 
        Bezier_XY ( CURVE_DEGREE, t, xcon, ycon, &xval, &yval );
158
 
 
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) );
163
 
 
164
 
        GetPainter().Draw2DLine (GfxContext, X0, Y0, X1, Y1, Color (0xFFFFFFFF) );
165
 
 
166
 
        xprev = xval;
167
 
        yprev = yval;
168
 
      }
169
 
 
170
 
      if (m_control_knot[0].m_X > m_minX)
171
 
      {
172
 
        // draw line from the left border to the left most control point.
173
 
 
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) );
176
 
 
177
 
        GetPainter().Draw2DLine (GfxContext, base.x, Y0, X0, Y0, Color (0xFFFFFFFF) );
178
 
      }
179
 
 
180
 
      if (m_control_knot[nbKnot-1].m_X < m_maxX)
181
 
      {
182
 
        // draw line from the right most control point to the left border.
183
 
 
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) );
186
 
 
187
 
        GetPainter().Draw2DLine (GfxContext, X0, Y0, base.x + base.GetWidth(), Y0, Color (0xFFFFFFFF) );
188
 
      }
189
 
 
190
 
      glDisable (GL_POINT_SMOOTH);
191
 
      glDisable (GL_LINE_SMOOTH);
192
 
      GfxContext.GetRenderStates().SetBlend (FALSE);
193
 
 
194
 
      for (i = 0; i <= nbKnot - 1; i += CURVE_DEGREE)
195
 
      {
196
 
        // Only the endpoint of cubic bezier.
197
 
 
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) );
200
 
 
201
 
        if (i < nbKnot - 1)
202
 
        {
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) );
205
 
 
206
 
          GetPainter().Draw2DLine (GfxContext, X0, Y0, X1, Y1, Color (0xFF0000FF) );
207
 
        }
208
 
 
209
 
        if ( i > 0)
210
 
        {
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) );
213
 
 
214
 
          GetPainter().Draw2DLine (GfxContext, X0, Y0, X2, Y2, Color (0xFF0000FF) );
215
 
        }
216
 
      }
217
 
 
218
 
      Geometry ShapeGeo = GetTheme().GetImageGeometry (eDOT6x6);
219
 
 
220
 
      for (i = 0; i < nbKnot; i++)
221
 
      {
222
 
        int X0, Y0;
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) );
225
 
 
226
 
        if (m_control_knot[i].m_IsSelected)
227
 
        {
228
 
          GetPainter().PaintShape (GfxContext,
229
 
                               Geometry (X0 - ShapeGeo.GetWidth() / 2, Y0 - ShapeGeo.GetHeight() / 2, ShapeGeo.GetWidth(), ShapeGeo.GetHeight() ),
230
 
                               Color (0xFF44FF44), eDOT6x6);
231
 
        }
232
 
        else
233
 
        {
234
 
          GetPainter().PaintShape (GfxContext,
235
 
                               Geometry (X0 - ShapeGeo.GetWidth() / 2, Y0 - ShapeGeo.GetHeight() / 2, ShapeGeo.GetWidth(), ShapeGeo.GetHeight() ),
236
 
                               Color (0xFFFFFFFF), eDOT6x6);
237
 
        }
238
 
      }
239
 
 
240
 
      delete xcon;
241
 
      delete ycon;
242
 
    }
243
 
 
244
 
    GetPainter().Paint2DQuadWireframe (GfxContext, base, Color (0xFF000000) );
245
 
 
246
 
    DrawRuler (GfxContext);
247
 
    GfxContext.PopClippingRectangle();
248
 
  }
249
 
 
250
 
  void BezierCurveControl2::DrawRuler (GraphicsEngine &GfxContext)
251
 
  {
252
 
    Geometry base = GetGeometry();
253
 
 
254
 
    base.OffsetPosition (GRAPH_MARGIN, GRAPH_MARGIN);
255
 
    base.OffsetSize (-2 * GRAPH_MARGIN, -2 * GRAPH_MARGIN);
256
 
 
257
 
    // Draw Horizontal ruler
258
 
 
259
 
    static float Funit = 1.0;
260
 
    float rangex = m_maxX - m_minX;
261
 
    int Iunit = Funit * base.GetWidth() / rangex;
262
 
 
263
 
    if (Iunit > 2 * UNIT_REFERENCE)
264
 
    {
265
 
      Funit = rangex * UNIT_REFERENCE / base.GetWidth();
266
 
    }
267
 
    else if (Iunit < UNIT_REFERENCE)
268
 
    {
269
 
      Funit = rangex * 2 * UNIT_REFERENCE / base.GetWidth();
270
 
    }
271
 
 
272
 
    if ( (m_minX < 0) && (m_maxX > 0) )
273
 
    {
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;
276
 
      int count = 0;
277
 
 
278
 
      while (start_x > base.x)
279
 
      {
280
 
        GetPainter().Draw2DLine (GfxContext, start_x, base.y + base.GetHeight(), start_x, base.y + base.GetHeight() - 5, Color (0xFF000000) );
281
 
        count++;
282
 
        start_x -= Funit * base.GetWidth() / rangex;
283
 
      }
284
 
 
285
 
      start_x = base.x + center + Funit * base.GetWidth() / rangex;
286
 
      count = 0;
287
 
 
288
 
      while (start_x < base.x + base.GetWidth() )
289
 
      {
290
 
        GetPainter().Draw2DLine (GfxContext, start_x, base.y + base.GetHeight(), start_x, base.y + base.GetHeight() - 5, Color (0xFF000000) );
291
 
        count++;
292
 
        start_x += Funit * base.GetWidth() / rangex;
293
 
      }
294
 
    }
295
 
 
296
 
    if (0 <= m_minX)
297
 
    {
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;
300
 
      int count = 0;
301
 
 
302
 
      while (start_x < base.x + base.GetWidth() )
303
 
      {
304
 
        GetPainter().Draw2DLine (GfxContext, start_x, base.y + base.GetHeight(), start_x, base.y + base.GetHeight() - 5, Color (0xFF000000) );
305
 
        count++;
306
 
        start_x += Funit * base.GetWidth() / rangex;
307
 
      }
308
 
    }
309
 
 
310
 
    if (m_maxX <= 0)
311
 
    {
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;
314
 
      int count = 0;
315
 
 
316
 
      while (start_x > base.x)
317
 
      {
318
 
        GetPainter().Draw2DLine (GfxContext, start_x, base.y + base.GetHeight(), start_x, base.y + base.GetHeight() - 5, Color (0xFF000000) );
319
 
        count++;
320
 
        start_x -= Funit * base.GetWidth() / rangex;
321
 
      }
322
 
    }
323
 
 
324
 
    // Draw Vertical ruler
325
 
 
326
 
    static float FunitY = 1.0;
327
 
    float rangey = m_maxY - m_minY;
328
 
    int IunitY = FunitY * base.GetHeight() / rangey;
329
 
 
330
 
    if (IunitY > 2 * UNIT_REFERENCE)
331
 
    {
332
 
      FunitY = rangey * UNIT_REFERENCE / base.GetHeight();
333
 
    }
334
 
    else if (IunitY < UNIT_REFERENCE)
335
 
    {
336
 
      FunitY = rangey * 2 * UNIT_REFERENCE / base.GetHeight();
337
 
    }
338
 
 
339
 
    if ( (m_minY < 0) && (m_maxY > 0) )
340
 
    {
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;
343
 
      int count = 0;
344
 
 
345
 
      while (start_y > base.y)
346
 
      {
347
 
        GetPainter().Draw2DLine (GfxContext, base.x, start_y , base.x + 5, start_y, Color (0xFF000000) );
348
 
        count++;
349
 
        start_y -= FunitY * base.GetHeight() / rangey;
350
 
      }
351
 
 
352
 
      start_y = base.y + base.GetHeight() - center + FunitY * base.GetHeight() / rangey;
353
 
      count = 0;
354
 
 
355
 
      while (start_y < base.y + base.GetHeight() )
356
 
      {
357
 
        GetPainter().Draw2DLine (GfxContext, base.x, start_y , base.x + 5, start_y, Color (0xFF000000) );
358
 
        count++;
359
 
        start_y += FunitY * base.GetHeight() / rangey;
360
 
      }
361
 
    }
362
 
 
363
 
    if (0 <= m_minY)
364
 
    {
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;
367
 
      int count = 0;
368
 
 
369
 
      while (start_y > base.y)
370
 
      {
371
 
        GetPainter().Draw2DLine (GfxContext, base.x, start_y , base.x + 5, start_y, Color (0xFF000000) );
372
 
        count++;
373
 
        start_y -= FunitY * base.GetHeight() / rangey;
374
 
      }
375
 
    }
376
 
 
377
 
    if (m_maxY <= 0)
378
 
    {
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;
381
 
      int count = 0;
382
 
 
383
 
      while (start_y < base.y + base.GetHeight() )
384
 
      {
385
 
        GetPainter().Draw2DLine (GfxContext, base.x, start_y , base.x + 5, start_y, Color (0xFF000000) );
386
 
        count++;
387
 
        start_y += FunitY * base.GetHeight() / rangey;
388
 
      }
389
 
    }
390
 
  }
391
 
 
392
 
  void BezierCurveControl2::DrawGrid (GraphicsEngine &GfxContext)
393
 
  {
394
 
    Geometry base = GetGeometry();
395
 
 
396
 
    base.OffsetPosition (GRAPH_MARGIN, GRAPH_MARGIN);
397
 
    base.OffsetSize (-2 * GRAPH_MARGIN, -2 * GRAPH_MARGIN);
398
 
 
399
 
    // Draw Vertical Grid
400
 
 
401
 
    static float Funit = 1.0;
402
 
    float rangex = m_maxX - m_minX;
403
 
    int Iunit = Funit * base.GetWidth() / rangex;
404
 
 
405
 
    if (Iunit > 2 * UNIT_REFERENCE)
406
 
    {
407
 
      Funit = rangex * UNIT_REFERENCE / base.GetWidth();
408
 
    }
409
 
    else if (Iunit < UNIT_REFERENCE)
410
 
    {
411
 
      Funit = rangex * 2 * UNIT_REFERENCE / base.GetWidth();
412
 
    }
413
 
 
414
 
    if ( (m_minX < 0) && (m_maxX > 0) )
415
 
    {
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;
418
 
      int count = 0;
419
 
 
420
 
      while (start_x > base.x)
421
 
      {
422
 
        // vertical grid
423
 
        GetPainter().Draw2DLine (GfxContext, start_x, base.y,
424
 
                             start_x, base.y + base.GetHeight(), Color (0xFF5F5F5F) );
425
 
 
426
 
        count++;
427
 
        start_x -= Funit * base.GetWidth() / rangex;
428
 
      }
429
 
 
430
 
      start_x = base.x + center + Funit * base.GetWidth() / rangex;
431
 
      count = 0;
432
 
 
433
 
      while (start_x < base.x + base.GetWidth() )
434
 
      {
435
 
        // vertical grid
436
 
        GetPainter().Draw2DLine (GfxContext, start_x, base.y,
437
 
                             start_x, base.y + base.GetHeight(), Color (0xFF5F5F5F) );
438
 
 
439
 
        count++;
440
 
        start_x += Funit * base.GetWidth() / rangex;
441
 
      }
442
 
    }
443
 
 
444
 
    if (0 <= m_minX)
445
 
    {
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;
448
 
      int count = 0;
449
 
 
450
 
      while (start_x < base.x + base.GetWidth() )
451
 
      {
452
 
        // vertical grid
453
 
        GetPainter().Draw2DLine (GfxContext, start_x, base.y,
454
 
                             start_x, base.y + base.GetHeight(), Color (0xFF5F5F5F) );
455
 
 
456
 
        count++;
457
 
        start_x += Funit * base.GetWidth() / rangex;
458
 
      }
459
 
    }
460
 
 
461
 
    if (m_maxX <= 0)
462
 
    {
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;
465
 
      int count = 0;
466
 
 
467
 
      while (start_x > base.x)
468
 
      {
469
 
        // vertical grid
470
 
        GetPainter().Draw2DLine (GfxContext, start_x, base.y,
471
 
                             start_x, base.y + base.GetHeight(), Color (0xFF5F5F5F) );
472
 
 
473
 
        count++;
474
 
        start_x -= Funit * base.GetWidth() / rangex;
475
 
      }
476
 
    }
477
 
 
478
 
    // Draw Horizontal Grid
479
 
 
480
 
    static float FunitY = 1.0;
481
 
    float rangey = m_maxY - m_minY;
482
 
    int IunitY = FunitY * base.GetHeight() / rangey;
483
 
 
484
 
    if (IunitY > 2 * UNIT_REFERENCE)
485
 
    {
486
 
      FunitY = rangey * UNIT_REFERENCE / base.GetHeight();
487
 
    }
488
 
    else if (IunitY < UNIT_REFERENCE)
489
 
    {
490
 
      FunitY = rangey * 2 * UNIT_REFERENCE / base.GetHeight();
491
 
    }
492
 
 
493
 
    if ( (m_minY < 0) && (m_maxY > 0) )
494
 
    {
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;
497
 
      int count = 0;
498
 
 
499
 
      while (start_y > base.y)
500
 
      {
501
 
        // horizontal grid
502
 
        GetPainter().Draw2DLine (GfxContext, base.x, start_y,
503
 
                             base.x + base.GetWidth(), start_y, Color (0xFF5F5F5F) );
504
 
 
505
 
        count++;
506
 
        start_y -= FunitY * base.GetHeight() / rangey;
507
 
      }
508
 
 
509
 
      start_y = base.y + base.GetHeight() - center + FunitY * base.GetHeight() / rangey;
510
 
      count = 0;
511
 
 
512
 
      while (start_y < base.y + base.GetHeight() )
513
 
      {
514
 
        GetPainter().Draw2DLine (GfxContext, base.x, start_y,
515
 
                             base.x + base.GetWidth(), start_y, Color (0xFF5F5F5F) );
516
 
 
517
 
        count++;
518
 
        start_y += FunitY * base.GetHeight() / rangey;
519
 
      }
520
 
    }
521
 
 
522
 
    if (0 <= m_minY)
523
 
    {
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;
526
 
      int count = 0;
527
 
 
528
 
      while (start_y > base.y)
529
 
      {
530
 
        GetPainter().Draw2DLine (GfxContext, base.x, start_y,
531
 
                             base.x + base.GetWidth(), start_y, Color (0xFF5F5F5F) );
532
 
 
533
 
        count++;
534
 
        start_y -= FunitY * base.GetHeight() / rangey;
535
 
      }
536
 
    }
537
 
 
538
 
    if (m_maxY <= 0)
539
 
    {
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;
542
 
      int count = 0;
543
 
 
544
 
      while (start_y < base.y + base.GetHeight() )
545
 
      {
546
 
        GetPainter().Draw2DLine (GfxContext, base.x, start_y,
547
 
                             base.x + base.GetWidth(), start_y, Color (0xFF5F5F5F) );
548
 
 
549
 
        count++;
550
 
        start_y += FunitY * base.GetHeight() / rangey;
551
 
      }
552
 
    }
553
 
  }
554
 
 
555
 
  void BezierCurveControl2::DrawCoordinateSystem (GraphicsEngine &GfxContext)
556
 
  {
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;
561
 
 
562
 
    int X0, Y0;
563
 
    X0 = X + W * (0 - m_minX) / (m_maxX - m_minX);
564
 
    Y0 = Y + H * ( 1 - (0 - m_minY) / (m_maxY - m_minY) );
565
 
 
566
 
    GetPainter().Draw2DLine (GfxContext, X0, Y, X0, Y + H, Color (0xFF222222) );
567
 
    GetPainter().Draw2DLine (GfxContext, X, Y0, X + W, Y0, Color (0xFF000000) );
568
 
  }
569
 
 
570
 
  void BezierCurveControl2::DrawContent (GraphicsEngine &GfxContext, bool force_draw)
571
 
  {
572
 
 
573
 
  }
574
 
 
575
 
  void BezierCurveControl2::PostDraw (GraphicsEngine &GfxContext, bool force_draw)
576
 
  {
577
 
 
578
 
  }
579
 
 
580
 
 
581
 
  void BezierCurveControl2::SetXAxisBounds (float minX, float maxX)
582
 
  {
583
 
    m_minX = minX;
584
 
    m_maxX = maxX;
585
 
    NeedRedraw();
586
 
  }
587
 
 
588
 
  void BezierCurveControl2::SetYAxisBounds (float minY, float maxY)
589
 
  {
590
 
    m_minY = minY;
591
 
    m_maxY = maxY;
592
 
    NeedRedraw();
593
 
  }
594
 
 
595
 
  void BezierCurveControl2::SetFunctionCallback (FunctionCallback f)
596
 
  {
597
 
    m_FunctionCallback = f;
598
 
    NeedRedraw();
599
 
  }
600
 
 
601
 
  float BezierCurveControl2::EvalFunction (float x)
602
 
  {
603
 
    if (m_FunctionCallback != 0)
604
 
      return (*m_FunctionCallback) (x);
605
 
 
606
 
    return 0;
607
 
  }
608
 
 
609
 
  void BezierCurveControl2::UpdateGraph()
610
 
  {
611
 
    NeedRedraw();
612
 
  }
613
 
 
614
 
 
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) )
618
 
#endif
619
 
 
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) )
623
 
#endif
624
 
 
625
 
  void BezierCurveControl2::RecvMouseUp (int x, int y, unsigned long button_flags, unsigned long key_flags)
626
 
  {
627
 
    NeedRedraw();
628
 
  }
629
 
 
630
 
  void BezierCurveControl2::RecvMouseDown (int x, int y, unsigned long button_flags, unsigned long key_flags)
631
 
  {
632
 
    if (! (button_flags & NUX_EVENT_BUTTON1) )
633
 
    {
634
 
      return;
635
 
    }
636
 
 
637
 
    m_bControlPointSelected = false;
638
 
    t_u32 nbKnot = (t_u32) m_control_knot.size();
639
 
 
640
 
    for (t_u32 i = 0; i < nbKnot; i++)
641
 
    {
642
 
      m_control_knot[i].m_IsSelected = false;
643
 
    }
644
 
 
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;
649
 
 
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);
651
 
 
652
 
    if (b == false)
653
 
      return;
654
 
 
655
 
//    X = GetX();
656
 
//    Y = GetY();
657
 
    for (t_u32 i = 0; i < nbKnot; i++)
658
 
    {
659
 
      int Xp, Yp;
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) );
662
 
 
663
 
      int tx, ty;
664
 
      tx = X + x - GRAPH_MARGIN;
665
 
      ty = Y + y - GRAPH_MARGIN;
666
 
 
667
 
      if (PT_INSIDE_BOX (tx, ty, Xp - KNOT_HIT_TEST, Xp + KNOT_HIT_TEST, Yp - KNOT_HIT_TEST, Yp + KNOT_HIT_TEST) )
668
 
      {
669
 
        m_control_knot[i].m_IsSelected = true;
670
 
        hit_point_dx = (tx) - Xp;
671
 
        hit_point_dy = Yp - (ty);
672
 
 
673
 
        m_bControlPointSelected = true;
674
 
 
675
 
        if ( (i % CURVE_DEGREE) == 0)
676
 
        {
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.
679
 
        }
680
 
 
681
 
        break;
682
 
      }
683
 
    }
684
 
 
685
 
    NeedRedraw();
686
 
  }
687
 
 
688
 
  int ClosestCubicBezierEndPoint (int i)
689
 
  {
690
 
    if ( (i % CURVE_DEGREE) == 0)
691
 
    {
692
 
      return i;
693
 
    }
694
 
 
695
 
    if ( ( (i + 1) % CURVE_DEGREE) == 0)
696
 
    {
697
 
      return i + 1;
698
 
    }
699
 
 
700
 
    if ( ( (i - 1) % CURVE_DEGREE) == 0)
701
 
    {
702
 
      return i - 1;
703
 
    }
704
 
 
705
 
    return 0;
706
 
  }
707
 
 
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*/
715
 
  )
716
 
  {
717
 
 
718
 
  }
719
 
 
720
 
  void BezierCurveControl2::RecvMouseDrag (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
721
 
  {
722
 
    if ( (m_bControlPointSelected == false) && (button_flags & NUX_STATE_BUTTON1_DOWN) && S_KEY)
723
 
    {
724
 
      if (m_bPanningEnabled)
725
 
      {
726
 
        ProcessPanning (x, y, dx, dy, button_flags, key_flags);
727
 
        return;
728
 
      }
729
 
    }
730
 
 
731
 
    if ( (m_bControlPointSelected == false) && (button_flags & NUX_STATE_BUTTON3_DOWN) && S_KEY)
732
 
    {
733
 
      if (m_bZoomingEnabled)
734
 
      {
735
 
        ProcessZooming (x, y, dx, dy, button_flags, key_flags);
736
 
        return;
737
 
      }
738
 
    }
739
 
 
740
 
    if (button_flags & NUX_STATE_BUTTON1_DOWN)
741
 
      ManipulateBezier (x, y, dx, dy, button_flags, key_flags);
742
 
  }
743
 
 
744
 
  void BezierCurveControl2::ManipulateBezier (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
745
 
  {
746
 
    float xp, yp;
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;
751
 
 
752
 
    t_s32 nbKnot = (t_s32) m_control_knot.size();
753
 
 
754
 
    xp = /*m_minX +*/ dx * (m_maxX - m_minX) / W;
755
 
    yp = /*m_minY +*/ dy * (m_maxY - m_minY) / H;
756
 
 
757
 
    nuxAssert (nbKnot >= CURVE_DEGREE);
758
 
    int x_border = 0;
759
 
    int y_border = 0;
760
 
 
761
 
    for (t_s32 i = 0; i < nbKnot; i++)
762
 
    {
763
 
      if (m_control_knot[i].m_IsSelected)
764
 
      {
765
 
        int tempx, tempy;
766
 
        tempx = X + x - GRAPH_MARGIN;
767
 
        tempy = Y + y - GRAPH_MARGIN;
768
 
 
769
 
        int Xp, Yp;
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) );
772
 
 
773
 
        if (dx > 0)
774
 
        {
775
 
          if (tempx > Xp + hit_point_dx)
776
 
          {
777
 
            xp = /*m_minX +*/ (m_maxX - m_minX) * (tempx - Xp - hit_point_dx) / W;
778
 
          }
779
 
          else
780
 
          {
781
 
            xp = 0;
782
 
          }
783
 
        }
784
 
        else if (dx < 0)
785
 
        {
786
 
          if (tempx < Xp + hit_point_dx)
787
 
          {
788
 
            xp = /*m_minX +*/ (m_maxX - m_minX) * (tempx - Xp - hit_point_dx) / W;
789
 
          }
790
 
          else
791
 
          {
792
 
            xp = 0;
793
 
          }
794
 
        }
795
 
 
796
 
        if (dy > 0)
797
 
        {
798
 
          if (tempy > Yp - hit_point_dy)
799
 
          {
800
 
            yp = /*m_minY +*/ (m_maxY - m_minY) * (tempy - Yp + hit_point_dy) / H;
801
 
          }
802
 
          else
803
 
          {
804
 
            yp = 0;
805
 
          }
806
 
        }
807
 
        else if (dy < 0)
808
 
        {
809
 
          if (tempy < Yp - hit_point_dy)
810
 
          {
811
 
            yp = /*m_minY +*/ (m_maxY - m_minY) * (tempy - Yp + hit_point_dy) / H;
812
 
          }
813
 
          else
814
 
          {
815
 
            yp = 0;
816
 
          }
817
 
        }
818
 
 
819
 
        if (m_bPanningEnabled == false)
820
 
        {
821
 
          if (m_control_knot[i].m_X + xp < m_minX)
822
 
          {
823
 
            xp = m_minX - m_control_knot[i].m_X;
824
 
            x_border = -1;
825
 
          }
826
 
          else if (m_control_knot[i].m_X + xp > m_maxX)
827
 
          {
828
 
            xp = m_maxX - m_control_knot[i].m_X;
829
 
            x_border = +1;
830
 
          }
831
 
 
832
 
          if (m_control_knot[i].m_Y - yp < m_minY)
833
 
          {
834
 
            yp = m_control_knot[i].m_Y - m_minY;
835
 
            y_border = -1;
836
 
          }
837
 
          else if (m_control_knot[i].m_Y - yp > m_maxY)
838
 
          {
839
 
            yp = m_control_knot[i].m_Y - m_maxY;
840
 
            y_border = +1;
841
 
          }
842
 
        }
843
 
 
844
 
 
845
 
        if ( (i % CURVE_DEGREE) == 0)
846
 
        {
847
 
          if (y_border == 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;
853
 
 
854
 
          // Only endpoint of cubic bezier curves.
855
 
          if (i == 0)
856
 
          {
857
 
            if (x_border == 0)
858
 
            {
859
 
              if ( m_control_knot[i].m_X + xp > m_control_knot[i + CURVE_DEGREE].m_X - 0.01)
860
 
              {
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;
863
 
              }
864
 
              else
865
 
              {
866
 
                m_control_knot[i].m_X += xp;
867
 
              }
868
 
            }
869
 
            else
870
 
            {
871
 
              if (x_border == -1)
872
 
                m_control_knot[i].m_X = m_minX;
873
 
              else if (x_border == +1)
874
 
                m_control_knot[i].m_X = m_maxX;
875
 
 
876
 
              if ( m_control_knot[i].m_X > m_control_knot[i + CURVE_DEGREE].m_X - 0.01)
877
 
              {
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;
880
 
              }
881
 
            }
882
 
 
883
 
            // move the right tangent points
884
 
            {
885
 
              m_control_knot[i+1].m_X += xp;
886
 
              m_control_knot[i+1].m_Y -= yp;
887
 
 
888
 
              if (m_control_knot[i+1].m_X < m_control_knot[i].m_X)
889
 
              {
890
 
                m_control_knot[i+1].m_X = m_control_knot[i].m_X;
891
 
              }
892
 
            }
893
 
          }
894
 
          else if (i == nbKnot - 1)
895
 
          {
896
 
            if (x_border == 0)
897
 
            {
898
 
              if (m_control_knot[i].m_X + xp < m_control_knot[i - CURVE_DEGREE].m_X + 0.01)
899
 
              {
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;
902
 
              }
903
 
              else
904
 
              {
905
 
                m_control_knot[i].m_X += xp;
906
 
              }
907
 
            }
908
 
            else
909
 
            {
910
 
              if (x_border == -1)
911
 
                m_control_knot[i].m_X = m_minX;
912
 
              else if (x_border == +1)
913
 
                m_control_knot[i].m_X = m_maxX;
914
 
 
915
 
              if (m_control_knot[i].m_X < m_control_knot[i - CURVE_DEGREE].m_X + 0.01)
916
 
              {
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;
919
 
              }
920
 
            }
921
 
 
922
 
            // move the left tangent points
923
 
            {
924
 
              m_control_knot[i-1].m_X += xp;
925
 
              m_control_knot[i-1].m_Y -= yp;
926
 
 
927
 
              if (m_control_knot[i-1].m_X > m_control_knot[i].m_X)
928
 
              {
929
 
                m_control_knot[i-1].m_X = m_control_knot[i].m_X;
930
 
              }
931
 
            }
932
 
          }
933
 
          else
934
 
          {
935
 
            if (m_control_knot[i].m_X + xp > m_control_knot[i + CURVE_DEGREE].m_X - 0.01)
936
 
            {
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;
939
 
            }
940
 
            else if (m_control_knot[i].m_X + xp < m_control_knot[i - CURVE_DEGREE].m_X + 0.01)
941
 
            {
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;
944
 
            }
945
 
            else
946
 
            {
947
 
              m_control_knot[i].m_X += xp;
948
 
            }
949
 
 
950
 
            // move the left and right tangent points
951
 
            {
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;
956
 
 
957
 
              if (m_control_knot[i-1].m_X > m_control_knot[i].m_X)
958
 
              {
959
 
                m_control_knot[i-1].m_X = m_control_knot[i].m_X;
960
 
              }
961
 
 
962
 
              if (m_control_knot[i+1].m_X < m_control_knot[i].m_X)
963
 
              {
964
 
                m_control_knot[i+1].m_X = m_control_knot[i].m_X;
965
 
              }
966
 
            }
967
 
          }
968
 
        }
969
 
        else
970
 
        {
971
 
          m_control_knot[i].m_X += xp;
972
 
          m_control_knot[i].m_Y -= yp;
973
 
 
974
 
          t_s32 index = (t_s32) ClosestCubicBezierEndPoint (i);
975
 
 
976
 
          if (index > i)
977
 
          {
978
 
            if (m_control_knot[i].m_X > m_control_knot[index].m_X)
979
 
            {
980
 
              m_control_knot[i].m_X = m_control_knot[index].m_X;
981
 
            }
982
 
          }
983
 
          else if ( index < i)
984
 
          {
985
 
            if (m_control_knot[i].m_X < m_control_knot[index].m_X)
986
 
            {
987
 
              m_control_knot[i].m_X = m_control_knot[index].m_X;
988
 
            }
989
 
          }
990
 
        }
991
 
 
992
 
        break;
993
 
      }
994
 
    }
995
 
 
996
 
    NeedRedraw();
997
 
  }
998
 
 
999
 
  void BezierCurveControl2::ProcessPanning (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
1000
 
  {
1001
 
    float xp, yp;
1002
 
    int W = GetBaseWidth() - 2 * GRAPH_MARGIN;
1003
 
    int H = GetBaseHeight() - 2 * GRAPH_MARGIN;
1004
 
 
1005
 
    xp = /*m_minX +*/ dx * (m_maxX - m_minX) / W;
1006
 
    yp = /*m_minY +*/ dy * (m_maxY - m_minY) / H;
1007
 
 
1008
 
    if (m_bControlPointSelected == false)
1009
 
    {
1010
 
      if (m_bPanningEnabled)
1011
 
      {
1012
 
        m_minX -= xp;
1013
 
        m_maxX -= xp;
1014
 
        m_minY += yp;
1015
 
        m_maxY += yp;
1016
 
 
1017
 
        NeedRedraw();
1018
 
        return;
1019
 
      }
1020
 
    }
1021
 
  }
1022
 
 
1023
 
  void BezierCurveControl2::ProcessZooming (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
1024
 
  {
1025
 
    float xp, yp;
1026
 
    int W = GetBaseWidth() - 2 * GRAPH_MARGIN;
1027
 
    int H = GetBaseHeight() - 2 * GRAPH_MARGIN;
1028
 
 
1029
 
    xp = /*m_minX +*/ dx * (m_maxX - m_minX) / W;
1030
 
    yp = /*m_minY +*/ dy * (m_maxY - m_minY) / H;
1031
 
 
1032
 
    if ( (m_minX + yp >= m_maxX - yp) || (m_minY + yp >= m_maxY - yp) )
1033
 
    {
1034
 
      yp = yp / 2.0f;
1035
 
    }
1036
 
 
1037
 
    if (m_bControlPointSelected == false)
1038
 
    {
1039
 
      if (m_bZoomingEnabled)
1040
 
      {
1041
 
        m_minX += yp;
1042
 
        m_maxX -= yp;
1043
 
        m_minY += yp;
1044
 
        m_maxY -= yp;
1045
 
 
1046
 
        NeedRedraw();
1047
 
        return;
1048
 
      }
1049
 
    }
1050
 
  }
1051
 
}
 
1
/*
 
2
 * Copyright 2010 Inalogic Inc.
 
3
 *
 
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.
 
7
 *
 
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.
 
13
 *
 
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/>
 
17
 *
 
18
 * Authored by: Jay Taoko <jaytaoko@inalogic.com>
 
19
 *
 
20
 */
 
21
 
 
22
 
 
23
#include "Nux.h"
 
24
 
 
25
#include "BezierCurveControl2.h"
 
26
#include "NuxCore/Math/Bezier.h"
 
27
 
 
28
namespace nux
 
29
{
 
30
 
 
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;
 
36
 
 
37
  unsigned long S_KEY = 0;
 
38
 
 
39
  BezierCurveControl2::BezierCurveControl2 (NUX_FILE_LINE_DECL)
 
40
    :   View (NUX_FILE_LINE_PARAM)
 
41
    ,   m_minX (-0.10f),
 
42
    m_minY (-0.100f),
 
43
    m_maxX (1.100f),
 
44
    m_maxY (1.100f),
 
45
    m_FunctionCallback (0),
 
46
    m_bControlPointSelected (0),
 
47
    m_bPanningEnabled (true),
 
48
    m_bZoomingEnabled (true)
 
49
  {
 
50
    SetMinimumSize (180, 180);
 
51
 
 
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) );
 
56
 
 
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) );
 
60
 
 
61
    OnKeyEvent.connect (sigc::mem_fun (this, &BezierCurveControl2::RecvKeyEvent) );
 
62
 
 
63
    NTextureData image;
 
64
    MakeCheckBoardImage (image.GetSurface (0), 64, 64, Color (0xff323232), Color (0xff535353), 8, 8);
 
65
    BaseTexture* m_CheckboardPattern = GetThreadGLDeviceFactory()->CreateSystemCapableTexture ();
 
66
    m_CheckboardPattern->Update (&image);
 
67
 
 
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);
 
72
 
 
73
    m_CheckboardPattern->UnReference ();
 
74
  }
 
75
 
 
76
  BezierCurveControl2::~BezierCurveControl2()
 
77
  {
 
78
    NUX_SAFE_DELETE (m_Background);
 
79
  }
 
80
 
 
81
 
 
82
  long BezierCurveControl2::ProcessEvent (IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
 
83
  {
 
84
    long ret = TraverseInfo;
 
85
 
 
86
    if (ievent.e_event == NUX_MOUSE_PRESSED)
 
87
    {
 
88
      if (!m_Geometry.IsPointInside (ievent.e_x, ievent.e_y) )
 
89
      {
 
90
        //ProcEvInfo = eDoNotProcess;
 
91
        //return TraverseInfo;
 
92
      }
 
93
    }
 
94
 
 
95
    S_KEY = ievent.GetVirtualKeyState (NUX_VK_S);
 
96
    ret = PostProcessEvent2 (ievent, ret, ProcessEventInfo);
 
97
    return ret;
 
98
  }
 
99
 
 
100
 
 
101
  void BezierCurveControl2::Draw (GraphicsEngine &GfxContext, bool force_draw)
 
102
  {
 
103
    Geometry base = GetGeometry();
 
104
 
 
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);
 
109
 
 
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;
 
114
 
 
115
    t_u32 i;
 
116
    int nsample = base.GetWidth();
 
117
    double t;
 
118
    t_u32 nbKnot = (t_u32) m_control_knot.size();
 
119
 
 
120
    GfxContext.PushClippingRectangle (base);
 
121
 
 
122
    GetPainter().PushDrawLayer (GfxContext, base, m_Background);
 
123
    GetPainter().PopBackground();
 
124
 
 
125
    //DrawGrid(GfxContext);
 
126
    DrawCoordinateSystem (GfxContext);
 
127
 
 
128
    if (nbKnot > 0)
 
129
    {
 
130
      double *xcon = new double[nbKnot];
 
131
      double xval;
 
132
      double *ycon = new double[nbKnot];
 
133
      double yval;
 
134
 
 
135
 
 
136
      for (i = 0; i < nbKnot; i++)
 
137
      {
 
138
        xcon[i] = m_control_knot[i].m_X;
 
139
        ycon[i] = m_control_knot[i].m_Y;
 
140
      }
 
141
 
 
142
      double xprev, yprev;
 
143
      Bezier_XY (CURVE_DEGREE, 0.0, xcon, ycon, &xprev, &yprev);
 
144
 
 
145
      int X0, Y0, X1, Y1, X2, Y2;
 
146
 
 
147
      glEnable (GL_POINT_SMOOTH);
 
148
      glEnable (GL_LINE_SMOOTH);
 
149
      glLineWidth (1);
 
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);
 
153
 
 
154
      for (i = 1; i < (t_u32) nsample; i++ )
 
155
      {
 
156
        t = ( double ) ( i ) / ( double ) ( nsample - 1 );
 
157
        Bezier_XY ( CURVE_DEGREE, t, xcon, ycon, &xval, &yval );
 
158
 
 
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) );
 
163
 
 
164
        GetPainter().Draw2DLine (GfxContext, X0, Y0, X1, Y1, Color (0xFFFFFFFF) );
 
165
 
 
166
        xprev = xval;
 
167
        yprev = yval;
 
168
      }
 
169
 
 
170
      if (m_control_knot[0].m_X > m_minX)
 
171
      {
 
172
        // draw line from the left border to the left most control point.
 
173
 
 
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) );
 
176
 
 
177
        GetPainter().Draw2DLine (GfxContext, base.x, Y0, X0, Y0, Color (0xFFFFFFFF) );
 
178
      }
 
179
 
 
180
      if (m_control_knot[nbKnot-1].m_X < m_maxX)
 
181
      {
 
182
        // draw line from the right most control point to the left border.
 
183
 
 
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) );
 
186
 
 
187
        GetPainter().Draw2DLine (GfxContext, X0, Y0, base.x + base.GetWidth(), Y0, Color (0xFFFFFFFF) );
 
188
      }
 
189
 
 
190
      glDisable (GL_POINT_SMOOTH);
 
191
      glDisable (GL_LINE_SMOOTH);
 
192
      GfxContext.GetRenderStates().SetBlend (FALSE);
 
193
 
 
194
      for (i = 0; i <= nbKnot - 1; i += CURVE_DEGREE)
 
195
      {
 
196
        // Only the endpoint of cubic bezier.
 
197
 
 
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) );
 
200
 
 
201
        if (i < nbKnot - 1)
 
202
        {
 
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) );
 
205
 
 
206
          GetPainter().Draw2DLine (GfxContext, X0, Y0, X1, Y1, Color (0xFF0000FF) );
 
207
        }
 
208
 
 
209
        if ( i > 0)
 
210
        {
 
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) );
 
213
 
 
214
          GetPainter().Draw2DLine (GfxContext, X0, Y0, X2, Y2, Color (0xFF0000FF) );
 
215
        }
 
216
      }
 
217
 
 
218
      Geometry ShapeGeo = GetTheme().GetImageGeometry (eDOT6x6);
 
219
 
 
220
      for (i = 0; i < nbKnot; i++)
 
221
      {
 
222
        int X0, Y0;
 
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) );
 
225
 
 
226
        if (m_control_knot[i].m_IsSelected)
 
227
        {
 
228
          GetPainter().PaintShape (GfxContext,
 
229
                               Geometry (X0 - ShapeGeo.GetWidth() / 2, Y0 - ShapeGeo.GetHeight() / 2, ShapeGeo.GetWidth(), ShapeGeo.GetHeight() ),
 
230
                               Color (0xFF44FF44), eDOT6x6);
 
231
        }
 
232
        else
 
233
        {
 
234
          GetPainter().PaintShape (GfxContext,
 
235
                               Geometry (X0 - ShapeGeo.GetWidth() / 2, Y0 - ShapeGeo.GetHeight() / 2, ShapeGeo.GetWidth(), ShapeGeo.GetHeight() ),
 
236
                               Color (0xFFFFFFFF), eDOT6x6);
 
237
        }
 
238
      }
 
239
 
 
240
      delete xcon;
 
241
      delete ycon;
 
242
    }
 
243
 
 
244
    GetPainter().Paint2DQuadWireframe (GfxContext, base, Color (0xFF000000) );
 
245
 
 
246
    DrawRuler (GfxContext);
 
247
    GfxContext.PopClippingRectangle();
 
248
  }
 
249
 
 
250
  void BezierCurveControl2::DrawRuler (GraphicsEngine &GfxContext)
 
251
  {
 
252
    Geometry base = GetGeometry();
 
253
 
 
254
    base.OffsetPosition (GRAPH_MARGIN, GRAPH_MARGIN);
 
255
    base.OffsetSize (-2 * GRAPH_MARGIN, -2 * GRAPH_MARGIN);
 
256
 
 
257
    // Draw Horizontal ruler
 
258
 
 
259
    static float Funit = 1.0;
 
260
    float rangex = m_maxX - m_minX;
 
261
    int Iunit = Funit * base.GetWidth() / rangex;
 
262
 
 
263
    if (Iunit > 2 * UNIT_REFERENCE)
 
264
    {
 
265
      Funit = rangex * UNIT_REFERENCE / base.GetWidth();
 
266
    }
 
267
    else if (Iunit < UNIT_REFERENCE)
 
268
    {
 
269
      Funit = rangex * 2 * UNIT_REFERENCE / base.GetWidth();
 
270
    }
 
271
 
 
272
    if ( (m_minX < 0) && (m_maxX > 0) )
 
273
    {
 
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;
 
276
      int count = 0;
 
277
 
 
278
      while (start_x > base.x)
 
279
      {
 
280
        GetPainter().Draw2DLine (GfxContext, start_x, base.y + base.GetHeight(), start_x, base.y + base.GetHeight() - 5, Color (0xFF000000) );
 
281
        count++;
 
282
        start_x -= Funit * base.GetWidth() / rangex;
 
283
      }
 
284
 
 
285
      start_x = base.x + center + Funit * base.GetWidth() / rangex;
 
286
      count = 0;
 
287
 
 
288
      while (start_x < base.x + base.GetWidth() )
 
289
      {
 
290
        GetPainter().Draw2DLine (GfxContext, start_x, base.y + base.GetHeight(), start_x, base.y + base.GetHeight() - 5, Color (0xFF000000) );
 
291
        count++;
 
292
        start_x += Funit * base.GetWidth() / rangex;
 
293
      }
 
294
    }
 
295
 
 
296
    if (0 <= m_minX)
 
297
    {
 
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;
 
300
      int count = 0;
 
301
 
 
302
      while (start_x < base.x + base.GetWidth() )
 
303
      {
 
304
        GetPainter().Draw2DLine (GfxContext, start_x, base.y + base.GetHeight(), start_x, base.y + base.GetHeight() - 5, Color (0xFF000000) );
 
305
        count++;
 
306
        start_x += Funit * base.GetWidth() / rangex;
 
307
      }
 
308
    }
 
309
 
 
310
    if (m_maxX <= 0)
 
311
    {
 
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;
 
314
      int count = 0;
 
315
 
 
316
      while (start_x > base.x)
 
317
      {
 
318
        GetPainter().Draw2DLine (GfxContext, start_x, base.y + base.GetHeight(), start_x, base.y + base.GetHeight() - 5, Color (0xFF000000) );
 
319
        count++;
 
320
        start_x -= Funit * base.GetWidth() / rangex;
 
321
      }
 
322
    }
 
323
 
 
324
    // Draw Vertical ruler
 
325
 
 
326
    static float FunitY = 1.0;
 
327
    float rangey = m_maxY - m_minY;
 
328
    int IunitY = FunitY * base.GetHeight() / rangey;
 
329
 
 
330
    if (IunitY > 2 * UNIT_REFERENCE)
 
331
    {
 
332
      FunitY = rangey * UNIT_REFERENCE / base.GetHeight();
 
333
    }
 
334
    else if (IunitY < UNIT_REFERENCE)
 
335
    {
 
336
      FunitY = rangey * 2 * UNIT_REFERENCE / base.GetHeight();
 
337
    }
 
338
 
 
339
    if ( (m_minY < 0) && (m_maxY > 0) )
 
340
    {
 
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;
 
343
      int count = 0;
 
344
 
 
345
      while (start_y > base.y)
 
346
      {
 
347
        GetPainter().Draw2DLine (GfxContext, base.x, start_y , base.x + 5, start_y, Color (0xFF000000) );
 
348
        count++;
 
349
        start_y -= FunitY * base.GetHeight() / rangey;
 
350
      }
 
351
 
 
352
      start_y = base.y + base.GetHeight() - center + FunitY * base.GetHeight() / rangey;
 
353
      count = 0;
 
354
 
 
355
      while (start_y < base.y + base.GetHeight() )
 
356
      {
 
357
        GetPainter().Draw2DLine (GfxContext, base.x, start_y , base.x + 5, start_y, Color (0xFF000000) );
 
358
        count++;
 
359
        start_y += FunitY * base.GetHeight() / rangey;
 
360
      }
 
361
    }
 
362
 
 
363
    if (0 <= m_minY)
 
364
    {
 
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;
 
367
      int count = 0;
 
368
 
 
369
      while (start_y > base.y)
 
370
      {
 
371
        GetPainter().Draw2DLine (GfxContext, base.x, start_y , base.x + 5, start_y, Color (0xFF000000) );
 
372
        count++;
 
373
        start_y -= FunitY * base.GetHeight() / rangey;
 
374
      }
 
375
    }
 
376
 
 
377
    if (m_maxY <= 0)
 
378
    {
 
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;
 
381
      int count = 0;
 
382
 
 
383
      while (start_y < base.y + base.GetHeight() )
 
384
      {
 
385
        GetPainter().Draw2DLine (GfxContext, base.x, start_y , base.x + 5, start_y, Color (0xFF000000) );
 
386
        count++;
 
387
        start_y += FunitY * base.GetHeight() / rangey;
 
388
      }
 
389
    }
 
390
  }
 
391
 
 
392
  void BezierCurveControl2::DrawGrid (GraphicsEngine &GfxContext)
 
393
  {
 
394
    Geometry base = GetGeometry();
 
395
 
 
396
    base.OffsetPosition (GRAPH_MARGIN, GRAPH_MARGIN);
 
397
    base.OffsetSize (-2 * GRAPH_MARGIN, -2 * GRAPH_MARGIN);
 
398
 
 
399
    // Draw Vertical Grid
 
400
 
 
401
    static float Funit = 1.0;
 
402
    float rangex = m_maxX - m_minX;
 
403
    int Iunit = Funit * base.GetWidth() / rangex;
 
404
 
 
405
    if (Iunit > 2 * UNIT_REFERENCE)
 
406
    {
 
407
      Funit = rangex * UNIT_REFERENCE / base.GetWidth();
 
408
    }
 
409
    else if (Iunit < UNIT_REFERENCE)
 
410
    {
 
411
      Funit = rangex * 2 * UNIT_REFERENCE / base.GetWidth();
 
412
    }
 
413
 
 
414
    if ( (m_minX < 0) && (m_maxX > 0) )
 
415
    {
 
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;
 
418
      int count = 0;
 
419
 
 
420
      while (start_x > base.x)
 
421
      {
 
422
        // vertical grid
 
423
        GetPainter().Draw2DLine (GfxContext, start_x, base.y,
 
424
                             start_x, base.y + base.GetHeight(), Color (0xFF5F5F5F) );
 
425
 
 
426
        count++;
 
427
        start_x -= Funit * base.GetWidth() / rangex;
 
428
      }
 
429
 
 
430
      start_x = base.x + center + Funit * base.GetWidth() / rangex;
 
431
      count = 0;
 
432
 
 
433
      while (start_x < base.x + base.GetWidth() )
 
434
      {
 
435
        // vertical grid
 
436
        GetPainter().Draw2DLine (GfxContext, start_x, base.y,
 
437
                             start_x, base.y + base.GetHeight(), Color (0xFF5F5F5F) );
 
438
 
 
439
        count++;
 
440
        start_x += Funit * base.GetWidth() / rangex;
 
441
      }
 
442
    }
 
443
 
 
444
    if (0 <= m_minX)
 
445
    {
 
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;
 
448
      int count = 0;
 
449
 
 
450
      while (start_x < base.x + base.GetWidth() )
 
451
      {
 
452
        // vertical grid
 
453
        GetPainter().Draw2DLine (GfxContext, start_x, base.y,
 
454
                             start_x, base.y + base.GetHeight(), Color (0xFF5F5F5F) );
 
455
 
 
456
        count++;
 
457
        start_x += Funit * base.GetWidth() / rangex;
 
458
      }
 
459
    }
 
460
 
 
461
    if (m_maxX <= 0)
 
462
    {
 
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;
 
465
      int count = 0;
 
466
 
 
467
      while (start_x > base.x)
 
468
      {
 
469
        // vertical grid
 
470
        GetPainter().Draw2DLine (GfxContext, start_x, base.y,
 
471
                             start_x, base.y + base.GetHeight(), Color (0xFF5F5F5F) );
 
472
 
 
473
        count++;
 
474
        start_x -= Funit * base.GetWidth() / rangex;
 
475
      }
 
476
    }
 
477
 
 
478
    // Draw Horizontal Grid
 
479
 
 
480
    static float FunitY = 1.0;
 
481
    float rangey = m_maxY - m_minY;
 
482
    int IunitY = FunitY * base.GetHeight() / rangey;
 
483
 
 
484
    if (IunitY > 2 * UNIT_REFERENCE)
 
485
    {
 
486
      FunitY = rangey * UNIT_REFERENCE / base.GetHeight();
 
487
    }
 
488
    else if (IunitY < UNIT_REFERENCE)
 
489
    {
 
490
      FunitY = rangey * 2 * UNIT_REFERENCE / base.GetHeight();
 
491
    }
 
492
 
 
493
    if ( (m_minY < 0) && (m_maxY > 0) )
 
494
    {
 
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;
 
497
      int count = 0;
 
498
 
 
499
      while (start_y > base.y)
 
500
      {
 
501
        // horizontal grid
 
502
        GetPainter().Draw2DLine (GfxContext, base.x, start_y,
 
503
                             base.x + base.GetWidth(), start_y, Color (0xFF5F5F5F) );
 
504
 
 
505
        count++;
 
506
        start_y -= FunitY * base.GetHeight() / rangey;
 
507
      }
 
508
 
 
509
      start_y = base.y + base.GetHeight() - center + FunitY * base.GetHeight() / rangey;
 
510
      count = 0;
 
511
 
 
512
      while (start_y < base.y + base.GetHeight() )
 
513
      {
 
514
        GetPainter().Draw2DLine (GfxContext, base.x, start_y,
 
515
                             base.x + base.GetWidth(), start_y, Color (0xFF5F5F5F) );
 
516
 
 
517
        count++;
 
518
        start_y += FunitY * base.GetHeight() / rangey;
 
519
      }
 
520
    }
 
521
 
 
522
    if (0 <= m_minY)
 
523
    {
 
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;
 
526
      int count = 0;
 
527
 
 
528
      while (start_y > base.y)
 
529
      {
 
530
        GetPainter().Draw2DLine (GfxContext, base.x, start_y,
 
531
                             base.x + base.GetWidth(), start_y, Color (0xFF5F5F5F) );
 
532
 
 
533
        count++;
 
534
        start_y -= FunitY * base.GetHeight() / rangey;
 
535
      }
 
536
    }
 
537
 
 
538
    if (m_maxY <= 0)
 
539
    {
 
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;
 
542
      int count = 0;
 
543
 
 
544
      while (start_y < base.y + base.GetHeight() )
 
545
      {
 
546
        GetPainter().Draw2DLine (GfxContext, base.x, start_y,
 
547
                             base.x + base.GetWidth(), start_y, Color (0xFF5F5F5F) );
 
548
 
 
549
        count++;
 
550
        start_y += FunitY * base.GetHeight() / rangey;
 
551
      }
 
552
    }
 
553
  }
 
554
 
 
555
  void BezierCurveControl2::DrawCoordinateSystem (GraphicsEngine &GfxContext)
 
556
  {
 
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;
 
561
 
 
562
    int X0, Y0;
 
563
    X0 = X + W * (0 - m_minX) / (m_maxX - m_minX);
 
564
    Y0 = Y + H * ( 1 - (0 - m_minY) / (m_maxY - m_minY) );
 
565
 
 
566
    GetPainter().Draw2DLine (GfxContext, X0, Y, X0, Y + H, Color (0xFF222222) );
 
567
    GetPainter().Draw2DLine (GfxContext, X, Y0, X + W, Y0, Color (0xFF000000) );
 
568
  }
 
569
 
 
570
  void BezierCurveControl2::DrawContent (GraphicsEngine &GfxContext, bool force_draw)
 
571
  {
 
572
 
 
573
  }
 
574
 
 
575
  void BezierCurveControl2::PostDraw (GraphicsEngine &GfxContext, bool force_draw)
 
576
  {
 
577
 
 
578
  }
 
579
 
 
580
 
 
581
  void BezierCurveControl2::SetXAxisBounds (float minX, float maxX)
 
582
  {
 
583
    m_minX = minX;
 
584
    m_maxX = maxX;
 
585
    NeedRedraw();
 
586
  }
 
587
 
 
588
  void BezierCurveControl2::SetYAxisBounds (float minY, float maxY)
 
589
  {
 
590
    m_minY = minY;
 
591
    m_maxY = maxY;
 
592
    NeedRedraw();
 
593
  }
 
594
 
 
595
  void BezierCurveControl2::SetFunctionCallback (FunctionCallback f)
 
596
  {
 
597
    m_FunctionCallback = f;
 
598
    NeedRedraw();
 
599
  }
 
600
 
 
601
  float BezierCurveControl2::EvalFunction (float x)
 
602
  {
 
603
    if (m_FunctionCallback != 0)
 
604
      return (*m_FunctionCallback) (x);
 
605
 
 
606
    return 0;
 
607
  }
 
608
 
 
609
  void BezierCurveControl2::UpdateGraph()
 
610
  {
 
611
    NeedRedraw();
 
612
  }
 
613
 
 
614
 
 
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) )
 
618
#endif
 
619
 
 
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) )
 
623
#endif
 
624
 
 
625
  void BezierCurveControl2::RecvMouseUp (int x, int y, unsigned long button_flags, unsigned long key_flags)
 
626
  {
 
627
    NeedRedraw();
 
628
  }
 
629
 
 
630
  void BezierCurveControl2::RecvMouseDown (int x, int y, unsigned long button_flags, unsigned long key_flags)
 
631
  {
 
632
    if (! (button_flags & NUX_EVENT_BUTTON1) )
 
633
    {
 
634
      return;
 
635
    }
 
636
 
 
637
    m_bControlPointSelected = false;
 
638
    t_u32 nbKnot = (t_u32) m_control_knot.size();
 
639
 
 
640
    for (t_u32 i = 0; i < nbKnot; i++)
 
641
    {
 
642
      m_control_knot[i].m_IsSelected = false;
 
643
    }
 
644
 
 
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;
 
649
 
 
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);
 
651
 
 
652
    if (b == false)
 
653
      return;
 
654
 
 
655
//    X = GetX();
 
656
//    Y = GetY();
 
657
    for (t_u32 i = 0; i < nbKnot; i++)
 
658
    {
 
659
      int Xp, Yp;
 
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) );
 
662
 
 
663
      int tx, ty;
 
664
      tx = X + x - GRAPH_MARGIN;
 
665
      ty = Y + y - GRAPH_MARGIN;
 
666
 
 
667
      if (PT_INSIDE_BOX (tx, ty, Xp - KNOT_HIT_TEST, Xp + KNOT_HIT_TEST, Yp - KNOT_HIT_TEST, Yp + KNOT_HIT_TEST) )
 
668
      {
 
669
        m_control_knot[i].m_IsSelected = true;
 
670
        hit_point_dx = (tx) - Xp;
 
671
        hit_point_dy = Yp - (ty);
 
672
 
 
673
        m_bControlPointSelected = true;
 
674
 
 
675
        if ( (i % CURVE_DEGREE) == 0)
 
676
        {
 
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.
 
679
        }
 
680
 
 
681
        break;
 
682
      }
 
683
    }
 
684
 
 
685
    NeedRedraw();
 
686
  }
 
687
 
 
688
  int ClosestCubicBezierEndPoint (int i)
 
689
  {
 
690
    if ( (i % CURVE_DEGREE) == 0)
 
691
    {
 
692
      return i;
 
693
    }
 
694
 
 
695
    if ( ( (i + 1) % CURVE_DEGREE) == 0)
 
696
    {
 
697
      return i + 1;
 
698
    }
 
699
 
 
700
    if ( ( (i - 1) % CURVE_DEGREE) == 0)
 
701
    {
 
702
      return i - 1;
 
703
    }
 
704
 
 
705
    return 0;
 
706
  }
 
707
 
 
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*/
 
715
  )
 
716
  {
 
717
 
 
718
  }
 
719
 
 
720
  void BezierCurveControl2::RecvMouseDrag (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
 
721
  {
 
722
    if ( (m_bControlPointSelected == false) && (button_flags & NUX_STATE_BUTTON1_DOWN) && S_KEY)
 
723
    {
 
724
      if (m_bPanningEnabled)
 
725
      {
 
726
        ProcessPanning (x, y, dx, dy, button_flags, key_flags);
 
727
        return;
 
728
      }
 
729
    }
 
730
 
 
731
    if ( (m_bControlPointSelected == false) && (button_flags & NUX_STATE_BUTTON3_DOWN) && S_KEY)
 
732
    {
 
733
      if (m_bZoomingEnabled)
 
734
      {
 
735
        ProcessZooming (x, y, dx, dy, button_flags, key_flags);
 
736
        return;
 
737
      }
 
738
    }
 
739
 
 
740
    if (button_flags & NUX_STATE_BUTTON1_DOWN)
 
741
      ManipulateBezier (x, y, dx, dy, button_flags, key_flags);
 
742
  }
 
743
 
 
744
  void BezierCurveControl2::ManipulateBezier (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
 
745
  {
 
746
    float xp, yp;
 
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;
 
751
 
 
752
    t_s32 nbKnot = (t_s32) m_control_knot.size();
 
753
 
 
754
    xp = /*m_minX +*/ dx * (m_maxX - m_minX) / W;
 
755
    yp = /*m_minY +*/ dy * (m_maxY - m_minY) / H;
 
756
 
 
757
    nuxAssert (nbKnot >= CURVE_DEGREE);
 
758
    int x_border = 0;
 
759
    int y_border = 0;
 
760
 
 
761
    for (t_s32 i = 0; i < nbKnot; i++)
 
762
    {
 
763
      if (m_control_knot[i].m_IsSelected)
 
764
      {
 
765
        int tempx, tempy;
 
766
        tempx = X + x - GRAPH_MARGIN;
 
767
        tempy = Y + y - GRAPH_MARGIN;
 
768
 
 
769
        int Xp, Yp;
 
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) );
 
772
 
 
773
        if (dx > 0)
 
774
        {
 
775
          if (tempx > Xp + hit_point_dx)
 
776
          {
 
777
            xp = /*m_minX +*/ (m_maxX - m_minX) * (tempx - Xp - hit_point_dx) / W;
 
778
          }
 
779
          else
 
780
          {
 
781
            xp = 0;
 
782
          }
 
783
        }
 
784
        else if (dx < 0)
 
785
        {
 
786
          if (tempx < Xp + hit_point_dx)
 
787
          {
 
788
            xp = /*m_minX +*/ (m_maxX - m_minX) * (tempx - Xp - hit_point_dx) / W;
 
789
          }
 
790
          else
 
791
          {
 
792
            xp = 0;
 
793
          }
 
794
        }
 
795
 
 
796
        if (dy > 0)
 
797
        {
 
798
          if (tempy > Yp - hit_point_dy)
 
799
          {
 
800
            yp = /*m_minY +*/ (m_maxY - m_minY) * (tempy - Yp + hit_point_dy) / H;
 
801
          }
 
802
          else
 
803
          {
 
804
            yp = 0;
 
805
          }
 
806
        }
 
807
        else if (dy < 0)
 
808
        {
 
809
          if (tempy < Yp - hit_point_dy)
 
810
          {
 
811
            yp = /*m_minY +*/ (m_maxY - m_minY) * (tempy - Yp + hit_point_dy) / H;
 
812
          }
 
813
          else
 
814
          {
 
815
            yp = 0;
 
816
          }
 
817
        }
 
818
 
 
819
        if (m_bPanningEnabled == false)
 
820
        {
 
821
          if (m_control_knot[i].m_X + xp < m_minX)
 
822
          {
 
823
            xp = m_minX - m_control_knot[i].m_X;
 
824
            x_border = -1;
 
825
          }
 
826
          else if (m_control_knot[i].m_X + xp > m_maxX)
 
827
          {
 
828
            xp = m_maxX - m_control_knot[i].m_X;
 
829
            x_border = +1;
 
830
          }
 
831
 
 
832
          if (m_control_knot[i].m_Y - yp < m_minY)
 
833
          {
 
834
            yp = m_control_knot[i].m_Y - m_minY;
 
835
            y_border = -1;
 
836
          }
 
837
          else if (m_control_knot[i].m_Y - yp > m_maxY)
 
838
          {
 
839
            yp = m_control_knot[i].m_Y - m_maxY;
 
840
            y_border = +1;
 
841
          }
 
842
        }
 
843
 
 
844
 
 
845
        if ( (i % CURVE_DEGREE) == 0)
 
846
        {
 
847
          if (y_border == 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;
 
853
 
 
854
          // Only endpoint of cubic bezier curves.
 
855
          if (i == 0)
 
856
          {
 
857
            if (x_border == 0)
 
858
            {
 
859
              if ( m_control_knot[i].m_X + xp > m_control_knot[i + CURVE_DEGREE].m_X - 0.01)
 
860
              {
 
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;
 
863
              }
 
864
              else
 
865
              {
 
866
                m_control_knot[i].m_X += xp;
 
867
              }
 
868
            }
 
869
            else
 
870
            {
 
871
              if (x_border == -1)
 
872
                m_control_knot[i].m_X = m_minX;
 
873
              else if (x_border == +1)
 
874
                m_control_knot[i].m_X = m_maxX;
 
875
 
 
876
              if ( m_control_knot[i].m_X > m_control_knot[i + CURVE_DEGREE].m_X - 0.01)
 
877
              {
 
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;
 
880
              }
 
881
            }
 
882
 
 
883
            // move the right tangent points
 
884
            {
 
885
              m_control_knot[i+1].m_X += xp;
 
886
              m_control_knot[i+1].m_Y -= yp;
 
887
 
 
888
              if (m_control_knot[i+1].m_X < m_control_knot[i].m_X)
 
889
              {
 
890
                m_control_knot[i+1].m_X = m_control_knot[i].m_X;
 
891
              }
 
892
            }
 
893
          }
 
894
          else if (i == nbKnot - 1)
 
895
          {
 
896
            if (x_border == 0)
 
897
            {
 
898
              if (m_control_knot[i].m_X + xp < m_control_knot[i - CURVE_DEGREE].m_X + 0.01)
 
899
              {
 
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;
 
902
              }
 
903
              else
 
904
              {
 
905
                m_control_knot[i].m_X += xp;
 
906
              }
 
907
            }
 
908
            else
 
909
            {
 
910
              if (x_border == -1)
 
911
                m_control_knot[i].m_X = m_minX;
 
912
              else if (x_border == +1)
 
913
                m_control_knot[i].m_X = m_maxX;
 
914
 
 
915
              if (m_control_knot[i].m_X < m_control_knot[i - CURVE_DEGREE].m_X + 0.01)
 
916
              {
 
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;
 
919
              }
 
920
            }
 
921
 
 
922
            // move the left tangent points
 
923
            {
 
924
              m_control_knot[i-1].m_X += xp;
 
925
              m_control_knot[i-1].m_Y -= yp;
 
926
 
 
927
              if (m_control_knot[i-1].m_X > m_control_knot[i].m_X)
 
928
              {
 
929
                m_control_knot[i-1].m_X = m_control_knot[i].m_X;
 
930
              }
 
931
            }
 
932
          }
 
933
          else
 
934
          {
 
935
            if (m_control_knot[i].m_X + xp > m_control_knot[i + CURVE_DEGREE].m_X - 0.01)
 
936
            {
 
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;
 
939
            }
 
940
            else if (m_control_knot[i].m_X + xp < m_control_knot[i - CURVE_DEGREE].m_X + 0.01)
 
941
            {
 
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;
 
944
            }
 
945
            else
 
946
            {
 
947
              m_control_knot[i].m_X += xp;
 
948
            }
 
949
 
 
950
            // move the left and right tangent points
 
951
            {
 
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;
 
956
 
 
957
              if (m_control_knot[i-1].m_X > m_control_knot[i].m_X)
 
958
              {
 
959
                m_control_knot[i-1].m_X = m_control_knot[i].m_X;
 
960
              }
 
961
 
 
962
              if (m_control_knot[i+1].m_X < m_control_knot[i].m_X)
 
963
              {
 
964
                m_control_knot[i+1].m_X = m_control_knot[i].m_X;
 
965
              }
 
966
            }
 
967
          }
 
968
        }
 
969
        else
 
970
        {
 
971
          m_control_knot[i].m_X += xp;
 
972
          m_control_knot[i].m_Y -= yp;
 
973
 
 
974
          t_s32 index = (t_s32) ClosestCubicBezierEndPoint (i);
 
975
 
 
976
          if (index > i)
 
977
          {
 
978
            if (m_control_knot[i].m_X > m_control_knot[index].m_X)
 
979
            {
 
980
              m_control_knot[i].m_X = m_control_knot[index].m_X;
 
981
            }
 
982
          }
 
983
          else if ( index < i)
 
984
          {
 
985
            if (m_control_knot[i].m_X < m_control_knot[index].m_X)
 
986
            {
 
987
              m_control_knot[i].m_X = m_control_knot[index].m_X;
 
988
            }
 
989
          }
 
990
        }
 
991
 
 
992
        break;
 
993
      }
 
994
    }
 
995
 
 
996
    NeedRedraw();
 
997
  }
 
998
 
 
999
  void BezierCurveControl2::ProcessPanning (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
 
1000
  {
 
1001
    float xp, yp;
 
1002
    int W = GetBaseWidth() - 2 * GRAPH_MARGIN;
 
1003
    int H = GetBaseHeight() - 2 * GRAPH_MARGIN;
 
1004
 
 
1005
    xp = /*m_minX +*/ dx * (m_maxX - m_minX) / W;
 
1006
    yp = /*m_minY +*/ dy * (m_maxY - m_minY) / H;
 
1007
 
 
1008
    if (m_bControlPointSelected == false)
 
1009
    {
 
1010
      if (m_bPanningEnabled)
 
1011
      {
 
1012
        m_minX -= xp;
 
1013
        m_maxX -= xp;
 
1014
        m_minY += yp;
 
1015
        m_maxY += yp;
 
1016
 
 
1017
        NeedRedraw();
 
1018
        return;
 
1019
      }
 
1020
    }
 
1021
  }
 
1022
 
 
1023
  void BezierCurveControl2::ProcessZooming (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
 
1024
  {
 
1025
    float xp, yp;
 
1026
    int W = GetBaseWidth() - 2 * GRAPH_MARGIN;
 
1027
    int H = GetBaseHeight() - 2 * GRAPH_MARGIN;
 
1028
 
 
1029
    xp = /*m_minX +*/ dx * (m_maxX - m_minX) / W;
 
1030
    yp = /*m_minY +*/ dy * (m_maxY - m_minY) / H;
 
1031
 
 
1032
    if ( (m_minX + yp >= m_maxX - yp) || (m_minY + yp >= m_maxY - yp) )
 
1033
    {
 
1034
      yp = yp / 2.0f;
 
1035
    }
 
1036
 
 
1037
    if (m_bControlPointSelected == false)
 
1038
    {
 
1039
      if (m_bZoomingEnabled)
 
1040
      {
 
1041
        m_minX += yp;
 
1042
        m_maxX -= yp;
 
1043
        m_minY += yp;
 
1044
        m_maxY -= yp;
 
1045
 
 
1046
        NeedRedraw();
 
1047
        return;
 
1048
      }
 
1049
    }
 
1050
  }
 
1051
}