Added aqua_speed for rite geo 50 tryker
[ryzomcore.git] / nel / tools / 3d / object_viewer / editable_range.h
blob16ef2adb0ad862918bd2f4fddc9e84076fdfa050
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) 2019 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/>.
21 #if !defined(AFX_EDITABLE_RANGE_H__0B1EFF2B_FA0E_4AC8_88B8_416605043BF9__INCLUDED_)
22 #define AFX_EDITABLE_RANGE_H__0B1EFF2B_FA0E_4AC8_88B8_416605043BF9__INCLUDED_
24 #if _MSC_VER > 1000
25 #pragma once
26 #endif // _MSC_VER > 1000
27 // editable_range.h : header file
30 #include <string>
31 #include "edit_attrib_dlg.h"
32 #include "range_manager.h"
33 #include "range_selector.h"
34 #include "ps_wrapper.h"
35 #include "bound_checker.h"
36 #include "particle_workspace.h"
38 /////////////////////////////////////////////////////////////////////////////
39 // CEditableRange dialog
41 class CEditableRange : public CEditAttribDlg
43 public:
44 /**
45 * Construct the dialog by giving it an Id. It will be used to save the user preference.
46 * Each dialog of this type must have its own id in the app.
48 CEditableRange(const std::string &id, CParticleWorkspace::CNode *node); // standard constructor
49 // Dialog Data
50 //{{AFX_DATA(CEditableRange)
51 enum { IDD = IDD_EDITABLE_RANGE };
52 CSliderCtrl m_SliderCtrl;
53 CEdit m_ValueCtrl;
54 CButton m_UpdateValue;
55 CButton m_SelectRange;
56 CString m_MinRange;
57 CString m_MaxRange;
58 CString m_Value;
59 int m_SliderPos;
60 //}}AFX_DATA
63 // Overrides
64 // ClassWizard generated virtual function overrides
65 //{{AFX_VIRTUAL(CEditableRange)
66 protected:
67 virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
68 //}}AFX_VIRTUAL
71 // init the dialog at the given position
72 public:
73 virtual void init(uint32 x, uint32 y, CWnd *pParent);
74 BOOL EnableWindow( BOOL bEnable = TRUE );
75 public:
76 /// for derivers : this must querries the value to the desired manager and set the dialog values
77 virtual void updateRange(void) = 0;
78 /** for derivers : value update from a linked object (reader). See examples in subclasses
80 virtual void updateValueFromReader(void) = 0;
81 // empty the values and the slider
82 void emptyDialog(void);
83 // validate the lower an upper bound of a range from their string representation
84 virtual bool editableRangeValueValidator(const CString &lo, const CString &up) = 0;
85 // update the dialog display
86 void update();
87 // Implementation
88 protected:
89 /** for derivers : value update : this is call with a float ranging from 0.f to 1.f (from the slider)
90 * And it must convert it to the desired value, changing the value of this dialog
92 virtual void updateValueFromSlider(double sliderValue) = 0;
93 /// the text has changed, and the user has pressed update
94 virtual void updateValueFromText(void) = 0;
95 // the range tune button was pressed. It muist show a dialog that allows the user to choose the range he wants
96 virtual void selectRange(void) = 0;
97 // the unique id of this dialog
98 std::string _Id;
99 CParticleWorkspace::CNode *_Node; // Node that owns the value
100 // Generated message map functions
101 //{{AFX_MSG(CEditableRange)
102 virtual BOOL OnInitDialog();
103 afx_msg void OnReleasedcaptureSlider(NMHDR* pNMHDR, LRESULT* pResult);
104 afx_msg void OnSelectRange();
105 afx_msg void OnSetfocusValue();
106 afx_msg void OnUpdateValue();
107 afx_msg void OnKillfocusValue();
108 afx_msg void OnChangeValue();
109 afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
110 //}}AFX_MSG
111 DECLARE_MESSAGE_MAP()
114 /** here, we define a template for editable ranges EditableRanges, that help to instanciate it
115 * Derivers have just to specialize 2 static methods : value2CString and string2value
118 template <typename T>
119 class CEditableRangeT : public CEditableRange, public CBoundChecker<T>
121 public:
122 /// ctor, it gives the range for the values
123 CEditableRangeT(const std::string &id, CParticleWorkspace::CNode *node, T defaultMin, T defaultMax)
124 : CEditableRange(id, node), _Range(defaultMin, defaultMax), _Wrapper(NULL)
128 /** set an interface of a wrapper to read / write values in the particle system
129 * NB : The 'OwnerNode' field of the wrapper if set to the value given when to 'node' when this object was constructed
131 void setWrapper(IPSWrapper<T> *wrapper) { _Wrapper = wrapper; _Wrapper->OwnerNode = _Node; }
135 public:
136 // SPECIALIZE THAT. write value into the given CString
137 static void value2CString(T value, CString &dest);
138 // SPECIALIZE THAT. convert a CString into a value, return NULL if ok, or a pointer to an error message
139 static const TCHAR *string2value(const CString &value, T &result);
143 void updateRange(void)
145 // retrieve our range
146 _Range = CRangeManager<T>::GetRange(_Id, _Range.first, _Range.second);
147 value2CString(_Range.first, m_MinRange);
148 value2CString(_Range.second, m_MaxRange);
149 /* if (_Wrapper)
151 setValue(_Wrapper->get());
153 UpdateData(FALSE);
155 void updateValueFromReader(void)
157 if (_Wrapper)
159 setValue(_Wrapper->get());
162 protected:
165 void updateValueFromText(void)
167 T value;
168 const TCHAR *message = string2value(m_Value, value);
169 if (!message)
171 const TCHAR *mess = validateUpperBound(value), *mess2 = validateLowerBound(value);
172 if (mess || mess2)
174 MessageBox(mess ? mess : mess2, _T("error"));
175 return;
179 _Wrapper->setAndUpdateModifiedFlag(value);
180 setValue(value);
181 return;
184 MessageBox(message, _T("error"));
187 void selectRange(void)
189 CString lowerBound, upperBound;
190 value2CString(_Range.first, lowerBound);
191 value2CString(_Range.second, upperBound);
193 CRangeSelector rs(lowerBound, upperBound, this);
195 if (rs.DoModal() == IDOK)
197 string2value(rs.getLowerBound(), _Range.first);
198 string2value(rs.getUpperBound(), _Range.second);
199 CRangeManager<T>::SetRange(_Id, _Range.first, _Range.second);
200 updateRange();
203 void updateValueFromSlider(double sliderValue)
205 nlassert(_Wrapper);
207 T value = _Range.first + (T) ((_Range.second - _Range.first) * sliderValue);
208 value2CString(value, m_Value);
210 if (_Wrapper)
212 _Wrapper->setAndUpdateModifiedFlag(value);
215 UpdateData(FALSE);
218 /// set a new value that will affect both slider and value display
219 void setValue(T value)
221 value2CString(value, m_Value);
223 // _Wrapper->set(value);
225 if (value < _Range.first)
227 m_SliderPos = (uint) (m_SliderCtrl.GetRangeMin());
229 else
230 if (value > _Range.second)
232 m_SliderPos = (uint) (m_SliderCtrl.GetRangeMax());
234 else
236 if (_Range.second != _Range.first)
238 m_SliderPos = (uint) ((double) (value - _Range.first) / (_Range.second - _Range.first) * (m_SliderCtrl.GetRangeMax() - m_SliderCtrl.GetRangeMin())
239 + m_SliderCtrl.GetRangeMin());
241 else
243 m_SliderPos = m_SliderCtrl.GetRangeMin();
246 UpdateData(FALSE);
250 virtual bool editableRangeValueValidator(const CString &lo, const CString &up)
252 T upT, loT;
254 const TCHAR *message = string2value(lo, loT);
255 if (message)
257 ::MessageBox(NULL, message, _T("Range selection error"), MB_OK);
258 return false;
260 const TCHAR *mess = validateUpperBound(loT), *mess2 = validateLowerBound(loT);
261 if (mess || mess2)
263 MessageBox(mess ? mess : mess2, _T("error"));
264 return false;
267 message = string2value(up, upT);
268 if (message)
270 ::MessageBox(NULL, message, _T("Range selection error"), MB_OK);
271 return false;
274 mess = validateUpperBound(upT);
275 mess2 = validateLowerBound(upT);
276 if (mess || mess2)
278 MessageBox(mess ? mess : mess2, _T("error"));
279 return false;
283 if (upT <= loT)
285 ::MessageBox(NULL, _T("upper bound must be strictly greater than lower bound"), _T("Range selection error"), MB_OK);
286 return false;
289 return true;
292 // min max values
293 std::pair<T, T> _Range;
295 // wrapper to the particle system
296 IPSWrapper<T> *_Wrapper;
302 ///////////////////////////////////////////////////////
303 // IMPLEMENTATION OF TEMPLATE METHOD SPECIALIZATIONS //
304 ///////////////////////////////////////////////////////
307 ////////////////////////////////////////////////////////
308 // float specialization. //
309 ////////////////////////////////////////////////////////
311 CEditableRangeT<float>::CEditableRangeT(const std::string &id, CParticleWorkspace::CNode *node, float defaultMin, float defaultMax )
312 : CEditableRange(id, node), _Range(defaultMin, defaultMax), _Wrapper(NULL)
316 inline void CEditableRangeT<float>::value2CString(float value, CString &dest)
318 dest.Format(_T("%g"), (double) value);
321 inline const TCHAR *CEditableRangeT<float>::string2value(const CString &value, float &result)
323 if (NLMISC::fromString(NLMISC::tStrToUtf8(value), result))
325 return NULL;
327 else
329 return _T("invalid value");
333 ////////////////////////////////////////////////////////
334 // uint32 specialization. //
335 ////////////////////////////////////////////////////////
337 CEditableRangeT<uint32>::CEditableRangeT(const std::string &id, CParticleWorkspace::CNode *node, uint32 defaultMin , uint32 defaultMax )
338 : CEditableRange(id, node), _Range(defaultMin, defaultMax), _Wrapper(NULL)
342 inline void CEditableRangeT<uint32>::value2CString(uint32 value, CString &dest)
344 dest.Format(_T("%d"), value);
347 inline const TCHAR *CEditableRangeT<uint32>::string2value(const CString &value, uint32 &result)
349 sint32 tmp;
350 if (NLMISC::fromString(NLMISC::tStrToUtf8(value), tmp))
352 if (value.Find(_T("-")) > -1)
354 return _T("negative values not allowed");
356 else
358 result = tmp;
359 return NULL;
362 else
364 return _T("invalid value");
369 ////////////////////////////////////////////////////////
370 // sint32 specialization. //
371 ////////////////////////////////////////////////////////
373 CEditableRangeT<sint32>::CEditableRangeT(const std::string &id, CParticleWorkspace::CNode *node, sint32 defaultMin , sint32 defaultMax)
374 : CEditableRange(id, node), _Range(defaultMin, defaultMax), _Wrapper(NULL)
378 inline void CEditableRangeT<sint32>::value2CString(sint32 value, CString &dest)
380 dest.Format(_T("%d"), value);
383 inline const TCHAR *CEditableRangeT<sint32>::string2value(const CString &value, sint32 &result)
385 sint32 tmp;
386 if (NLMISC::fromString(NLMISC::tStrToUtf8(value), tmp))
388 result = tmp;
389 return NULL;
391 else
393 return _T("invalid value");
398 // some typedefs
401 typedef CEditableRangeT<float> CEditableRangeFloat;
402 typedef CEditableRangeT<uint32> CEditableRangeUInt;
403 typedef CEditableRangeT<sint32> CEditableRangeInt;
407 //{{AFX_INSERT_LOCATION}}
408 // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
412 #endif // !defined(AFX_EDITABLE_RANGE_H__0B1EFF2B_FA0E_4AC8_88B8_416605043BF9__INCLUDED_)