Added aqua_speed for rite geo 50 tryker
[ryzomcore.git] / nel / tools / 3d / object_viewer / direction_edit.cpp
blobc3dca1c7981407f1ccdff9265b69100403308ab8
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "std_afx.h"
19 #include "object_viewer.h"
20 #include "direction_edit.h"
21 #include "direction_attr.h"
22 #include "popup_notify.h"
24 #include "nel/misc/vector.h"
26 /////////////////////////////////////////////////////////////////////////////
27 // CDirectionEdit dialog
30 CDirectionEdit::CDirectionEdit(IPSWrapper<NLMISC::CVector> *wrapper)
31 : _Wrapper(wrapper), _MouseState(CDirectionEdit::Wait)
34 nlassert(wrapper);
35 //{{AFX_DATA_INIT(CDirectionEdit)
36 // NOTE: the ClassWizard will add member initialization here
37 //}}AFX_DATA_INIT
41 void CDirectionEdit::init(IPopupNotify *pn, CWnd *pParent)
43 Create(IDD_DIRECTION_EDIT, pParent);
44 _Parent = pn;
45 ShowWindow(SW_SHOW);
49 void CDirectionEdit::DoDataExchange(CDataExchange* pDX)
51 CDialog::DoDataExchange(pDX);
52 //{{AFX_DATA_MAP(CDirectionEdit)
53 // NOTE: the ClassWizard will add DDX and DDV calls here
54 //}}AFX_DATA_MAP
58 BEGIN_MESSAGE_MAP(CDirectionEdit, CDialog)
59 //{{AFX_MSG_MAP(CDirectionEdit)
60 ON_WM_PAINT()
61 ON_WM_LBUTTONDOWN()
62 ON_WM_MOUSEMOVE()
63 ON_WM_LBUTTONUP()
64 ON_WM_CLOSE()
65 //}}AFX_MSG_MAP
66 END_MESSAGE_MAP()
69 // private : draw a basis with the given letters
70 static void DrawBasis(CDC &dc, sint x, sint y, sint size, const char *xStr, const char *yStr)
72 dc.FillSolidRect(x, y, size, size, 0xffffff);
74 CPen p;
75 p.CreatePen(PS_SOLID, 1, (COLORREF) 0);
77 CPen *oldPen = dc.SelectObject(&p);
79 dc.MoveTo(x + 5, y + size / 2);
80 dc.LineTo(x + size - 5, y + size / 2);
81 dc.MoveTo(x + size / 2, y + 5);
82 dc.LineTo(x + size / 2, y + size - 5);
84 dc.TextOut(x + size - 20, y + size / 2 - 18, CString(xStr));
85 dc.TextOut(x + 5 + size / 2, y + 5, CString(yStr));
87 dc.SelectObject(oldPen);
91 /// private : draw a vector in a basis
92 static void DrawVector(CDC &dc, float vx, float vy, sint x, sint y, sint size)
94 CPen p;
95 p.CreatePen(PS_SOLID, 1, (COLORREF) 0xff);
96 CPen *oldPen = dc.SelectObject(&p);
98 dc.MoveTo(x + size / 2, y + size / 2);
99 dc.LineTo(int(x + size / 2 + vx * 0.9f * size / 2), int(y + size / 2 - vy * 0.9f * size / 2));
101 dc.SelectObject(oldPen);
105 // size in pixel of the basis that is drawn in the dialog
106 const uint32 BasisSize = 120;
108 // the gap between 2 basis on the screen
109 const uint32 BasisGap = 20;
111 // the distance to the upper left corner for the basis drawing
112 const uint CornerDist = 10;
117 /// private get back a screen coord (pox, py) to a part of a vector. The basis of click is (x, y) - (x + size, y + size)
118 static void ScreenToVect(float &vx, float &vy, sint px, sint py, sint x, sint y, sint size)
120 vx = (px - (x + size / 2)) / 0.9f;
121 vy = ((y + size / 2) - py) / 0.9f;
124 void CDirectionEdit::OnPaint()
126 CPaintDC dc(this);
128 // get the current vector;
129 NLMISC::CVector v = _Wrapper->get();
132 // draw a white square, and draw the vector in it
134 DrawBasis(dc, CornerDist, CornerDist, BasisSize, "X", "Z");
135 DrawVector(dc, v.x, v.z, CornerDist, CornerDist, BasisSize);
137 DrawBasis(dc, CornerDist, CornerDist + BasisGap + BasisSize, BasisSize, "Y", "Z");
138 DrawVector(dc, v.y, v.z, CornerDist, CornerDist + BasisGap + BasisSize, BasisSize);
142 void CDirectionEdit::selectNewVect(const CPoint &point)
144 const float epsilon = 10E-3f;
145 NLMISC::CVector v = _Wrapper->get();
146 if (point.x > CornerDist && point.y > CornerDist && point.x < (CornerDist + BasisSize) && point.y < (CornerDist + BasisSize))
148 ScreenToVect(v.x, v.z, point.x, point.y, CornerDist, CornerDist, BasisSize);
149 float d = v.x * v.x + v.z * v.z;
150 float f;
151 if (fabsf(d > epsilon))
153 f = sqrtf((1.f - v.y * v.y) / d);
155 else
157 f = 1;
160 v.x *= f;
161 v.z *= f;
164 if (point.x > CornerDist && point.y > (BasisGap + BasisSize + CornerDist) && point.x < (CornerDist + BasisSize) && point.y < (CornerDist + BasisGap + 2 * BasisSize))
166 ScreenToVect(v.y, v.z, point.x, point.y, CornerDist, CornerDist + BasisGap + BasisSize, BasisSize);
167 float d = v.y * v.y + v.z * v.z;
168 float f;
169 if (fabsf(d > epsilon))
171 f = sqrtf((1.f - v.x * v.x) / d);
173 else
175 f = 1;
178 v.y *= f;
179 v.z *= f;
182 v.normalize();
183 _Wrapper->setAndUpdateModifiedFlag(v);
185 Invalidate();
189 void CDirectionEdit::OnLButtonDown(UINT nFlags, CPoint point)
191 selectNewVect(point);
192 _MouseState = Drag;
193 CDialog::OnLButtonDown(nFlags, point);
196 void CDirectionEdit::OnMouseMove(UINT nFlags, CPoint point)
198 if (_MouseState == Drag)
200 selectNewVect(point);
203 CDialog::OnMouseMove(nFlags, point);
206 void CDirectionEdit::OnLButtonUp(UINT nFlags, CPoint point)
208 _MouseState = Wait;
209 CDialog::OnLButtonUp(nFlags, point);
213 void CDirectionEdit::OnClose()
215 nlassert(_Parent);
216 CDialog::OnClose();
217 _Parent->childPopupClosed(this);