1 #include <math.h>
2 #include "studiox_includes.h"
3 #include "easing_function_select_dlg.h"
4 
5 
6 // easing_function_select_dlg dialog
7 
8 #define ANIMATION_TOTAL_STEP 50
9 #define ANIMATION_TIMER_ID   1024
10 #define ANIMATION_BOX_WIDTH  30
11 #define ANIMATION_BOX_HEIGHT 16
12 #define ANIMATION_DOT_RADIUS 10
13 
14 
15 enum easing_function_select_dlg_test_commands{
16     TEST_SELECT_EASING_FUNCTION = 1,
17     TEST_SAVE_EASING_FUNCTION_SELECT,
18     TEST_CANCEL_EASING_FUNCTION_SELECT
19 };
20 
21 STRING_VAL_PAIR easing_function_list[] = {
22     { _T("back ease in"), GX_ANIMATION_BACK_EASE_IN },
23     { _T("back ease out"), GX_ANIMATION_BACK_EASE_OUT },
24     { _T("back ease in out"), GX_ANIMATION_BACK_EASE_IN_OUT },
25     { _T("bounce ease in"), GX_ANIMATION_BOUNCE_EASE_IN },
26     { _T("bounce ease out"), GX_ANIMATION_BOUNCE_EASE_OUT },
27     { _T("bounce ease in out"), GX_ANIMATION_BOUNCE_EASE_IN_OUT },
28     { _T("circ ease in"), GX_ANIMATION_CIRC_EASE_IN },
29     { _T("circ ease out"), GX_ANIMATION_CIRC_EASE_OUT },
30     { _T("circ ease in out"), GX_ANIMATION_CIRC_EASE_IN_OUT },
31     { _T("cubic ease in"), GX_ANIMATION_CUBIC_EASE_IN },
32     { _T("cubic ease out"), GX_ANIMATION_CUBIC_EASE_OUT },
33     { _T("cubic ease in out"), GX_ANIMATION_CUBIC_EASE_IN_OUT },
34     { _T("elastic ease in"), GX_ANIMATION_ELASTIC_EASE_IN },
35     { _T("elastic ease out"), GX_ANIMATION_ELASTIC_EASE_OUT },
36     { _T("elastic ease in out"), GX_ANIMATION_ELASTIC_EASE_IN_OUT },
37     { _T("expo ease in"), GX_ANIMATION_EXPO_EASE_IN },
38     { _T("expo ease out"), GX_ANIMATION_EXPO_EASE_OUT },
39     { _T("expo ease in out"), GX_ANIMATION_EXPO_EASE_IN_OUT },
40     { _T("quad ease in"), GX_ANIMATION_QUAD_EASE_IN },
41     { _T("quad ease out"), GX_ANIMATION_QUAD_EASE_OUT },
42     { _T("quad ease in out"), GX_ANIMATION_QUAD_EASE_IN_OUT },
43     { _T("quart ease in"), GX_ANIMATION_QUART_EASE_IN },
44     { _T("quart ease out"), GX_ANIMATION_QUART_EASE_OUT },
45     { _T("quart ease in out"), GX_ANIMATION_QUART_EASE_IN_OUT },
46     { _T("quint ease in"), GX_ANIMATION_QUINT_EASE_IN },
47     { _T("quint ease out"), GX_ANIMATION_QUINT_EASE_OUT },
48     { _T("quint ease in out"), GX_ANIMATION_QUINT_EASE_IN_OUT },
49     { _T("sine ease in"), GX_ANIMATION_SINE_EASE_IN },
50     { _T("sine ease out"), GX_ANIMATION_SINE_EASE_OUT },
51     { _T("sine ease in out"), GX_ANIMATION_SINE_EASE_IN_OUT },
52     { _T(""), 0}
53 };
54 
IMPLEMENT_DYNAMIC(easing_function_select_dlg,express_dialog)55 IMPLEMENT_DYNAMIC(easing_function_select_dlg, express_dialog)
56 
57 BEGIN_MESSAGE_MAP(easing_function_select_dlg, express_dialog)
58     ON_CBN_SELCHANGE(IDC_EASING_FUNC_COMBO, OnSelecteEasingFuncCombo)
59     ON_WM_PAINT()
60     ON_WM_ERASEBKGND()
61     ON_WM_TIMER()
62     ON_BN_CLICKED(IDC_ANIMATION_START, &easing_function_select_dlg::OnAnimationStart)
63     ON_MESSAGE(STUDIO_TEST, &easing_function_select_dlg::OnTestMessage)
64 END_MESSAGE_MAP()
65 
66 ///////////////////////////////////////////////////////////////////////////////
67 easing_function_select_dlg::easing_function_select_dlg(int easing_function_id, CWnd* pParent /*=NULL*/)
68     : express_dialog(easing_function_select_dlg::IDD, pParent)
69 {
70     SetTitleText("Select Easing Function");
71     IconId = IDB_CONFIGURE_PROJECTS;
72     mEasingFuncId = easing_function_id;
73 
74     mWaveRect.left = 0;
75     mWaveRect.right = 0;
76     mWaveRect.top = 0;
77     mWaveRect.bottom = 0;
78     mAnimationStep = 0;
79 
80     int dpi = GetSystemDPI();
81     mAnimationBoxSize.cx = MulDiv(ANIMATION_BOX_WIDTH, dpi, DEFAULT_DPI_96);
82     mAnimationBoxSize.cy = MulDiv(ANIMATION_BOX_HEIGHT, dpi, DEFAULT_DPI_96);
83 
84     mAnimationDotRadius = MulDiv(ANIMATION_DOT_RADIUS, dpi, DEFAULT_DPI_96);
85 }
86 
87 ///////////////////////////////////////////////////////////////////////////////
~easing_function_select_dlg()88 easing_function_select_dlg::~easing_function_select_dlg()
89 {
90 }
91 
92 ///////////////////////////////////////////////////////////////////////////////
GetEasingFuncId(CString type_name)93 int easing_function_select_dlg::GetEasingFuncId(CString type_name)
94 {
95     return FindPairVal(easing_function_list, type_name);
96 }
97 
98 ///////////////////////////////////////////////////////////////////////////////
GetEasingFuncIdName(int type)99 CString easing_function_select_dlg::GetEasingFuncIdName(int type)
100 {
101     return FindPairString(easing_function_list, type);
102 }
103 
104 ///////////////////////////////////////////////////////////////////////////////
DoDataExchange(CDataExchange * pDX)105 void easing_function_select_dlg::DoDataExchange(CDataExchange* pDX)
106 {
107     express_dialog::DoDataExchange(pDX);
108     DDX_Control(pDX, IDC_EASING_FUNC_COMBO, mEasingFuncCombo);
109     DDX_Control(pDX, IDC_ANIMATION_STATUS, mAnimationStatus);
110 
111     if (!pDX->m_bSaveAndValidate)
112     {
113         mAnimationStatus.SetWindowTextW(L"");
114         SetLiveRegion(mAnimationStatus.GetSafeHwnd());
115     }
116 }
117 
118 ///////////////////////////////////////////////////////////////////////////////
OnInitDialog()119 BOOL easing_function_select_dlg::OnInitDialog()
120 {
121     express_dialog::OnInitDialog();
122 
123     AddCancelButton();
124     AddSaveButton();
125 
126     STRING_VAL_PAIR *current = easing_function_list;
127     int index;
128     int sel_index = -1;
129 
130     while (current->name.GetLength())
131     {
132         index = mEasingFuncCombo.AddString(current->name);
133         mEasingFuncCombo.SetItemData(index, current->val);
134         if (current->val == mEasingFuncId)
135         {
136             sel_index = index;
137         }
138         current++;
139     }
140 
141     if (sel_index >= 0)
142     {
143         mEasingFuncCombo.SetCurSel(sel_index);
144     }
145     mEasingFuncCombo.InsertString(0, _T("None"));
146 
147     if (sel_index < 0)
148     {
149         mEasingFuncCombo.SetCurSel(0);
150     }
151 
152     return TRUE;
153 }
154 
155 ///////////////////////////////////////////////////////////////////////////////
OnPaint()156 void easing_function_select_dlg::OnPaint()
157 {
158     CPaintDC dc(this);
159     CRect rect;
160 
161     GetDlgItem(IDC_ANIMATION_START)->GetWindowRect(&rect);
162     ScreenToClient(&rect);
163     mWaveRect.top = rect.bottom + (mAnimationBoxSize.cy << 2);
164 
165     mAnimationStatus.GetWindowRect(&rect);
166     ScreenToClient(&rect);
167     mWaveRect.bottom = rect.top - (mAnimationBoxSize.cy << 2);
168     mWaveRect.left = rect.left;
169     mWaveRect.right = rect.right;
170 
171     mAnimationRect = mWaveRect;
172     mAnimationRect.left -= (mAnimationBoxSize.cx * 3 / 2) + 1;
173     mAnimationRect.right += (mAnimationDotRadius / 2) + 1;
174     mAnimationRect.top -= (mAnimationBoxSize.cy << 2);
175     mAnimationRect.bottom += (mAnimationBoxSize.cy << 2);
176 
177     CDC        dcMem;
178     HBITMAP    hbmMem;
179     HANDLE     hOld;
180 
181     GetClientRect(&rect);
182 
183     /* Flush canvas memory to off-screen DC. */
184     dcMem.CreateCompatibleDC(&dc);
185     hbmMem = CreateCompatibleBitmap(dc, rect.Width(), rect.Height());
186     hOld = SelectObject(dcMem, hbmMem);
187 
188     dcMem.FillSolidRect(rect, GetSysColor(COLOR_3DFACE));
189 
190     Graphics       g(dcMem);
191 
192     Color color;
193     color.SetFromCOLORREF(GetSysColor(COLOR_WINDOWTEXT));
194     Pen pen(color);
195 
196     g.DrawLine(&pen, mWaveRect.left, mWaveRect.top, mWaveRect.left, mWaveRect.bottom);
197     g.DrawLine(&pen, mWaveRect.left, mWaveRect.bottom, mWaveRect.right, mWaveRect.bottom);
198 
199     DrawEasingCurve(g);
200 
201     PaintTitleAndStatusBar(&dcMem);
202 
203     /* Transfer the off-screen DC to the screen. */
204     BitBlt(dc, 0, 0, rect.Width(), rect.Height(), dcMem, 0, 0, SRCCOPY);
205 
206     /* Free-up the off-screen DC.  */
207     SelectObject(dcMem, hOld);
208     DeleteObject(hbmMem);
209     DeleteDC(dcMem);
210 }
211 
212 ///////////////////////////////////////////////////////////////////////////////
OnEraseBkgnd(CDC * pDC)213 BOOL easing_function_select_dlg::OnEraseBkgnd(CDC* pDC)
214 {
215     return GX_FALSE;
216 }
217 
218 ///////////////////////////////////////////////////////////////////////////////
OnTimer(UINT_PTR nIDEvent)219 void easing_function_select_dlg::OnTimer(UINT_PTR nIDEvent)
220 {
221     if (nIDEvent == ANIMATION_TIMER_ID)
222     {
223         mAnimationStep++;
224 
225         CString status("");
226         if (mAnimationStep == 1)
227         {
228             if (mEasingFuncId)
229             {
230                 status = GetEasingFuncIdName(mEasingFuncId);
231             }
232             else
233             {
234                 status = L"linear";
235             }
236 
237             status.Append(L" animation is started!");
238         }
239         else if (mAnimationStep == ANIMATION_TOTAL_STEP)
240         {
241             if (mEasingFuncId)
242             {
243                 status = GetEasingFuncIdName(mEasingFuncId);
244             }
245             else
246             {
247                 status = L"linear";
248             }
249 
250             status.Append(L" animation is completed!");
251             KillTimer(ANIMATION_TIMER_ID);
252         }
253 
254         if (!status.IsEmpty())
255         {
256             mAnimationStatus.SetWindowTextW(status);
257 
258             // Raise a UIA LiveRegionChanged
259             // event so that a screen reader is made aware of a change to the LiveRegion.
260             // Make sure the updated text is set on the label before making this call.
261             mAnimationStatus.NotifyWinEvent(
262                 EVENT_OBJECT_LIVEREGIONCHANGED,
263                 OBJID_CLIENT,
264                 CHILDID_SELF);
265         }
266 
267         InvalidateRect(&mAnimationRect);
268     }
269 }
270 
271 ///////////////////////////////////////////////////////////////////////////////
OnAnimationStart()272 void easing_function_select_dlg::OnAnimationStart()
273 {
274     mAnimationStep = 0;
275     SetTimer(ANIMATION_TIMER_ID, USER_TIMER_MINIMUM, GX_NULL);
276 }
277 
278 ///////////////////////////////////////////////////////////////////////////////
BackEaseIn(float t,float d)279 float easing_function_select_dlg::BackEaseIn(float t, float d)
280 {
281     t /= d;
282     return (float)(t *t*(2.70158 * t - 1.70158));
283 }
284 
285 ///////////////////////////////////////////////////////////////////////////////
BackEaseOut(float t,float d)286 float easing_function_select_dlg::BackEaseOut(float t, float d)
287 {
288     t = t / d - 1;
289     return (float)(t * t * (2.70158 * t + 1.70158) + 1);
290 }
291 
292 ///////////////////////////////////////////////////////////////////////////////
BackEaseInOut(float t,float d)293 float easing_function_select_dlg::BackEaseInOut(float t, float d)
294 {
295     t = (2 * t / d);
296 
297     if (t < 1)
298     {
299         return (float)(t * t * (3.5949 * t - 2.5949) / 2);
300     }
301     else
302     {
303         t -= 2;
304         return (float)(t * t * (3.5949 * t + 2.5949) / 2 + 1);
305     }
306 }
307 
308 ///////////////////////////////////////////////////////////////////////////////
BounceEaseIn(float t,float d)309 float easing_function_select_dlg::BounceEaseIn(float t, float d)
310 {
311     return (float)(1 - BounceEaseOut(d - t, d));
312 }
313 
314 ///////////////////////////////////////////////////////////////////////////////
BounceEaseOut(float t,float d)315 float easing_function_select_dlg::BounceEaseOut(float t, float d)
316 {
317     t /= d;
318     if (t < 0.363)
319     {
320         return (float)(7.5625 * t * t);
321     }
322     else if (t < 0.727)
323     {
324         t -= (float)0.545;
325         return (float)(7.5625 * t * t + 0.75);
326     }
327     else if (t < 0.909)
328     {
329         t -= (float)0.818;
330         return (float)(7.5625 * t * t + 0.9375);
331     }
332     else
333     {
334         t -= (float)0.9545;
335         return (float)(7.5625 * t * t + 0.984375);
336     }
337 
338 }
339 
340 ///////////////////////////////////////////////////////////////////////////////
BounceEaseInOut(float t,float d)341 float easing_function_select_dlg::BounceEaseInOut(float t, float d)
342 {
343     if (t * 2 < d)
344     {
345         return BounceEaseIn(t * 2, d) / 2;
346     }
347     else
348     {
349         return (BounceEaseOut(t * 2 - d, d) + 1) / 2;
350     }
351 }
352 
353 ///////////////////////////////////////////////////////////////////////////////
CircEaseIn(float t,float d)354 float easing_function_select_dlg::CircEaseIn(float t, float d)
355 {
356     t /= d;
357     return (float)(1 - sqrt(1 - t * t));
358 }
359 
360 ///////////////////////////////////////////////////////////////////////////////
CircEaseOut(float t,float d)361 float easing_function_select_dlg::CircEaseOut(float t, float d)
362 {
363     t = (t / d) - 1;
364     return (float)(sqrt(1 - t * t));
365 }
366 
367 ///////////////////////////////////////////////////////////////////////////////
CircEaseInOut(float t,float d)368 float easing_function_select_dlg::CircEaseInOut(float t, float d)
369 {
370     t = (2 * t / d);
371     if (t < 1)
372     {
373         return (float)((1 - sqrt(1 - t * t)) / 2);
374     }
375     else
376     {
377         t-=2;
378         return (float)((1 + sqrt(1 - t * t)) / 2);
379     }
380 }
381 
382 ///////////////////////////////////////////////////////////////////////////////
CubicEaseIn(float t,float d)383 float easing_function_select_dlg::CubicEaseIn(float t, float d)
384 {
385     t /= d;
386 
387     return (t * t * t);
388 }
389 
390 ///////////////////////////////////////////////////////////////////////////////
CubicEaseOut(float t,float d)391 float easing_function_select_dlg::CubicEaseOut(float t, float d)
392 {
393     t = t / d - 1;
394     return (t * t * t + 1);
395 }
396 
397 ///////////////////////////////////////////////////////////////////////////////
CubicEaseInOut(float t,float d)398 float easing_function_select_dlg::CubicEaseInOut(float t, float d)
399 {
400     t = 2 * t / d;
401 
402     if (t < 1)
403     {
404         return (t * t * t / 2);
405     }
406     else
407     {
408         t -= 2;
409         return (t * t * t / 2 + 1);
410     }
411 }
412 
413 ///////////////////////////////////////////////////////////////////////////////
ElasticEaseIn(float t,float d)414 float easing_function_select_dlg::ElasticEaseIn(float t, float d)
415 {
416     if (t == 0)
417     {
418         return 0;
419     }
420 
421     if (t == d)
422     {
423         return 1;
424     }
425 
426     t = (t / d) - 1;
427 
428     return (float)(-pow(2, 10 * t) * sin(20.93 * t -1.57));
429 }
430 
431 ///////////////////////////////////////////////////////////////////////////////
ElasticEaseOut(float t,float d)432 float easing_function_select_dlg::ElasticEaseOut(float t, float d)
433 {
434     if (t == 0)
435     {
436         return 0;
437     }
438 
439     if (t == d)
440     {
441         return 1;
442     }
443 
444     t /= d;
445     return (float)(pow(2, -10 * t) * sin(20.93 * t - 1.57) + 1);
446 }
447 
448 ///////////////////////////////////////////////////////////////////////////////
ElasticEaseInOut(float t,float d)449 float easing_function_select_dlg::ElasticEaseInOut(float t, float d)
450 {
451     if (t == 0)
452     {
453         return 0;
454     }
455 
456     t = (2 * t) / d;
457     if (t == 2)
458     {
459         return 1;
460     }
461 
462     if (t < 1)
463     {
464         t -= 1;
465         return (float)(-pow(2, 10 * t) * sin(13.96*t - 1.57) / 2);
466     }
467     else
468     {
469         t -= 1;
470         return (float)(pow(2, -10 * t) * sin(13.96*t - 1.57) / 2 + 1);
471     }
472 }
473 
474 ///////////////////////////////////////////////////////////////////////////////
ExpoEaseIn(float t,float d)475 float easing_function_select_dlg::ExpoEaseIn(float t, float d)
476 {
477     t /= d;
478     return (float)pow(2, 10 * (t - 1));
479 }
480 
481 ///////////////////////////////////////////////////////////////////////////////
ExpoEaseOut(float t,float d)482 float easing_function_select_dlg::ExpoEaseOut(float t, float d)
483 {
484     t /= d;
485     return (float)(1 - pow(2, -10 * t));
486 }
487 
488 ///////////////////////////////////////////////////////////////////////////////
ExpoEaseInOut(float t,float d)489 float easing_function_select_dlg::ExpoEaseInOut(float t, float d)
490 {
491     t = 2 * t / d;
492     if (t < 1)
493     {
494         return (float)pow(2, 10 * (t - 1)) / 2;
495     }
496     else
497     {
498         t--;
499         return (float)(1 - pow(2, -10 * t) / 2);
500     }
501     return 0;
502 }
503 
504 ///////////////////////////////////////////////////////////////////////////////
QuadEaseInt(float t,float d)505 float easing_function_select_dlg::QuadEaseInt(float t, float d)
506 {
507     t /= d;
508     return t * t;
509 }
510 
511 ///////////////////////////////////////////////////////////////////////////////
QuadEaseOut(float t,float d)512 float easing_function_select_dlg::QuadEaseOut(float t, float d)
513 {
514     t /= d;
515     return t * (2 - t);
516 }
517 
518 ///////////////////////////////////////////////////////////////////////////////
QuadEaseInOut(float t,float d)519 float easing_function_select_dlg::QuadEaseInOut(float t, float d)
520 {
521     t = (2 * t / d);
522     if (t < 1)
523     {
524         return (t * t / 2);
525     }
526     else
527     {
528         t--;
529         return ((1 - t* (t - 2)) / 2);
530     }
531 }
532 
533 ///////////////////////////////////////////////////////////////////////////////
QuartEaseIn(float t,float d)534 float easing_function_select_dlg::QuartEaseIn(float t, float d)
535 {
536     t /= d;
537     return t * t * t * t;
538 }
539 
540 ///////////////////////////////////////////////////////////////////////////////
QuartEaseOut(float t,float d)541 float easing_function_select_dlg::QuartEaseOut(float t, float d)
542 {
543     t = t / d - 1;
544     return (1 - t*t*t*t);
545 }
546 
547 ///////////////////////////////////////////////////////////////////////////////
QuartEaseInOut(float t,float d)548 float easing_function_select_dlg::QuartEaseInOut(float t, float d)
549 {
550     t = (2 * t / d);
551     if (t < 1)
552     {
553         return t * t * t * t / 2;
554     }
555     else
556     {
557         t -= 2;
558         return (1 - t * t * t * t / 2);
559     }
560 }
561 
562 ///////////////////////////////////////////////////////////////////////////////
QuintEaseIn(float t,float d)563 float easing_function_select_dlg::QuintEaseIn(float t, float d)
564 {
565     t /= d;
566     return t * t * t * t * t;
567 }
568 
569 ///////////////////////////////////////////////////////////////////////////////
QuintEaseOut(float t,float d)570 float easing_function_select_dlg::QuintEaseOut(float t, float d)
571 {
572     t = (t / d - 1);
573     return (t * t * t * t * t + 1);
574 }
575 
576 ///////////////////////////////////////////////////////////////////////////////
QuintEaseInOut(float t,float d)577 float easing_function_select_dlg::QuintEaseInOut(float t, float d)
578 {
579     t = (2 * t / d);
580     if (t < 1)
581     {
582         return t * t * t * t *t / 2;
583     }
584     else
585     {
586         t -= 2;
587         return (t * t* t* t* t / 2 + 1);
588     }
589 }
590 
591 ///////////////////////////////////////////////////////////////////////////////
SinEaseIn(float t,float d)592 float easing_function_select_dlg::SinEaseIn(float t, float d)
593 {
594     return (float)(1 - cos(t / d * 1.57));
595 }
596 
597 ///////////////////////////////////////////////////////////////////////////////
SinEaseOut(float t,float d)598 float easing_function_select_dlg::SinEaseOut(float t, float d)
599 {
600     return (float)sin(t / d * 1.57);
601 }
602 
603 ///////////////////////////////////////////////////////////////////////////////
SinEaseInOut(float t,float d)604 float easing_function_select_dlg::SinEaseInOut(float t, float d)
605 {
606     return (float)((1 - cos(t / d * 3.14)) / 2);
607 }
608 
609 ///////////////////////////////////////////////////////////////////////////////
DrawEasingCurve(Graphics & g)610 void easing_function_select_dlg::DrawEasingCurve(Graphics &g)
611 {
612     SolidBrush red_brush(Color(255, 200, 0, 0));
613     REAL x;
614     REAL x1, x2;
615     REAL y1, y2;
616     REAL width = (REAL)mWaveRect.Width();
617     REAL height = (REAL)mWaveRect.Height();
618 
619     Color color;
620     color.SetFromCOLORREF(GetSysColor(COLOR_WINDOWTEXT));
621     Pen line_pen(color);
622 
623     g.SetSmoothingMode(SmoothingModeAntiAlias);
624 
625     switch (mEasingFuncId)
626     {
627     case GX_ANIMATION_BACK_EASE_IN:
628         mpEasingFuncCallback = BackEaseIn;
629         break;
630     case GX_ANIMATION_BACK_EASE_OUT:
631         mpEasingFuncCallback = BackEaseOut;
632         break;
633     case GX_ANIMATION_BACK_EASE_IN_OUT:
634         mpEasingFuncCallback = BackEaseInOut;
635         break;
636     case GX_ANIMATION_BOUNCE_EASE_IN:
637         mpEasingFuncCallback = BounceEaseIn;
638         break;
639     case GX_ANIMATION_BOUNCE_EASE_OUT:
640         mpEasingFuncCallback = BounceEaseOut;
641         break;
642     case GX_ANIMATION_BOUNCE_EASE_IN_OUT:
643         mpEasingFuncCallback = BounceEaseInOut;
644         break;
645     case GX_ANIMATION_CIRC_EASE_IN:
646         mpEasingFuncCallback = CircEaseIn;
647         break;
648     case GX_ANIMATION_CIRC_EASE_OUT:
649         mpEasingFuncCallback = CircEaseOut;
650         break;
651     case GX_ANIMATION_CIRC_EASE_IN_OUT:
652         mpEasingFuncCallback = CircEaseInOut;
653         break;
654     case GX_ANIMATION_CUBIC_EASE_IN:
655         mpEasingFuncCallback = CubicEaseIn;
656         break;
657     case GX_ANIMATION_CUBIC_EASE_OUT:
658         mpEasingFuncCallback = CubicEaseOut;
659         break;
660     case GX_ANIMATION_CUBIC_EASE_IN_OUT:
661         mpEasingFuncCallback = CubicEaseInOut;
662         break;
663     case GX_ANIMATION_ELASTIC_EASE_IN:
664         mpEasingFuncCallback = ElasticEaseIn;
665         break;
666     case GX_ANIMATION_ELASTIC_EASE_OUT:
667         mpEasingFuncCallback = ElasticEaseOut;
668         break;
669     case GX_ANIMATION_ELASTIC_EASE_IN_OUT:
670         mpEasingFuncCallback = ElasticEaseInOut;
671         break;
672     case GX_ANIMATION_EXPO_EASE_IN:
673         mpEasingFuncCallback = ExpoEaseIn;
674         break;
675     case GX_ANIMATION_EXPO_EASE_OUT:
676         mpEasingFuncCallback = ExpoEaseOut;
677         break;
678     case GX_ANIMATION_EXPO_EASE_IN_OUT:
679         mpEasingFuncCallback = ExpoEaseInOut;
680         break;
681     case GX_ANIMATION_QUAD_EASE_IN:
682         mpEasingFuncCallback = QuadEaseInt;
683         break;
684     case GX_ANIMATION_QUAD_EASE_OUT:
685         mpEasingFuncCallback = QuadEaseOut;
686         break;
687     case GX_ANIMATION_QUAD_EASE_IN_OUT:
688         mpEasingFuncCallback = QuadEaseInOut;
689         break;
690     case GX_ANIMATION_QUART_EASE_IN:
691         mpEasingFuncCallback = QuartEaseIn;
692         break;
693     case GX_ANIMATION_QUART_EASE_OUT:
694         mpEasingFuncCallback = QuartEaseOut;
695         break;
696     case GX_ANIMATION_QUART_EASE_IN_OUT:
697         mpEasingFuncCallback = QuartEaseInOut;
698         break;
699     case GX_ANIMATION_QUINT_EASE_IN:
700         mpEasingFuncCallback = QuintEaseIn;
701         break;
702     case GX_ANIMATION_QUINT_EASE_OUT:
703         mpEasingFuncCallback = QuintEaseOut;
704         break;
705     case GX_ANIMATION_QUINT_EASE_IN_OUT:
706         mpEasingFuncCallback = QuintEaseInOut;
707         break;
708     case GX_ANIMATION_SINE_EASE_IN:
709         mpEasingFuncCallback = SinEaseIn;
710         break;
711     case GX_ANIMATION_SINE_EASE_OUT:
712         mpEasingFuncCallback = SinEaseOut;
713         break;
714     case GX_ANIMATION_SINE_EASE_IN_OUT:
715         mpEasingFuncCallback = SinEaseInOut;
716         break;
717     default:
718         mpEasingFuncCallback = GX_NULL;
719         break;
720     }
721 
722     // draw easing curve
723     if (mpEasingFuncCallback)
724     {
725         x1 = (REAL)mWaveRect.left;
726         y1 = (REAL)mWaveRect.bottom;
727         for (x = 1; x <= width; x += 1)
728         {
729             x2 = (REAL)mWaveRect.left + x;
730             y2 = (REAL)mWaveRect.bottom - height * mpEasingFuncCallback(x, width);
731             g.DrawLine(&line_pen, x1, y1, x2, y2);
732 
733             x1 = x2;
734             y1 = y2;
735         }
736 
737         x = mAnimationStep * width / ANIMATION_TOTAL_STEP;
738         x2 = (REAL)mWaveRect.left + x;
739         y2 = (REAL)mWaveRect.bottom - height * mpEasingFuncCallback(x, width);
740     }
741     else
742     {
743         g.DrawLine(&line_pen, mWaveRect.left, mWaveRect.bottom, mWaveRect.right, mWaveRect.top);
744         x = mAnimationStep * width / ANIMATION_TOTAL_STEP;
745         x2 = (REAL)mWaveRect.left + x;
746         y2 = (REAL)mWaveRect.bottom - (REAL)(height * x / width);
747     }
748     // draw dot in curve
749     g.FillEllipse(&red_brush, RectF(x2 - ((REAL)mAnimationDotRadius/2), y2 - ((REAL)mAnimationDotRadius/2),
750         (REAL)mAnimationDotRadius, (REAL)mAnimationDotRadius));
751 
752     // draw animation rectangle
753     g.FillRectangle(&red_brush, RectF((REAL)(mWaveRect.left - (mAnimationBoxSize.cx * 3 / 2)),
754             (REAL)(y2 - (mAnimationBoxSize.cy/2)), (REAL)mAnimationBoxSize.cx, (REAL)mAnimationBoxSize.cy));
755 }
756 
757 ///////////////////////////////////////////////////////////////////////////////
OnSelecteEasingFuncCombo()758 void easing_function_select_dlg::OnSelecteEasingFuncCombo()
759 {
760     int index = mEasingFuncCombo.GetCurSel();
761     mEasingFuncId = mEasingFuncCombo.GetItemData(index);
762     InvalidateRect(&mAnimationRect);
763     mAnimationStatus.SetWindowTextW(L"");
764     mAnimationStep = 0;
765 }
766 
767 ///////////////////////////////////////////////////////////////////////////////
OnTestMessage(WPARAM wParam,LPARAM lParam)768 LRESULT easing_function_select_dlg::OnTestMessage(WPARAM wParam, LPARAM lParam)
769 {
770     switch (wParam)
771     {
772     case TEST_SELECT_EASING_FUNCTION:
773         mEasingFuncCombo.SelectString(0, GetTestingParam(0));
774         SendMessage(WM_COMMAND, MAKEWPARAM(IDC_EASING_FUNC_COMBO, CBN_SELCHANGE), (LPARAM)mEasingFuncCombo.m_hWnd);
775         break;
776 
777     case TEST_SAVE_EASING_FUNCTION_SELECT:
778         OnOK();
779         break;
780 
781     case TEST_CANCEL_EASING_FUNCTION_SELECT:
782         OnCancel();
783         break;
784     }
785 
786     return 0;
787 }