Added aqua_speed for rite geo 50 tryker
[ryzomcore.git] / nel / tools / 3d / object_viewer / emitter_dlg.cpp
blob50a60782b79ba0eb21de455d39a4d382eb96decb
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 #include "std_afx.h"
21 #include "object_viewer.h"
22 #include "emitter_dlg.h"
23 #include "direction_attr.h"
24 #include "particle_tree_ctrl.h"
25 #include "particle_dlg.h"
27 #include "nel/3d/particle_system.h"
31 /////////////////////////////////////////////////////////////////////////////
32 // CEmitterDlg dialog
35 CEmitterDlg::CEmitterDlg(CParticleWorkspace::CNode *ownerNode, NL3D::CPSEmitter *emitter, CParticleDlg *particleDlg)
36 : _Node(ownerNode),
37 _Emitter(emitter),
38 _PeriodDlg(NULL),
39 _GenNbDlg(NULL),
40 _StrenghtModulateDlg(NULL),
41 _SpeedInheritanceFactorDlg(NULL),
42 _ParticleDlg(particleDlg)
44 nlassert(_Emitter);
45 nlassert(_ParticleDlg);
46 //{{AFX_DATA_INIT(CEmitterDlg)
47 m_ConsistentEmission = _Emitter->isConsistentEmissionEnabled();
48 m_BypassAutoLOD = FALSE;
49 //}}AFX_DATA_INIT
52 CEmitterDlg::~CEmitterDlg()
54 _PeriodDlg->DestroyWindow();
55 _GenNbDlg->DestroyWindow();
56 _StrenghtModulateDlg->DestroyWindow();
57 _SpeedInheritanceFactorDlg->DestroyWindow();
58 _DelayedEmissionDlg->DestroyWindow();
59 _MaxEmissionCountDlg->DestroyWindow();
61 delete _PeriodDlg;
62 delete _GenNbDlg;
63 delete _StrenghtModulateDlg;
64 delete _SpeedInheritanceFactorDlg;
65 delete _DelayedEmissionDlg;
66 delete _MaxEmissionCountDlg;
70 void CEmitterDlg::init(CWnd* pParent)
72 Create(IDD_EMITTER_DIALOG, pParent);
73 // fill the emitted type combo box with all the types of located
74 initEmittedType();
75 m_EmissionTypeCtrl.SetCurSel((int) _Emitter->getEmissionType() );
76 ShowWindow(SW_SHOW);
77 UpdateData(FALSE);
80 void CEmitterDlg::initEmittedType()
82 m_EmittedTypeCtrl.ResetContent();
83 NL3D::CParticleSystem *ps = _Emitter->getOwner()->getOwner();
84 uint nbLocated = ps->getNbProcess();
85 m_EmittedTypeCtrl.InitStorage(nbLocated, 16);
86 for (uint k = 0; k < nbLocated; ++k)
88 NL3D::CPSLocated *loc = dynamic_cast<NL3D::CPSLocated *>(ps->getProcess(k));
89 if (loc) // is this a located
91 m_EmittedTypeCtrl.AddString(nlUtf8ToTStr(loc->getName()));
92 _LocatedList.push_back(loc);
93 if (loc == _Emitter->getEmittedType())
95 m_EmittedTypeCtrl.SetCurSel(k);
101 void CEmitterDlg::DoDataExchange(CDataExchange* pDX)
103 CDialog::DoDataExchange(pDX);
104 //{{AFX_DATA_MAP(CEmitterDlg)
105 DDX_Control(pDX, IDC_DIRECTION_MODE, m_DirectionModeCtrl);
106 DDX_Control(pDX, IDC_TYPE_OF_EMISSION, m_EmissionTypeCtrl);
107 DDX_Control(pDX, IDC_EMITTED_TYPE, m_EmittedTypeCtrl);
108 DDX_Check(pDX, IDC_CONSISTENT_EMISSION, m_ConsistentEmission);
109 DDX_Check(pDX, IDC_BYPASS_AUTOLOD, m_BypassAutoLOD);
110 //}}AFX_DATA_MAP
114 BEGIN_MESSAGE_MAP(CEmitterDlg, CDialog)
115 //{{AFX_MSG_MAP(CEmitterDlg)
116 ON_CBN_SELCHANGE(IDC_EMITTED_TYPE, OnSelchangeEmittedType)
117 ON_CBN_SELCHANGE(IDC_TYPE_OF_EMISSION, OnSelchangeTypeOfEmission)
118 ON_BN_CLICKED(IDC_CONSISTENT_EMISSION, OnConsistentEmission)
119 ON_BN_CLICKED(IDC_BYPASS_AUTOLOD, OnBypassAutoLOD)
120 ON_CBN_SELCHANGE(IDC_DIRECTION_MODE, OnSelchangeDirectionMode)
121 //}}AFX_MSG_MAP
122 END_MESSAGE_MAP()
124 /////////////////////////////////////////////////////////////////////////////
125 // CEmitterDlg message handlers
127 void CEmitterDlg::OnSelchangeEmittedType()
129 UpdateData();
130 uint k = m_EmittedTypeCtrl.GetCurSel();
131 if (!_Emitter->setEmittedType(_LocatedList[k]))
133 if (_Emitter->getOwner()->getOwner()->getBehaviourType() == NL3D::CParticleSystem::SpellFX || _Emitter->getOwner()->getOwner()->getBypassMaxNumIntegrationSteps())
135 MessageBox(_T("Can't perform operation : the system is flagged with 'No max nb steps' or uses the preset 'Spell FX', and thus, should have a finite duration. This operation create a loop in the system, and so is forbidden."), _T("Error"), MB_ICONEXCLAMATION);
137 else
139 MessageBox(_T("Loops with emitters are forbidden."), _T("Error"), MB_ICONEXCLAMATION);
141 initEmittedType();
143 _ParticleDlg->StartStopDlg->resetAutoCount(_Node);
144 updateModifiedFlag();
147 void CEmitterDlg::OnSelchangeTypeOfEmission()
149 UpdateData();
150 if (!_Emitter->setEmissionType((NL3D::CPSEmitter::TEmissionType) m_EmissionTypeCtrl.GetCurSel()))
152 CString mess;
153 mess.LoadString(IDS_PS_NO_FINITE_DURATION);
154 CString errorStr;
155 errorStr.LoadString(IDS_ERROR);
156 MessageBox((LPCTSTR) mess, (LPCTSTR) errorStr, MB_ICONEXCLAMATION);
157 m_EmissionTypeCtrl.SetCurSel((int) _Emitter->getEmissionType());
160 updatePeriodDlg();
161 _ParticleDlg->StartStopDlg->resetAutoCount(_Node);
162 updateModifiedFlag();
166 void CEmitterDlg::updatePeriodDlg(void)
168 BOOL bEnable = _Emitter->getEmissionType() == NL3D::CPSEmitter::regular;
169 _PeriodDlg->EnableWindow(bEnable);
170 _DelayedEmissionDlg->EnableWindow(bEnable);
171 _MaxEmissionCountDlg->EnableWindow(bEnable);
174 BOOL CEmitterDlg::OnInitDialog()
176 CDialog::OnInitDialog();
178 RECT r;
180 GetDlgItem(IDC_SPEED_INHERITANCE_FACTOR_FRAME)->GetWindowRect(&r);
181 ScreenToClient(&r);
182 _SpeedInheritanceFactorDlg = new CEditableRangeFloat("SPEED_INHERITANCE_FACTOR", _Node, -1.f, 1.f);
183 _SpeedInheritanceFactorWrapper.E = _Emitter;
184 _SpeedInheritanceFactorDlg->setWrapper(&_SpeedInheritanceFactorWrapper);
185 _SpeedInheritanceFactorDlg->init(r.left, r.top, this);
187 GetDlgItem(IDC_DELAYED_EMISSION_FRAME)->GetWindowRect(&r);
188 ScreenToClient(&r);
189 _DelayedEmissionDlg = new CEditableRangeFloat("DELAYED_EMISSION", _Node, 0.f, 10.f);
190 _DelayedEmissionDlg->enableLowerBound(0.f, false);
191 _DelayedEmissionWrapper.E = _Emitter;
192 _DelayedEmissionWrapper.Node = _Node;
193 _DelayedEmissionWrapper.SSPS = _ParticleDlg->StartStopDlg;
194 _DelayedEmissionDlg->setWrapper(&_DelayedEmissionWrapper);
195 _DelayedEmissionDlg->init(r.left, r.top, this);
197 GetDlgItem(IDC_MAX_EMISSION_COUNT_FRAME)->GetWindowRect(&r);
198 ScreenToClient(&r);
199 _MaxEmissionCountDlg = new CEditableRangeUInt("MAX_EMISSION_COUNT", _Node, 0, 100);
200 _MaxEmissionCountDlg->enableUpperBound(256, false);
201 _MaxEmissionCountWrapper.E = _Emitter;
202 _MaxEmissionCountWrapper.Node = _Node;
203 _MaxEmissionCountWrapper.SSPS = _ParticleDlg->StartStopDlg;
204 _MaxEmissionCountWrapper.HWnd = (HWND) (*this);
205 _MaxEmissionCountDlg->setWrapper(&_MaxEmissionCountWrapper);
206 _MaxEmissionCountDlg->init(r.left, r.top, this);
207 _MaxEmissionCountWrapper.MaxEmissionCountDlg = _MaxEmissionCountDlg;
211 uint posX = 13;
212 uint posY = r.bottom + 5;
214 // setup the dialog for the period of emission edition
216 _PeriodDlg = new CAttribDlgFloat("EMISSION_PERIOD", _Node, 0.f, 2.f);
217 _PeriodWrapper.E = _Emitter;
218 _PeriodWrapper.Node = _Node;
219 _PeriodWrapper.SSPS = _ParticleDlg->StartStopDlg;
220 _PeriodDlg->setWrapper(&_PeriodWrapper);
221 _PeriodDlg->setSchemeWrapper(&_PeriodWrapper);
222 HBITMAP bmh = LoadBitmap(::AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_EMISSION_PERIOD));
223 _PeriodDlg->init(bmh, posX, posY, this);
224 posY += 120;
226 // setup the dialog that helps tuning the number of particle being emitted at a time
228 _GenNbDlg = new CAttribDlgUInt("EMISSION_GEN_NB", _Node, 1, 11);
229 _GenNbWrapper.E = _Emitter;
230 _GenNbWrapper.Node = _Node;
231 _GenNbWrapper.SSPS = _ParticleDlg->StartStopDlg;
232 _GenNbDlg->setWrapper(&_GenNbWrapper);
233 _GenNbDlg->setSchemeWrapper(&_GenNbWrapper);
234 bmh = LoadBitmap(::AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_EMISSION_QUANTITY));
235 _GenNbDlg->init(bmh, posX, posY, this);
236 posY += 120;
238 if (dynamic_cast<NL3D::CPSModulatedEmitter *>(_Emitter))
240 _StrenghtModulateDlg = new CAttribDlgFloat("EMISSION_GEN_NB", _Node, 1, 11);
241 _ModulatedStrenghtWrapper.E = dynamic_cast<NL3D::CPSModulatedEmitter *>(_Emitter);
242 _StrenghtModulateDlg->setWrapper(&_ModulatedStrenghtWrapper);
243 _StrenghtModulateDlg->setSchemeWrapper(&_ModulatedStrenghtWrapper);
244 bmh = LoadBitmap(::AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_MODULATE_STRENGHT));
245 _StrenghtModulateDlg->init(bmh, posX, posY, this);
246 posY += 120;
249 // deals with emitters that have a direction
250 if (dynamic_cast<NL3D::CPSDirection *>(_Emitter))
252 CDirectionAttr *da = new CDirectionAttr(std::string("DIRECTION"));
253 pushWnd(da);
254 _DirectionWrapper.E = dynamic_cast<NL3D::CPSDirection *>(_Emitter);
255 da->setWrapper(&_DirectionWrapper);
256 da->setDirectionWrapper(dynamic_cast<NL3D::CPSDirection *>(_Emitter));
257 da->init(posX, posY, this);
258 da->GetClientRect(&r);
259 posY += r.bottom;
262 // radius for conic emitter
263 if (dynamic_cast<NL3D::CPSEmitterConic *>(_Emitter))
265 CEditableRangeFloat *ecr = new CEditableRangeFloat(std::string("CONIC EMITTER RADIUS"), _Node, 0.1f, 2.1f);
266 pushWnd(ecr);
267 _ConicEmitterRadiusWrapper.E = dynamic_cast<NL3D::CPSEmitterConic *>(_Emitter);
268 ecr->setWrapper(&_ConicEmitterRadiusWrapper);
269 ecr->init(posX + 80, posY, this);
271 CStatic *s = new CStatic;
272 pushWnd(s);
273 s->Create(_T("Radius :"), SS_LEFT, CRect(posX, posY + 10 , posX + 70, posY + 32), this);
274 s->SetFont(CFont::FromHandle((HFONT) GetStockObject(DEFAULT_GUI_FONT)));
275 s->ShowWindow(SW_SHOW);
277 ecr->GetClientRect(&r);
278 posY += r.bottom;
281 if (_Emitter->isSpeedBasisEmissionEnabled())
283 m_DirectionModeCtrl.SetCurSel((int)AlignOnEmitterDirection);
285 else if (!_Emitter->isUserMatrixModeForEmissionDirectionEnabled())
287 m_DirectionModeCtrl.SetCurSel((int)Default);
289 else if (_Emitter->getUserMatrixModeForEmissionDirection() == NL3D::PSFXWorldMatrix)
291 m_DirectionModeCtrl.SetCurSel((int)LocalToSystem);
293 else if (_Emitter->getUserMatrixModeForEmissionDirection() == NL3D::PSIdentityMatrix)
295 m_DirectionModeCtrl.SetCurSel((int)InWorld);
297 else if (_Emitter->getUserMatrixModeForEmissionDirection() == NL3D::PSUserMatrix)
299 m_DirectionModeCtrl.SetCurSel((int)LocalToFatherSkeleton);
301 else
303 nlassert(0);
306 updatePeriodDlg();
308 // bypass auto LOD
309 nlassert(_Emitter->getOwner() && _Emitter->getOwner()->getOwner());
310 NL3D::CParticleSystem &ps = *_Emitter->getOwner()->getOwner();
311 CButton *button = (CButton *) GetDlgItem(IDC_BYPASS_AUTOLOD);
312 if (ps.isAutoLODEnabled() && !ps.isSharingEnabled())
314 button->EnableWindow(TRUE);
315 m_BypassAutoLOD = _Emitter->getBypassAutoLOD();
317 else
319 button->EnableWindow(FALSE);
322 return TRUE; // return TRUE unless you set the focus to a control
323 // EXCEPTION: OCX Property Pages should return FALSE
326 void CEmitterDlg::OnConsistentEmission()
328 UpdateData();
329 _Emitter->enableConsistenEmission(m_ConsistentEmission != 0 ? true : false /* VC6 warning */);
330 updateModifiedFlag();
331 UpdateData(TRUE);
334 void CEmitterDlg::OnBypassAutoLOD()
336 UpdateData();
337 _Emitter->setBypassAutoLOD(m_BypassAutoLOD ? true : false);
338 UpdateData(TRUE);
339 updateModifiedFlag();
342 void CEmitterDlg::CMaxEmissionCountWrapper::set(const uint32 &count)
344 if (!E->setMaxEmissionCount((uint8) count))
346 CString mess;
347 mess.LoadString(IDS_PS_NO_FINITE_DURATION);
348 CString errorStr;
349 errorStr.LoadString(IDS_ERROR);
350 ::MessageBox(HWnd, (LPCTSTR) mess, (LPCTSTR) errorStr, MB_ICONEXCLAMATION);
351 MaxEmissionCountDlg->updateValueFromReader();
353 SSPS->resetAutoCount(Node);
356 void CEmitterDlg::OnSelchangeDirectionMode()
358 UpdateData();
359 nlassert(_Emitter);
360 switch(m_DirectionModeCtrl.GetCurSel())
362 case Default:
363 _Emitter->enableSpeedBasisEmission(false);
364 _Emitter->enableUserMatrixModeForEmissionDirection(false);
365 break;
366 case AlignOnEmitterDirection:
367 _Emitter->enableSpeedBasisEmission(true);
368 _Emitter->enableUserMatrixModeForEmissionDirection(false);
369 break;
370 case InWorld:
371 _Emitter->enableSpeedBasisEmission(false);
372 _Emitter->enableUserMatrixModeForEmissionDirection(true);
373 _Emitter->setUserMatrixModeForEmissionDirection(NL3D::PSIdentityMatrix);
374 break;
375 case LocalToSystem:
376 _Emitter->enableSpeedBasisEmission(false);
377 _Emitter->enableUserMatrixModeForEmissionDirection(true);
378 _Emitter->setUserMatrixModeForEmissionDirection(NL3D::PSFXWorldMatrix);
379 break;
380 case LocalToFatherSkeleton:
381 _Emitter->enableSpeedBasisEmission(false);
382 _Emitter->enableUserMatrixModeForEmissionDirection(true);
383 _Emitter->setUserMatrixModeForEmissionDirection(NL3D::PSUserMatrix);
384 break;
386 updateModifiedFlag();
387 UpdateData(FALSE);