1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
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.
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/>.
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
)
35 //{{AFX_DATA_INIT(CDirectionEdit)
36 // NOTE: the ClassWizard will add member initialization here
41 void CDirectionEdit::init(IPopupNotify
*pn
, CWnd
*pParent
)
43 Create(IDD_DIRECTION_EDIT
, pParent
);
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
58 BEGIN_MESSAGE_MAP(CDirectionEdit
, CDialog
)
59 //{{AFX_MSG_MAP(CDirectionEdit)
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);
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
)
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()
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
;
151 if (fabsf(d
> epsilon
))
153 f
= sqrtf((1.f
- v
.y
* v
.y
) / d
);
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
;
169 if (fabsf(d
> epsilon
))
171 f
= sqrtf((1.f
- v
.x
* v
.x
) / d
);
183 _Wrapper
->setAndUpdateModifiedFlag(v
);
189 void CDirectionEdit::OnLButtonDown(UINT nFlags
, CPoint point
)
191 selectNewVect(point
);
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
)
209 CDialog::OnLButtonUp(nFlags
, point
);
213 void CDirectionEdit::OnClose()
217 _Parent
->childPopupClosed(this);