Linux multi-monitor fullscreen support
[ryzomcore.git] / nel / tools / 3d / object_viewer / vegetable_density_page.cpp
blob0f5a49faecabccd87a2ae1a81cba0a4aa7adaca4
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/>.
20 // vegetable_density_page.cpp : implementation file
23 #include "std_afx.h"
24 #include "object_viewer.h"
25 #include "vegetable_density_page.h"
26 #include "vegetable_edit_tools.h"
27 #include "vegetable_noise_value_dlg.h"
28 #include "vegetable_dlg.h"
29 #include "nel/misc/noise_value.h"
30 #include "nel/3d/vegetable.h"
34 #define NL_VEGETABLE_EDIT_ANGLE_SLIDER_SIZE 256
37 /////////////////////////////////////////////////////////////////////////////
38 // CVegetableDensityPage property page
40 IMPLEMENT_DYNCREATE(CVegetableDensityPage, CPropertyPage)
42 CVegetableDensityPage::CVegetableDensityPage() : CPropertyPage(CVegetableDensityPage::IDD),
43 _DensityDlg(NULL), _MaxDensityDlg(NULL)
45 //{{AFX_DATA_INIT(CVegetableDensityPage)
46 //}}AFX_DATA_INIT
49 CVegetableDensityPage::~CVegetableDensityPage()
51 #define REMOVE_WND(wnd) if (wnd) { wnd->DestroyWindow(); delete wnd; }
52 REMOVE_WND(_DensityDlg);
53 REMOVE_WND(_MaxDensityDlg);
56 void CVegetableDensityPage::DoDataExchange(CDataExchange* pDX)
58 CPropertyPage::DoDataExchange(pDX);
59 //{{AFX_DATA_MAP(CVegetableDensityPage)
60 DDX_Control(pDX, IDC_STATIC_VEGETABLE_SHAPENAME, StaticVegetableShape);
61 DDX_Control(pDX, IDC_STATIC_MAX_DENSITY, MaxDensityStaticText);
62 DDX_Control(pDX, IDC_SLIDER_ANGLE_MIN, AngleMinSlider);
63 DDX_Control(pDX, IDC_SLIDER_ANGLE_MAX, AngleMaxSlider);
64 DDX_Control(pDX, IDC_EDIT_ANGLE_MIN, AngleMinEdit);
65 DDX_Control(pDX, IDC_EDIT_ANGLE_MAX, AngleMaxEdit);
66 DDX_Control(pDX, IDC_COMBO_DIST_TYPE, DistTypeCombo);
67 DDX_Control(pDX, IDC_CHECK_MAX_DENSITY, MaxDensityCheckBox);
68 //}}AFX_DATA_MAP
72 BEGIN_MESSAGE_MAP(CVegetableDensityPage, CPropertyPage)
73 //{{AFX_MSG_MAP(CVegetableDensityPage)
74 ON_BN_CLICKED(IDC_CHECK_MAX_DENSITY, OnCheckMaxDensity)
75 ON_CBN_SELCHANGE(IDC_COMBO_DIST_TYPE, OnSelchangeComboDistType)
76 ON_BN_CLICKED(IDC_RADIO_ANGLE_CEILING, OnRadioAngleCeiling)
77 ON_BN_CLICKED(IDC_RADIO_ANGLE_FLOOR, OnRadioAngleFloor)
78 ON_BN_CLICKED(IDC_RADIO_ANGLE_WALL, OnRadioAngleWall)
79 ON_NOTIFY(NM_RELEASEDCAPTURE, IDC_SLIDER_ANGLE_MAX, OnReleasedcaptureSliderAngleMax)
80 ON_NOTIFY(NM_RELEASEDCAPTURE, IDC_SLIDER_ANGLE_MIN, OnReleasedcaptureSliderAngleMin)
81 ON_EN_KILLFOCUS(IDC_EDIT_ANGLE_MIN, OnKillfocusEditAngleMin)
82 ON_EN_KILLFOCUS(IDC_EDIT_ANGLE_MAX, OnKillfocusEditAngleMax)
83 ON_EN_CHANGE(IDC_EDIT_ANGLE_MIN, OnChangeEditAngleMin)
84 ON_EN_CHANGE(IDC_EDIT_ANGLE_MAX, OnChangeEditAngleMax)
85 ON_BN_CLICKED(IDC_BUTTON_VEGETABLE_BROWSE, OnButtonVegetableBrowse)
86 //}}AFX_MSG_MAP
87 END_MESSAGE_MAP()
90 // ***************************************************************************
91 // ***************************************************************************
92 // ***************************************************************************
93 // ***************************************************************************
96 // ***************************************************************************
97 void CVegetableDensityPage::setVegetableToEdit(NL3D::CVegetable *vegetable)
99 _Vegetable= vegetable;
101 // If not NULL, init all controls.
102 if(_Vegetable)
104 // Init ShapeName
105 // ----------
106 StaticVegetableShape.SetWindowText(nlUtf8ToTStr(_Vegetable->ShapeName));
108 // init Creation Distance.
109 // ----------
110 // normalize creation distance for this editor.
111 _Vegetable->DistType= std::min( (uint)_Vegetable->DistType, (uint)(DistTypeCombo.GetCount()-1) );
112 // set Creation Distance.
113 DistTypeCombo.SetCurSel( _Vegetable->DistType );
115 // init _DensityDlg.
116 // ----------
117 _DensityDlg->setNoiseValue(&_Vegetable->Density, _VegetableDlg);
119 // init MaxDensity
120 // ----------
121 if(_Vegetable->MaxDensity == -1)
123 // Disable the checkBox and the slider.
124 MaxDensityCheckBox.SetCheck(0);
125 static float dummy;
126 _MaxDensityDlg->setFloat(&dummy, _VegetableDlg);
127 _MaxDensityDlg->EnableWindow(false);
128 // Init with a default value
129 _PrecMaxDensityValue= NL_VEGETABLE_EDIT_DEFAULT_MAX_DENSITY;
131 else
133 // Enable the checkBox and the slider
134 MaxDensityCheckBox.SetCheck(1);
135 _MaxDensityDlg->setFloat(&_Vegetable->MaxDensity, _VegetableDlg);
136 _MaxDensityDlg->EnableWindow(true);
139 // init AngleSetup.
140 // ----------
141 NL3D::CVegetable::TAngleType angType= _Vegetable->getAngleType();
142 // disable 3 radio buttons.
143 ((CButton*)GetDlgItem(IDC_RADIO_ANGLE_FLOOR))->SetCheck(0);
144 ((CButton*)GetDlgItem(IDC_RADIO_ANGLE_WALL))->SetCheck(0);
145 ((CButton*)GetDlgItem(IDC_RADIO_ANGLE_CEILING))->SetCheck(0);
146 // enable only the one of interest.
147 switch(angType)
149 case NL3D::CVegetable::AngleGround:
150 ((CButton*)GetDlgItem(IDC_RADIO_ANGLE_FLOOR))->SetCheck(1);
151 enableAngleEdit(IDC_RADIO_ANGLE_FLOOR);
152 break;
153 case NL3D::CVegetable::AngleWall:
154 ((CButton*)GetDlgItem(IDC_RADIO_ANGLE_WALL))->SetCheck(1);
155 enableAngleEdit(IDC_RADIO_ANGLE_WALL);
156 break;
157 case NL3D::CVegetable::AngleCeiling:
158 ((CButton*)GetDlgItem(IDC_RADIO_ANGLE_CEILING))->SetCheck(1);
159 enableAngleEdit(IDC_RADIO_ANGLE_CEILING);
160 break;
162 // to avoid a strange bug if pos==0... (not correctly setuped the first time)
163 AngleMinSlider.SetPos(10);
164 AngleMaxSlider.SetPos(10);
165 // Init sliders / edit.
166 updateViewAngleMin();
167 updateViewAngleMax();
172 // ***************************************************************************
173 void CVegetableDensityPage::enableAngleEdit(uint radioId)
175 // first disable all
176 AngleMinSlider.EnableWindow(false);
177 AngleMinEdit.EnableWindow(false);
178 AngleMaxSlider.EnableWindow(false);
179 AngleMaxEdit.EnableWindow(false);
180 // Then enable only what needed.
181 if(radioId == IDC_RADIO_ANGLE_WALL || radioId == IDC_RADIO_ANGLE_FLOOR)
183 AngleMinSlider.EnableWindow(true);
184 AngleMinEdit.EnableWindow(true);
186 if(radioId == IDC_RADIO_ANGLE_WALL || radioId == IDC_RADIO_ANGLE_CEILING)
188 AngleMaxSlider.EnableWindow(true);
189 AngleMaxEdit.EnableWindow(true);
194 // ***************************************************************************
195 void CVegetableDensityPage::updateViewAngleMin()
197 double angle= _Vegetable->getCosAngleMin();
198 NLMISC::clamp(angle, -1, 1);
199 angle= asin(angle);
201 sint pos= (sint)(angle/(NLMISC::Pi/2) * NL_VEGETABLE_EDIT_ANGLE_SLIDER_SIZE);
202 NLMISC::clamp(pos, -NL_VEGETABLE_EDIT_ANGLE_SLIDER_SIZE, NL_VEGETABLE_EDIT_ANGLE_SLIDER_SIZE);
203 AngleMinSlider.SetPos(pos);
205 CString stmp;
206 stmp.Format(_T("%.2f"), (double)(angle*180/NLMISC::Pi));
207 AngleMinEdit.SetWindowText(stmp);
210 // ***************************************************************************
211 void CVegetableDensityPage::updateViewAngleMax()
213 double angle= _Vegetable->getCosAngleMax();
214 NLMISC::clamp(angle, -1, 1);
215 angle= asin(angle);
217 sint pos= (sint)(angle/(NLMISC::Pi/2) * NL_VEGETABLE_EDIT_ANGLE_SLIDER_SIZE);
218 NLMISC::clamp(pos, -NL_VEGETABLE_EDIT_ANGLE_SLIDER_SIZE, NL_VEGETABLE_EDIT_ANGLE_SLIDER_SIZE);
219 AngleMaxSlider.SetPos(pos);
221 CString stmp;
222 stmp.Format(_T("%.2f"), (double)(angle * 180 / NLMISC::Pi));
223 AngleMaxEdit.SetWindowText(stmp);
227 // ***************************************************************************
228 void CVegetableDensityPage::updateAngleMinFromEditText()
230 // get angles edited.
231 TCHAR stmp[256];
232 AngleMinEdit.GetWindowText(stmp, 256);
233 float angleMin;
234 NLMISC::fromString(NLMISC::tStrToUtf8(stmp), angleMin);
235 NLMISC::clamp(angleMin, -90, 90);
236 // make a sinus, because 90 => 1, and -90 =>-1
237 float cosAngleMin= (float)sin(angleMin*NLMISC::Pi/180.f);
239 // setup vegetable.
240 if(_Vegetable->getAngleType()== NL3D::CVegetable::AngleWall)
241 _Vegetable->setAngleWall(cosAngleMin, _Vegetable->getCosAngleMax());
242 else if(_Vegetable->getAngleType()== NL3D::CVegetable::AngleGround)
243 _Vegetable->setAngleGround(cosAngleMin);
245 // update views
246 updateViewAngleMin();
248 // update 3D view
249 _VegetableDlg->refreshVegetableDisplay();
251 // ***************************************************************************
252 void CVegetableDensityPage::updateAngleMaxFromEditText()
254 // get angles edited.
255 TCHAR stmp[256];
256 AngleMaxEdit.GetWindowText(stmp, 256);
257 float angleMax;
258 NLMISC::fromString(NLMISC::tStrToUtf8(stmp), angleMax);
259 NLMISC::clamp(angleMax, -90, 90);
260 // make a sinus, because 90 => 1, and -90 =>-1
261 float cosAngleMax= (float)sin(angleMax*NLMISC::Pi/180.f);
263 // setup vegetable.
264 if(_Vegetable->getAngleType()== NL3D::CVegetable::AngleWall)
265 _Vegetable->setAngleWall(_Vegetable->getCosAngleMin(), cosAngleMax);
266 else if(_Vegetable->getAngleType()== NL3D::CVegetable::AngleCeiling)
267 _Vegetable->setAngleCeiling(cosAngleMax);
269 // update views
270 updateViewAngleMax();
272 // update 3D view
273 _VegetableDlg->refreshVegetableDisplay();
278 // ***************************************************************************
279 // ***************************************************************************
280 // CVegetableDensityPage message handlers
281 // ***************************************************************************
282 // ***************************************************************************
286 // ***************************************************************************
287 BOOL CVegetableDensityPage::OnInitDialog()
289 CPropertyPage::OnInitDialog();
292 // position setup.
293 uint x= 5;
294 // Position of the density DlgBox relative to CVegetableDensityPage.
295 uint yDensity= 130;
296 // y relative to MaxDensity Group
297 uint yMaxDensity= 45;
298 // get y of MaxDensityStaticText relative to CVegetableDensityPage.
299 RECT rectParent;
300 RECT rect;
301 GetWindowRect(&rectParent);
302 MaxDensityStaticText.GetWindowRect(&rect);
303 // and apply.
304 yMaxDensity+= rect.top - rectParent.top;
307 // Init Density Dialog.
308 _DensityDlg = new CVegetableNoiseValueDlg (std::string("Density"));
309 _DensityDlg->setDefaultRangeAbs(NL_VEGETABLE_DENSITY_ABS_RANGE_MIN, NL_VEGETABLE_DENSITY_ABS_RANGE_MAX);
310 _DensityDlg->setDefaultRangeRand(NL_VEGETABLE_DENSITY_RAND_RANGE_MIN, NL_VEGETABLE_DENSITY_RAND_RANGE_MAX);
311 _DensityDlg->setDefaultRangeFreq(NL_VEGETABLE_FREQ_RANGE_MIN, NL_VEGETABLE_FREQ_RANGE_MAX);
312 _DensityDlg->init(x, yDensity, this);
315 // Init MaxDensity Dialog.
316 _MaxDensityDlg = new CDirectEditableRangeFloat (std::string("VEGET_MAX_DENSITY"), 0, NL_VEGETABLE_EDIT_DEFAULT_MAX_DENSITY,
317 "MaxDensity");
318 _MaxDensityDlg->enableLowerBound(0, false);
319 _MaxDensityDlg->init(x+10, yMaxDensity, this);
322 // Init angle sliders.
323 AngleMinSlider.SetRange(-NL_VEGETABLE_EDIT_ANGLE_SLIDER_SIZE, NL_VEGETABLE_EDIT_ANGLE_SLIDER_SIZE);
324 AngleMaxSlider.SetRange(-NL_VEGETABLE_EDIT_ANGLE_SLIDER_SIZE, NL_VEGETABLE_EDIT_ANGLE_SLIDER_SIZE);
327 // Init ShapeName
328 StaticVegetableShape.SetWindowText(_T(""));
331 return TRUE; // return TRUE unless you set the focus to a control
332 // EXCEPTION: OCX Property Pages should return FALSE
335 // ***************************************************************************
336 void CVegetableDensityPage::OnCheckMaxDensity()
338 if(MaxDensityCheckBox.GetCheck() == 1)
340 // check, restore maxDensity
341 _Vegetable->MaxDensity= _PrecMaxDensityValue;
342 // enable dlg.
343 _MaxDensityDlg->setFloat(&_Vegetable->MaxDensity, _VegetableDlg);
344 _MaxDensityDlg->EnableWindow(true);
346 else
348 // uncheck, bkup maxDenstiy
349 _PrecMaxDensityValue= _Vegetable->MaxDensity;
350 // disable dlg
351 static float dummy;
352 _MaxDensityDlg->setFloat(&dummy, _VegetableDlg);
353 _MaxDensityDlg->EnableWindow(false);
354 // and setup vegetable (disable MaxDensity).
355 _Vegetable->MaxDensity= -1;
358 // update 3D view
359 _VegetableDlg->refreshVegetableDisplay();
362 // ***************************************************************************
363 void CVegetableDensityPage::OnSelchangeComboDistType()
365 // Get the DistType, and just copy to vegetable.
366 _Vegetable->DistType= DistTypeCombo.GetCurSel();
368 // Since used to display name in selection listBox, must update the name
369 _VegetableDlg->updateCurSelVegetableName();
371 // update 3D view
372 _VegetableDlg->refreshVegetableDisplay();
375 // ***************************************************************************
376 void CVegetableDensityPage::OnRadioAngleCeiling()
378 // Enable just the AngleMax slider.
379 enableAngleEdit(IDC_RADIO_ANGLE_CEILING);
381 // Init value.
382 _Vegetable->setAngleCeiling(0);
384 // Update view Value
385 updateViewAngleMax();
387 // update 3D view
388 _VegetableDlg->refreshVegetableDisplay();
391 // ***************************************************************************
392 void CVegetableDensityPage::OnRadioAngleFloor()
394 // Enable just the AngleMin slider.
395 enableAngleEdit(IDC_RADIO_ANGLE_FLOOR);
397 // Init value.
398 _Vegetable->setAngleGround(0);
400 // Update view Value
401 updateViewAngleMin();
403 // update 3D view
404 _VegetableDlg->refreshVegetableDisplay();
407 // ***************************************************************************
408 void CVegetableDensityPage::OnRadioAngleWall()
410 // Enable both sliders.
411 enableAngleEdit(IDC_RADIO_ANGLE_WALL);
413 // Init value.
414 _Vegetable->setAngleWall(-1, 1);
416 // Update view Value
417 updateViewAngleMin();
418 updateViewAngleMax();
420 // update 3D view
421 _VegetableDlg->refreshVegetableDisplay();
424 // ***************************************************************************
425 void CVegetableDensityPage::OnReleasedcaptureSliderAngleMax(NMHDR* pNMHDR, LRESULT* pResult)
427 float angle= 90 * (float)AngleMaxSlider.GetPos() / (float)NL_VEGETABLE_EDIT_ANGLE_SLIDER_SIZE;
428 NLMISC::clamp(angle, -90, 90);
429 // make a sinus, because 90 => 1, and -90 =>-1
430 float cosAngleMax= (float)sin(angle*NLMISC::Pi/180.f);
432 // setup vegetable.
433 if(_Vegetable->getAngleType()== NL3D::CVegetable::AngleWall)
434 _Vegetable->setAngleWall(_Vegetable->getCosAngleMin(), cosAngleMax);
435 else
436 _Vegetable->setAngleCeiling(cosAngleMax);
438 // update view
439 updateViewAngleMax();
441 // update 3D view
442 _VegetableDlg->refreshVegetableDisplay();
444 *pResult = 0;
447 // ***************************************************************************
448 void CVegetableDensityPage::OnReleasedcaptureSliderAngleMin(NMHDR* pNMHDR, LRESULT* pResult)
450 float angle= 90 * (float)AngleMinSlider.GetPos() / (float)NL_VEGETABLE_EDIT_ANGLE_SLIDER_SIZE;
451 NLMISC::clamp(angle, -90, 90);
452 // make a sinus, because 90 => 1, and -90 =>-1
453 float cosAngleMin= (float)sin(angle*NLMISC::Pi/180.f);
455 // setup vegetable.
456 if(_Vegetable->getAngleType()== NL3D::CVegetable::AngleWall)
457 _Vegetable->setAngleWall(cosAngleMin, _Vegetable->getCosAngleMax());
458 else
459 _Vegetable->setAngleGround(cosAngleMin);
461 // update view
462 updateViewAngleMin();
464 // update 3D view
465 _VegetableDlg->refreshVegetableDisplay();
467 *pResult = 0;
470 // ***************************************************************************
471 void CVegetableDensityPage::OnKillfocusEditAngleMin()
473 updateAngleMinFromEditText();
475 void CVegetableDensityPage::OnKillfocusEditAngleMax()
477 updateAngleMaxFromEditText();
480 static void concatEdit2Lines(CEdit &edit)
482 const uint lineLen= 1000;
483 uint n;
484 // retrieve the 2 lines.
485 TCHAR tmp0[2*lineLen];
486 TCHAR tmp1[lineLen];
487 n= edit.GetLine(0, tmp0, lineLen); tmp0[n]= 0;
488 n= edit.GetLine(1, tmp1, lineLen); tmp1[n]= 0;
489 // concat and update the CEdit.
490 edit.SetWindowText(_tcscat(tmp0, tmp1));
493 void CVegetableDensityPage::OnChangeEditAngleMin()
495 // Trick to track "Enter" keypress: CEdit are multiline. If GetLineCount()>1, then
496 // user has press enter.
497 if(AngleMinEdit.GetLineCount()>1)
499 // must ccat the 2 first lines.
500 concatEdit2Lines(AngleMinEdit);
501 // the text (and so the lineCount) is reseted in this method.
502 updateAngleMinFromEditText();
505 void CVegetableDensityPage::OnChangeEditAngleMax()
507 // Trick to track "Enter" keypress: CEdit are multiline. If GetLineCount()>1, then
508 // user has press enter.
509 if(AngleMaxEdit.GetLineCount()>1)
511 // must ccat the 2 first lines.
512 concatEdit2Lines(AngleMinEdit);
513 // the text (and so the lineCount) is reseted in this method.
514 updateAngleMaxFromEditText();
520 // ***************************************************************************
521 void CVegetableDensityPage::OnButtonVegetableBrowse()
523 CFileDialog fd(TRUE, _T("veget"), _T("*.veget"), 0, NULL, this) ;
524 fd.m_ofn.lpstrTitle = _T("Open Vegetable Shape");
526 if (fd.DoModal() == IDOK)
528 // Add to the path
529 std::string fileName = NLMISC::tStrToUtf8(fd.GetFileName());
531 // Add search path for the .veget
532 std::string path = NLMISC::CFile::getPath(NLMISC::tStrToUtf8(fd.GetPathName()));
533 NLMISC::CPath::addSearchPath (path);
537 // verify the file can be opened.
538 NLMISC::CPath::lookup(fileName);
540 // update shapeName and view
541 _Vegetable->ShapeName = fileName;
542 StaticVegetableShape.SetWindowText(fd.GetFileName());
544 // update the name in the list-box
545 _VegetableDlg->updateCurSelVegetableName();
547 // update 3D view
548 _VegetableDlg->refreshVegetableDisplay();
550 catch (const NLMISC::EPathNotFound &ep)
552 MessageBox(nlUtf8ToTStr(ep.what()), _T("Can't open file"));