Added aqua_speed for rite geo 50 tryker
[ryzomcore.git] / nel / tools / 3d / object_viewer / curve_edit.cpp
blobe3e732ff4464264c41b31c0be89a1dac7d578f06
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2010 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "std_afx.h"
23 #include "object_viewer.h"
24 #include "curve_edit.h"
25 #include "editable_range.h"
26 #include "nel/3d/ps_float.h"
27 #include "nel/misc/common.h"
28 #include "nel/misc/fast_floor.h"
30 static const uint CtrlPointSize = 3;
34 CurveEdit::CurveEdit(NL3D::CPSFloatCurveFunctor *curve, CParticleWorkspace::CNode *ownerNode, IPopupNotify *pn, CWnd* pParent /*=NULL*/)
35 : CDialog(CurveEdit::IDD, pParent),
36 _Node(ownerNode),
37 _PN(pn),
38 Curve(curve),
39 _State(Create),
40 _X(10),
41 _Y(10),
42 _Width(350),
43 _Height(200),
44 _SelectedCtrlPoint(-1),
45 _NumSamplesDlg(NULL)
48 nlassert(Curve);
49 //{{AFX_DATA_INIT(CurveEdit)
50 m_DisplayInterpolation = FALSE;
51 m_SmoothingOn = FALSE;
52 //}}AFX_DATA_INIT
53 scaleMinMax();
56 CurveEdit::~CurveEdit()
58 if (_NumSamplesDlg)
60 _NumSamplesDlg->DestroyWindow();
61 delete _NumSamplesDlg;
66 void CurveEdit::DoDataExchange(CDataExchange* pDX)
68 CDialog::DoDataExchange(pDX);
69 //{{AFX_DATA_MAP(CurveEdit)
70 DDX_Check(pDX, IDC_DISPLAY_INTERPOLATION, m_DisplayInterpolation);
71 DDX_Check(pDX, IDC_SMOOTHING_ON, m_SmoothingOn);
72 //}}AFX_DATA_MAP
76 BEGIN_MESSAGE_MAP(CurveEdit, CDialog)
77 //{{AFX_MSG_MAP(CurveEdit)
78 ON_WM_MOUSEMOVE()
79 ON_WM_LBUTTONUP()
80 ON_WM_LBUTTONDOWN()
81 ON_WM_PAINT()
82 ON_BN_CLICKED(IDC_ZOOM_OUT, OnZoomOut)
83 ON_BN_CLICKED(IDC_ZOOM_IN, OnZoomIn)
84 ON_BN_CLICKED(IDC_GO_UP, OnGoUp)
85 ON_BN_CLICKED(IDC_GO_DOWN, OnGoDown)
86 ON_BN_CLICKED(IDC_MOVE_POINT, OnMovePoint)
87 ON_BN_CLICKED(IDC_ADD_POINT, OnAddPoint)
88 ON_BN_CLICKED(IDC_REMOVE_POINT, OnRemovePoint)
89 ON_BN_CLICKED(IDC_DISPLAY_INTERPOLATION, OnDisplayInterpolation)
90 ON_BN_CLICKED(IDC_SMOOTHING_ON, OnSmoothingOn)
91 ON_BN_CLICKED(IDC_LAST_EQUAL_FIRST, OnLastEqualFirst)
92 ON_BN_CLICKED(IDC_CENTER_CURVE, OnCenterCurve)
93 ON_BN_CLICKED(IDC_FIRST_EQUAL_LAST, OnFirstEqualLast)
94 ON_WM_DESTROY()
95 ON_WM_CLOSE()
96 //}}AFX_MSG_MAP
97 END_MESSAGE_MAP()
99 /////////////////////////////////////////////////////////////////////////////
100 // CurveEdit message handlers
102 void CurveEdit::OnMouseMove(UINT nFlags, CPoint point)
104 switch (_State)
106 case Move:
107 case Remove:
109 sint cpIndex = intersectCtrlPoint(point.x, point.y);
110 if (cpIndex != _SelectedCtrlPoint)
112 _SelectedCtrlPoint = cpIndex;
113 Invalidate();
116 break;
117 case Moving:
119 Curve->setCtrlPoint(_SelectedCtrlPoint,coordsFromScreen(point.x, point.y));
120 _SelectedCtrlPoint = intersectCtrlPoint(point.x, point.y); // the index of the point we are moving may have changed
121 if (_SelectedCtrlPoint == -1) _State = Move;
122 Invalidate();
124 break;
127 CDialog::OnMouseMove(nFlags, point);
130 void CurveEdit::OnLButtonUp(UINT nFlags, CPoint point)
132 switch (_State)
134 case Moving:
135 _State = Move;
136 _SelectedCtrlPoint = intersectCtrlPoint(point.x, point.y);
137 Invalidate();
138 break;
139 case Removing:
140 _State = Remove;
141 break;
142 case Created:
143 _State = Create;
144 break;
146 CDialog::OnLButtonUp(nFlags, point);
149 void CurveEdit::OnLButtonDown(UINT nFlags, CPoint point)
151 switch (_State)
153 case Move:
155 if (_SelectedCtrlPoint != -1) _State = Moving;
157 break;
158 case Create:
160 Curve->addControlPoint(coordsFromScreen(point.x, point.y));
161 _State = Created;
162 invalidate();
164 case Remove:
166 if ( _SelectedCtrlPoint == -1 || Curve->getNumCtrlPoints() == 2 ) return;
167 Curve->removeCtrlPoint(_SelectedCtrlPoint);
168 _State= Removing;
169 _SelectedCtrlPoint = -1;
170 invalidate();
172 break;
174 CDialog::OnLButtonDown(nFlags, point);
177 void CurveEdit::OnPaint()
179 UpdateData();
180 CPaintDC dc(this); // device context for painting
181 drawBackGround(dc);
182 drawUnits(dc);
183 drawCurve(dc);
184 if (m_DisplayInterpolation) drawInterpolatingCurve(dc);
185 drawCtrlPoints(dc);
189 void CurveEdit::setupBoundRect(CDC &dc)
191 CRgn rgn;
192 rgn.CreateRectRgn(_X, _X, _X + _Width, _Y + _Height);
193 dc.SelectClipRgn(&rgn, RGN_COPY );
196 void CurveEdit::drawBackGround(CDC &dc)
198 setupBoundRect(dc);
199 dc.FillSolidRect(_X, _Y, _Width, _Height, 0xffffff);
204 POINT CurveEdit::makePoint(float date, float value) const
206 POINT p;
207 p.x = (int) (_X + date * _Width);
208 p.y = (int) (_Y + _Height - _Scale * _Height * (value - _Origin));
209 return p;
213 sint CurveEdit::intersectCtrlPoint(sint x, sint y)
215 uint numPoints = Curve->getNumCtrlPoints();
216 for (uint k = 0; k < numPoints; ++k)
218 const CCtrlPoint &cp = Curve->getControlPoint(k);
219 POINT p = makePoint(cp.Date, cp.Value);
220 if ( x >= (sint) (p.x - CtrlPointSize)
221 && x <= (sint) (p.x + CtrlPointSize)
222 && y >= (sint) (p.y - CtrlPointSize)
223 && y <= (sint) (p.y + CtrlPointSize) )
225 return k;
228 return -1;
231 CurveEdit::CCtrlPoint CurveEdit::coordsFromScreen(sint x, sint y) const
233 float date =(x - _X) / (float) _Width;
234 NLMISC::clamp(date, 0.f, 1.f);
235 CCtrlPoint pos(
236 date,
237 _Origin + (_Y + _Height - y) / (_Scale * _Height)
239 return pos;
243 void CurveEdit::drawCurve(CDC &dc)
245 setupBoundRect(dc);
246 CPen pen;
247 pen.CreatePen(PS_SOLID, 1, (COLORREF) 0x000000);
248 CGdiObject *oldPen = dc.SelectObject(&pen);
250 dc.MoveTo(makePoint(0, Curve->getValue(0)));
251 for (sint x = 0; x < _Width; ++x)
253 const float date = x / (float) _Width;
254 dc.LineTo(_X + x, makePoint(date, Curve->getValue(date)).y);
256 dc.SelectObject(oldPen);
260 void CurveEdit::drawInterpolatingCurve(CDC &dc)
262 setupBoundRect(dc);
263 CPen pen;
264 pen.CreatePen(PS_SOLID, 1, (COLORREF) 0x772211);
265 CGdiObject *oldPen = dc.SelectObject(&pen);
266 dc.MoveTo(makePoint(0, getSampledValue(0)));
267 for (sint x = 0; x < _Width; ++x)
269 const float date = x / (float) _Width;
270 dc.LineTo(_X + x, makePoint(date, getSampledValue(date)).y);
272 dc.SelectObject(oldPen);
277 void CurveEdit::scaleMinMax()
279 float minValue, maxValue;
280 maxValue = minValue = getSampledValue(0);
281 for (sint x = 1; x < _Width; ++x)
283 const float date = x / (float) _Width;
284 const float value = getSampledValue(date);
285 minValue = std::min(minValue, value);
286 maxValue = std::max(maxValue, value);
288 _Origin = (maxValue == minValue) ? minValue - .5f : minValue;
289 _Scale = (maxValue == minValue) ? 1.f : 1.f / (maxValue - minValue);
295 void CurveEdit::drawCtrlPoints(CDC &dc)
297 setupBoundRect(dc);
298 CPen pens[2];
299 pens[0].CreatePen(PS_SOLID, 1, (COLORREF) 0x00ff00);
300 pens[1].CreatePen(PS_SOLID, 1, (COLORREF) 0x0000ff);
302 uint numPoints = Curve->getNumCtrlPoints();
303 for (uint k = 0; k < numPoints; ++k)
305 CGdiObject *oldPen = dc.SelectObject(&pens[k == (uint) _SelectedCtrlPoint ? 1 : 0]); // slect the red pen if thi ctrl point is selected
306 const CCtrlPoint &cp = Curve->getControlPoint(k);
307 POINT p = makePoint(cp.Date, cp.Value);
308 dc.MoveTo(p.x- CtrlPointSize, p.y - CtrlPointSize);
309 dc.LineTo(p.x + CtrlPointSize, p.y - CtrlPointSize);
310 dc.LineTo(p.x + CtrlPointSize, p.y + CtrlPointSize);
311 dc.LineTo(p.x - CtrlPointSize, p.y + CtrlPointSize);
312 dc.LineTo(p.x - CtrlPointSize, p.y - CtrlPointSize);
313 dc.SelectObject(oldPen);
318 void CurveEdit::OnZoomOut()
320 _Scale *= 1.5f;
321 Invalidate();
324 void CurveEdit::OnZoomIn()
326 _Scale *= 0.5f;
327 Invalidate();
330 void CurveEdit::OnGoUp()
332 _Origin += (1.f / _Scale) * 0.25f;
333 Invalidate();
336 void CurveEdit::OnGoDown()
338 _Origin -= (1.f / _Scale) * 0.25f;
339 Invalidate();
343 void CurveEdit::drawUnits(CDC &dc)
345 CPen pens[2];
346 pens[0].CreatePen(PS_SOLID, 1, (COLORREF) 0xaaaaaa);
347 pens[1].CreatePen(PS_SOLID, 1, (COLORREF) 0xff0011);
349 sint upVal = (sint) floorf(coordsFromScreen(0, _X).Value);
350 sint downVal = (sint) floorf(coordsFromScreen(0, _X + _Width).Value);
352 nlassert(upVal >= downVal);
353 for (sint k = downVal ; k <= upVal ; ++k)
355 CGdiObject *oldPen = dc.SelectObject(&pens[k == 0 ? 1 : 0]);
356 dc.MoveTo(makePoint(0, (float) k));
357 dc.LineTo(makePoint(1, (float) k));
358 dc.SelectObject(oldPen);
362 BOOL CurveEdit::OnInitDialog()
364 CDialog::OnInitDialog();
366 ((CButton *) GetDlgItem(IDC_ADD_POINT))->SetCheck(1);
368 _NumSamplesDlg = new CEditableRangeUInt(std::string("FLOAT_CURVE_NB_SAMPLE"), _Node, 1, 512);
369 _NumSampleWrapper.CE = this;
370 _NumSamplesDlg->setWrapper(&_NumSampleWrapper);
371 _NumSamplesDlg->init(80, 225, this);
372 _NumSamplesDlg->enableLowerBound(1, true);
373 m_SmoothingOn = Curve->hasSmoothing();
375 UpdateData(FALSE);
376 return TRUE; // return TRUE unless you set the focus to a control
377 // EXCEPTION: OCX Property Pages should return FALSE
380 void CurveEdit::OnMovePoint()
382 _State = Move;
383 _SelectedCtrlPoint = -1;
384 Invalidate();
387 void CurveEdit::OnAddPoint()
389 _State = Create;
390 _SelectedCtrlPoint = -1;
391 Invalidate();
394 void CurveEdit::OnRemovePoint()
396 _State = Remove;
397 _SelectedCtrlPoint = -1;
398 Invalidate();
401 void CurveEdit::OnDisplayInterpolation()
403 Invalidate();
408 float CurveEdit::getSampledValue(float date) const
410 nlassert(Curve);
411 nlassert(date >=0 && date < 1);
412 NLMISC::OptFastFloorBegin();
413 float result = (*Curve)(date);
414 NLMISC::OptFastFloorEnd();
415 return result;
418 void CurveEdit::OnSmoothingOn()
420 UpdateData();
421 nlassert(Curve);
422 Curve->enableSmoothing(m_SmoothingOn ? true : false /* perf; warning */);
423 invalidate();
427 void CurveEdit::OnLastEqualFirst()
429 CCtrlPoint pt = Curve->getControlPoint(0);
430 pt.Date = Curve->getControlPoint(Curve->getNumCtrlPoints() - 1).Date;
431 Curve->setCtrlPoint(Curve->getNumCtrlPoints() - 1, pt);
432 invalidate();
435 void CurveEdit::OnCenterCurve()
437 scaleMinMax();
438 Invalidate();
441 void CurveEdit::OnFirstEqualLast()
443 CCtrlPoint pt = Curve->getControlPoint(Curve->getNumCtrlPoints() - 1);
444 pt.Date = Curve->getControlPoint(0).Date;
445 Curve->setCtrlPoint(0, pt);
446 invalidate();
449 void CurveEdit::OnDestroy()
451 CDialog::OnDestroy();
454 void CurveEdit::init(CWnd *pParent)
456 CDialog::Create(IDD_CURVE_EDIT, pParent);
457 ShowWindow(SW_SHOW);
461 void CurveEdit::OnClose()
463 CDialog::OnClose();
464 _PN->childPopupClosed(this);
467 void CurveEdit::invalidate()
469 if (_Node)
471 _Node->setModified(true);
473 Invalidate();