Added aqua_speed for rite geo 50 tryker
[ryzomcore.git] / nel / tools / 3d / object_viewer / particle_system_edit.cpp
blob7aa989d8b4f7cc9b0b35819a625a3c19c28c7624
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 "particle_system_edit.h"
21 #include "nel/3d/particle_system.h"
22 #include "nel/3d/particle_system_model.h"
23 #include "nel/3d/ps_color.h"
24 #include "editable_range.h"
25 #include "auto_lod_dlg.h"
26 #include "ps_global_color_dlg.h"
27 #include "choose_name.h"
28 #include "particle_tree_ctrl.h"
29 #include "particle_dlg.h"
30 #include "choose_frame_delay.h"
32 static void concatEdit2Lines(CEdit &edit)
34 const uint lineLen= 1000;
35 uint n;
36 // retrieve the 2 lines.
37 TCHAR tmp0[2*lineLen];
38 TCHAR tmp1[lineLen];
39 n= edit.GetLine(0, tmp0, lineLen); tmp0[n]= 0;
40 n= edit.GetLine(1, tmp1, lineLen); tmp1[n]= 0;
41 // concat and update the CEdit.
42 edit.SetWindowText(_tcscat(tmp0, tmp1));
46 /////////////////////////////////////////////////////////////////////////////
47 // CParticleSystemEdit dialog
49 CTimeThresholdWrapper CParticleSystemEdit::_TimeThresholdWrapper;
51 CMaxViewDistWrapper CParticleSystemEdit::_MaxViewDistWrapper;
53 CMaxNbIntegrationWrapper CParticleSystemEdit::_MaxNbIntegrationWrapper;
55 CLODRatioWrapper CParticleSystemEdit::_LODRatioWrapper;
57 CUserParamWrapper CParticleSystemEdit::_UserParamWrapper[4];
59 //=====================================================
60 CParticleSystemEdit::CParticleSystemEdit(CParticleWorkspace::CNode *ownerNode, CParticleTreeCtrl *ptc)
61 : _Node(ownerNode),
62 _TimeThresholdDlg(NULL),
63 _MaxIntegrationStepDlg(NULL),
64 _MaxViewDistDlg(NULL),
65 _LODRatioDlg(NULL),
66 _AutoLODDlg(NULL),
67 _GlobalColorDlg(NULL),
68 _ParticleTreeCtrl(ptc)
70 nlassert(ptc);
71 //{{AFX_DATA_INIT(CParticleSystemEdit)
72 m_AccurateIntegration = FALSE;
73 m_EnableSlowDown = FALSE;
74 m_DieWhenOutOfRange = FALSE;
75 m_DieWhenOutOfFrustum = FALSE;
76 m_EnableLoadBalancing = FALSE;
77 m_BypassMaxNumSteps = FALSE;
78 m_ForceLighting = FALSE;
79 m_BBoxX = _T("");
80 m_BBoxY = _T("");
81 m_BBoxZ = _T("");
82 //}}AFX_DATA_INIT
86 //=====================================================
87 CParticleSystemEdit::~CParticleSystemEdit()
89 #define REMOVE_WND(wnd) if (wnd) { wnd->DestroyWindow(); delete wnd; wnd = NULL; }
90 REMOVE_WND(_TimeThresholdDlg);
91 REMOVE_WND(_MaxIntegrationStepDlg);
92 REMOVE_WND(_MaxViewDistDlg);
93 REMOVE_WND(_LODRatioDlg);
94 REMOVE_WND(_AutoLODDlg);
95 REMOVE_WND(_GlobalColorDlg);
96 //_ParticleTreeCtrl->getParticleDlg()->getObjectViewer()->getFrameDelayDlg()->lockToPS(false);
100 //=====================================================
101 void CParticleSystemEdit::init(CWnd *pParent) // standard constructor
103 Create(CParticleSystemEdit::IDD, pParent);
105 // TODO : remove all ugly hardcoded values
107 RECT r;
109 const sint xPos = 80;
110 sint yPos = 162;
112 _MaxViewDistDlg = new CEditableRangeFloat (std::string("MAX VIEW DIST"), _Node, 0, 100.f);
113 _MaxViewDistWrapper.PS = _Node->getPSPointer();
114 _MaxViewDistDlg->enableLowerBound(0, true);
115 _MaxViewDistDlg->setWrapper(&_MaxViewDistWrapper);
116 _MaxViewDistDlg->init(87, 325, this);
118 _LODRatioDlg = new CEditableRangeFloat (std::string("LOD RATIO"), _Node, 0, 1.f);
119 _LODRatioWrapper.PS = _Node->getPSPointer();
120 _LODRatioDlg->enableLowerBound(0, true);
121 _LODRatioDlg->enableUpperBound(1, true);
122 _LODRatioDlg->setWrapper(&_LODRatioWrapper);
123 _LODRatioDlg->init(87, 357, this);
126 _TimeThresholdDlg = new CEditableRangeFloat (std::string("TIME THRESHOLD"), _Node, 0.005f, 0.3f);
127 _TimeThresholdWrapper.PS = _Node->getPSPointer();
128 _TimeThresholdDlg->enableLowerBound(0, true);
129 _TimeThresholdDlg->setWrapper(&_TimeThresholdWrapper);
130 GetDlgItem(IDC_TIME_THRESHOLD_PLACE_HOLDER)->GetWindowRect(&r);
131 ScreenToClient(&r);
132 _TimeThresholdDlg->init(r.left, r.top, this);
135 _MaxIntegrationStepDlg = new CEditableRangeUInt (std::string("MAX INTEGRATION STEPS"), _Node, 0, 4);
136 _MaxNbIntegrationWrapper.PS = _Node->getPSPointer();
137 _MaxIntegrationStepDlg->enableLowerBound(0, true);
138 _MaxIntegrationStepDlg->setWrapper(&_MaxNbIntegrationWrapper);
139 GetDlgItem(IDC_MAX_STEP_PLACE_HOLDER)->GetWindowRect(&r);
140 ScreenToClient(&r);
141 _MaxIntegrationStepDlg->init(r.left, r.top, this);
145 for (uint k = 0; k < 4; ++k)
147 _UserParamWrapper[k].PS = _Node->getPSPointer();
148 _UserParamWrapper[k].Index = k;
149 CEditableRangeFloat *erf = new CEditableRangeFloat (std::string("USER PARAM") + (char) (k + 65), NULL, 0, 1.0f);
150 erf->enableLowerBound(0, false);
151 erf->enableUpperBound(1, false);
152 pushWnd(erf);
153 erf->setWrapper(&_UserParamWrapper[k]);
154 erf->init(xPos, yPos, this);
155 yPos += 35;
159 NL3D::TAnimationTime t;
160 uint32 max;
161 bool csd;
162 bool klt;
163 _Node->getPSPointer()->getAccurateIntegrationParams(t, max, csd, klt);
165 m_PrecomputeBBoxCtrl.SetCheck(_Node->getPSPointer()->getAutoComputeBBox() ? 0 : 1);
166 ((CButton *) GetDlgItem(IDC_AUTO_BBOX))->SetCheck(_ParticleTreeCtrl->getParticleDlg()->getAutoBBox() ? 1 : 0);
168 m_EnableSlowDown = csd;
169 ((CButton *) GetDlgItem(IDC_SHARABLE))->SetCheck(_Node->getPSPointer()->isSharingEnabled());
171 m_AccurateIntegration = _Node->getPSPointer()->isAccurateIntegrationEnabled();
173 BOOL bAutoLOD = _Node->getPSPointer()->isAutoLODEnabled();
174 ((CButton *) GetDlgItem(IDC_ENABLE_AUTO_LOD))->SetCheck(bAutoLOD);
175 GetDlgItem(IDC_EDIT_AUTO_LOD)->EnableWindow(bAutoLOD);
178 /// global color
179 int bGlobalColor = _Node->getPSPointer()->getColorAttenuationScheme() != NULL ? 1 : 0;
180 ((CButton *) GetDlgItem(IDC_GLOBAL_COLOR))->SetCheck(bGlobalColor);
181 GetDlgItem(IDC_EDIT_GLOBAL_COLOR)->EnableWindow(bGlobalColor);
185 updateIntegrationParams();
186 updatePrecomputedBBoxParams();
187 updateLifeMgtPresets();
189 m_EnableLoadBalancing = _Node->getPSPointer()->isLoadBalancingEnabled();
190 _MaxIntegrationStepDlg->EnableWindow(_Node->getPSPointer()->getBypassMaxNumIntegrationSteps() ? FALSE : TRUE);
191 m_ForceLighting = _Node->getPSPointer()->getForceGlobalColorLightingFlag();
193 CString lockButtonStr;
194 lockButtonStr.LoadString(IDS_LOCK_PS);
195 GetDlgItem(IDC_LOCK_FRAME_DELAY)->SetWindowText(lockButtonStr);
197 UpdateData(FALSE);
198 ShowWindow(SW_SHOW);
203 //=====================================================
204 void CParticleSystemEdit::updateIntegrationParams()
206 BOOL ew = _Node->getPSPointer()->isAccurateIntegrationEnabled();
207 _TimeThresholdDlg->EnableWindow(ew);
208 _MaxIntegrationStepDlg->EnableWindow(ew);
209 m_EnableSlowDownCtrl.EnableWindow(ew);
213 //=====================================================
214 void CParticleSystemEdit::updateDieOnEventParams()
216 BOOL ew = _Node->getPSPointer()->getDestroyCondition() == NL3D::CParticleSystem::none ? FALSE : TRUE;
217 GetDlgItem(IDC_AUTO_DELAY)->EnableWindow(ew);
218 bool autoDelay = _Node->getPSPointer()->getAutoComputeDelayBeforeDeathConditionTest();
219 if (autoDelay)
221 ew = FALSE;
224 GetDlgItem(IDC_APPLY_AFTER_DELAY)->EnableWindow(ew);
226 CString out;
228 if (_Node->getPSPointer()->getDelayBeforeDeathConditionTest() >= 0)
230 out.Format(_T("%.2g"), _Node->getPSPointer()->getDelayBeforeDeathConditionTest());
232 else
234 out = _T("???");
237 GetDlgItem(IDC_APPLY_AFTER_DELAY)->SetWindowText(out);
238 ((CButton *) GetDlgItem(IDC_AUTO_DELAY))->SetCheck(autoDelay ? 1 : 0);
241 //=====================================================
242 void CParticleSystemEdit::OnPrecomputeBbox()
244 UpdateData();
245 _Node->getPSPointer()->setAutoComputeBBox(!_Node->getPSPointer()->getAutoComputeBBox() ? true : false);
246 if (!_Node->getPSPointer()->getAutoComputeBBox())
248 _ParticleTreeCtrl->getParticleDlg()->setAutoBBox(true);
249 _ParticleTreeCtrl->getParticleDlg()->resetAutoBBox();
250 ((CButton *) GetDlgItem(IDC_AUTO_BBOX))->SetCheck(1);
252 else
254 _ParticleTreeCtrl->getParticleDlg()->setAutoBBox(false);
255 ((CButton *) GetDlgItem(IDC_AUTO_BBOX))->SetCheck(0);
257 updatePrecomputedBBoxParams();
258 updateModifiedFlag();
261 //=====================================================
262 void CParticleSystemEdit::updatePrecomputedBBoxParams()
264 nlassert(_ParticleTreeCtrl);
265 BOOL ew = !_ParticleTreeCtrl->getParticleDlg()->getAutoBBox() && !_Node->getPSPointer()->getAutoComputeBBox();
267 m_BBoxXCtrl.EnableWindow(ew);
268 m_BBoxYCtrl.EnableWindow(ew);
269 m_BBoxZCtrl.EnableWindow(ew);
270 GetDlgItem(IDC_DEC_BBOX)->EnableWindow(!_Node->getPSPointer()->getAutoComputeBBox());
271 GetDlgItem(IDC_INC_BBOX)->EnableWindow(!_Node->getPSPointer()->getAutoComputeBBox());
272 GetDlgItem(IDC_AUTO_BBOX)->EnableWindow(!_Node->getPSPointer()->getAutoComputeBBox());
274 if (!ew)
276 m_BBoxX.Empty();
277 m_BBoxY.Empty();
278 m_BBoxZ.Empty();
280 else
282 NLMISC::CAABBox b;
283 _Node->getPSPointer()->computeBBox(b);
284 char out[128];
285 sprintf(out, "%.3g", b.getHalfSize().x); m_BBoxX = out;
286 sprintf(out, "%.3g", b.getHalfSize().y); m_BBoxY = out;
287 sprintf(out, "%.3g", b.getHalfSize().z); m_BBoxZ = out;
290 GetDlgItem(IDC_RESET_BBOX)->EnableWindow(_ParticleTreeCtrl->getParticleDlg()->getAutoBBox() && !_Node->getPSPointer()->getAutoComputeBBox());
292 UpdateData(FALSE);
295 //=====================================================
296 void CParticleSystemEdit::OnSelchangePsDieOnEvent()
298 UpdateData();
299 _Node->getPSPointer()->setDestroyCondition((NL3D::CParticleSystem::TDieCondition) m_DieOnEvent.GetCurSel());
300 updateDieOnEventParams();
301 updateModifiedFlag();
302 updateModifiedFlag();
305 //=====================================================
306 void CParticleSystemEdit::DoDataExchange(CDataExchange* pDX)
308 CDialog::DoDataExchange(pDX);
309 //{{AFX_DATA_MAP(CParticleSystemEdit)
310 DDX_Control(pDX, IDC_BYPASS_MAX_NUM_STEPS, m_BypassMaxNumStepsCtrl);
311 DDX_Control(pDX, IDC_FORCE_LIFE_TIME_UPDATE, m_ForceLifeTimeUpdate);
312 DDX_Control(pDX, IDC_DIE_WHEN_OUT_OF_FRUSTRUM, m_DieWhenOutOfFrustumCtrl);
313 DDX_Control(pDX, IDC_DIE_WHEN_OUT_OF_RANGE, m_DieWhenOutOfRangeCtrl);
314 DDX_Control(pDX, IDC_ANIM_TYPE_CTRL, m_AnimTypeCtrl);
315 DDX_Control(pDX, IDC_LIFE_MGT_PRESETS, m_PresetCtrl);
316 DDX_Control(pDX, IDC_PS_DIE_ON_EVENT, m_DieOnEvent);
317 DDX_Control(pDX, IDC_PRECOMPUTE_BBOX, m_PrecomputeBBoxCtrl);
318 DDX_Control(pDX, IDC_BB_Z, m_BBoxZCtrl);
319 DDX_Control(pDX, IDC_BB_Y, m_BBoxYCtrl);
320 DDX_Control(pDX, IDC_BB_X, m_BBoxXCtrl);
321 DDX_Control(pDX, IDC_ENABLE_SLOW_DOWN, m_EnableSlowDownCtrl);
322 DDX_Check(pDX, IDC_ACCURATE_INTEGRATION, m_AccurateIntegration);
323 DDX_Check(pDX, IDC_ENABLE_SLOW_DOWN, m_EnableSlowDown);
324 DDX_Check(pDX, IDC_DIE_WHEN_OUT_OF_RANGE, m_DieWhenOutOfRange);
325 DDX_Check(pDX, IDC_DIE_WHEN_OUT_OF_FRUSTRUM, m_DieWhenOutOfFrustum);
326 DDX_Check(pDX, IDC_ENABLE_LOAD_BALANCING, m_EnableLoadBalancing);
327 DDX_Check(pDX, IDC_BYPASS_MAX_NUM_STEPS, m_BypassMaxNumSteps);
328 DDX_Check(pDX, IDC_FORCE_GLOBAL_LIGHITNG, m_ForceLighting);
329 DDX_Text(pDX, IDC_BB_X, m_BBoxX);
330 DDX_Text(pDX, IDC_BB_Y, m_BBoxY);
331 DDX_Text(pDX, IDC_BB_Z, m_BBoxZ);
332 //}}AFX_DATA_MAP
336 BEGIN_MESSAGE_MAP(CParticleSystemEdit, CDialog)
337 //{{AFX_MSG_MAP(CParticleSystemEdit)
338 ON_BN_CLICKED(IDC_ACCURATE_INTEGRATION, OnAccurateIntegration)
339 ON_BN_CLICKED(IDC_ENABLE_SLOW_DOWN, OnEnableSlowDown)
340 ON_BN_CLICKED(IDC_PRECOMPUTE_BBOX, OnPrecomputeBbox)
341 ON_BN_CLICKED(IDC_INC_BBOX, OnIncBbox)
342 ON_BN_CLICKED(IDC_DEC_BBOX, OnDecBbox)
343 ON_BN_CLICKED(IDC_DIE_WHEN_OUT_OF_RANGE, OnDieWhenOutOfRange)
344 ON_CBN_SELCHANGE(IDC_PS_DIE_ON_EVENT, OnSelchangePsDieOnEvent)
345 ON_EN_CHANGE(IDC_APPLY_AFTER_DELAY, OnChangeApplyAfterDelay)
346 ON_BN_CLICKED(IDC_DIE_WHEN_OUT_OF_FRUSTRUM, OnDieWhenOutOfFrustum)
347 ON_CBN_SELCHANGE(IDC_LIFE_MGT_PRESETS, OnSelchangeLifeMgtPresets)
348 ON_CBN_SELCHANGE(IDC_ANIM_TYPE_CTRL, OnSelchangeAnimTypeCtrl)
349 ON_BN_CLICKED(IDC_SHARABLE, OnSharable)
350 ON_BN_CLICKED(IDC_EDIT_AUTO_LOD, OnEditAutoLod)
351 ON_BN_CLICKED(IDC_ENABLE_AUTO_LOD, OnEnableAutoLod)
352 ON_BN_CLICKED(IDC_FORCE_LIFE_TIME_UPDATE, OnForceLifeTimeUpdate)
353 ON_BN_CLICKED(IDC_EDIT_GLOBAL_COLOR, OnEditGlobalColor)
354 ON_BN_CLICKED(IDC_GLOBAL_COLOR, OnGlobalColor)
355 ON_BN_CLICKED(IDC_ENABLE_LOAD_BALANCING, OnEnableLoadBalancing)
356 ON_BN_CLICKED(IDC_GLOBAL_USER_PARAM_1, OnGlobalUserParam1)
357 ON_BN_CLICKED(IDC_GLOBAL_USER_PARAM_2, OnGlobalUserParam2)
358 ON_BN_CLICKED(IDC_GLOBAL_USER_PARAM_3, OnGlobalUserParam3)
359 ON_BN_CLICKED(IDC_GLOBAL_USER_PARAM_4, OnGlobalUserParam4)
360 ON_BN_CLICKED(IDC_BYPASS_MAX_NUM_STEPS, OnBypassMaxNumSteps)
361 ON_BN_CLICKED(IDC_FORCE_GLOBAL_LIGHITNG, OnForceGlobalLighitng)
362 ON_BN_CLICKED(IDC_AUTO_DELAY, OnAutoDelay)
363 ON_EN_CHANGE(IDC_BB_Z, OnChangeBBZ)
364 ON_EN_CHANGE(IDC_BB_X, OnChangeBBX)
365 ON_EN_CHANGE(IDC_BB_Y, OnChangeBBY)
366 ON_BN_CLICKED(IDC_AUTO_BBOX, OnAutoBbox)
367 ON_BN_CLICKED(IDC_RESET_BBOX, OnResetBBox)
368 ON_BN_CLICKED(IDC_LOCK_FRAME_DELAY, OnLockFrameDelay)
369 //}}AFX_MSG_MAP
370 END_MESSAGE_MAP()
372 /////////////////////////////////////////////////////////////////////////////
373 // CParticleSystemEdit message handlers
375 //=====================================================
376 void CParticleSystemEdit::OnAccurateIntegration()
378 UpdateData();
379 _Node->getPSPointer()->enableAccurateIntegration(m_AccurateIntegration ? true : false);
380 updateIntegrationParams();
381 updateModifiedFlag();
384 //=====================================================
385 void CParticleSystemEdit::OnEnableSlowDown()
387 UpdateData();
388 NL3D::TAnimationTime t;
389 uint32 max;
390 bool csd;
391 bool klt;
392 _Node->getPSPointer()->getAccurateIntegrationParams(t, max, csd, klt);
393 _Node->getPSPointer()->setAccurateIntegrationParams(t, max, m_EnableSlowDown ? true : false, klt);
394 updateModifiedFlag();
397 //=====================================================
398 void CParticleSystemEdit::updateBBoxFromText()
400 NLMISC::CVector h;
401 TCHAR inX[128], inY[128], inZ[128];
402 m_BBoxXCtrl.GetWindowText(inX, 128);
403 m_BBoxYCtrl.GetWindowText(inY, 128);
404 m_BBoxZCtrl.GetWindowText(inZ, 128);
406 if (_stscanf(inX, _T("%f"), &h.x) == 1
407 && _stscanf(inY, _T("%f"), &h.y) == 1
408 && _stscanf(inZ, _T("%f"), &h.z) == 1
411 NLMISC::CAABBox b;
412 b.setHalfSize(h);
413 _Node->getPSPointer()->setPrecomputedBBox(b);
415 else
417 MessageBox(_T("Invalid entry"), _T("error"), MB_OK);
421 //=====================================================
422 void CParticleSystemEdit::OnIncBbox()
424 NLMISC::CAABBox b;
425 _Node->getPSPointer()->computeBBox(b);
426 b.setHalfSize(1.1f * b.getHalfSize());
427 _Node->getPSPointer()->setPrecomputedBBox(b);
428 updatePrecomputedBBoxParams();
429 updateModifiedFlag();
432 //=====================================================
433 void CParticleSystemEdit::OnDecBbox()
435 NLMISC::CAABBox b;
436 _Node->getPSPointer()->computeBBox(b);
437 b.setHalfSize(0.9f * b.getHalfSize());
438 _Node->getPSPointer()->setPrecomputedBBox(b);
439 updatePrecomputedBBoxParams();
440 updateModifiedFlag();
443 //=====================================================
444 void CParticleSystemEdit::OnDieWhenOutOfRange()
446 UpdateData();
447 _Node->getPSPointer()->setDestroyModelWhenOutOfRange(m_DieWhenOutOfRange ? true : false);
448 updateModifiedFlag();
451 //=====================================================
452 void CParticleSystemEdit::OnDieWhenOutOfFrustum()
454 UpdateData();
455 _Node->getPSPointer()->destroyWhenOutOfFrustum(m_DieWhenOutOfFrustum ? true : false);
456 m_AnimTypeCtrl.EnableWindow(!m_DieWhenOutOfFrustum);
457 updateModifiedFlag();
460 //=====================================================
461 void CParticleSystemEdit::OnChangeApplyAfterDelay()
463 if (_Node->getPSPointer()->getAutoComputeDelayBeforeDeathConditionTest()) return;
465 TCHAR in[128];
466 GetDlgItem(IDC_APPLY_AFTER_DELAY)->GetWindowText(in, 128);
468 float value;
469 if (_stscanf(in, _T("%f"), &value) == 1)
471 if (_Node->getPSPointer()->getDelayBeforeDeathConditionTest() != value)
473 _Node->getPSPointer()->setDelayBeforeDeathConditionTest(value);
474 updateModifiedFlag();
479 //=====================================================
480 void CParticleSystemEdit::OnSelchangeLifeMgtPresets()
482 UpdateData(TRUE);
483 if (m_PresetCtrl.GetCurSel() == NL3D::CParticleSystem::SpellFX ||
484 m_PresetCtrl.GetCurSel() == NL3D::CParticleSystem::SpawnedEnvironmentFX)
486 NL3D::CPSLocatedBindable *lb;
487 if (!_Node->getPSPointer()->canFinish(&lb))
489 m_PresetCtrl.SetCurSel((int) _Node->getPSPointer()->getBehaviourType());
490 CString mess;
491 CString err;
492 err.LoadString(IDS_ERROR);
493 if (!lb)
495 mess.LoadString(IDS_NO_FINITE_DURATION);
496 MessageBox((LPCTSTR) mess, (LPCTSTR) err, MB_ICONEXCLAMATION);
498 else
500 mess.LoadString(IDS_NO_FINITE_DURATION_FOR_OBJ);
501 mess += lb->getName().c_str();
502 MessageBox((LPCTSTR) mess, (LPCTSTR) err, MB_ICONEXCLAMATION);
504 return;
507 _Node->getPSPointer()->activatePresetBehaviour((NL3D::CParticleSystem::TPresetBehaviour) m_PresetCtrl.GetCurSel());
508 updateLifeMgtPresets();
509 updateModifiedFlag();
512 //=====================================================
513 void CParticleSystemEdit::OnSelchangeAnimTypeCtrl()
515 UpdateData(TRUE);
516 _Node->getPSPointer()->setAnimType((NL3D::CParticleSystem::TAnimType) m_AnimTypeCtrl.GetCurSel());
517 updateModifiedFlag();
520 //=====================================================
521 void CParticleSystemEdit::updateLifeMgtPresets()
523 m_PresetCtrl.SetCurSel((int) _Node->getPSPointer()->getBehaviourType());
524 m_DieWhenOutOfRange = _Node->getPSPointer()->getDestroyModelWhenOutOfRange();
525 m_DieWhenOutOfFrustum = _Node->getPSPointer()->doesDestroyWhenOutOfFrustum();
526 m_BypassMaxNumSteps = _Node->getPSPointer()->getBypassMaxNumIntegrationSteps();
527 m_DieOnEvent.SetCurSel((int) _Node->getPSPointer()->getDestroyCondition());
528 m_AnimTypeCtrl.SetCurSel((int) _Node->getPSPointer()->getAnimType());
529 updateDieOnEventParams();
531 NL3D::TAnimationTime t;
532 uint32 max;
533 bool csd;
534 bool klt;
535 _Node->getPSPointer()->getAccurateIntegrationParams(t, max, csd, klt);
536 ((CButton *) GetDlgItem(IDC_FORCE_LIFE_TIME_UPDATE))->SetCheck(klt);
538 BOOL bEnable = _Node->getPSPointer()->getBehaviourType() == NL3D::CParticleSystem::UserBehaviour ? TRUE : FALSE;
540 m_DieWhenOutOfRangeCtrl.EnableWindow(bEnable);
541 m_DieWhenOutOfFrustumCtrl.EnableWindow(bEnable);
542 m_DieOnEvent.EnableWindow(bEnable);
543 m_AnimTypeCtrl.EnableWindow(bEnable);
544 m_ForceLifeTimeUpdate.EnableWindow(bEnable);
545 m_BypassMaxNumStepsCtrl.EnableWindow(bEnable);
546 _MaxIntegrationStepDlg->EnableWindow(_Node->getPSPointer()->getBypassMaxNumIntegrationSteps() ? FALSE : TRUE);
548 UpdateData(FALSE);
553 //=====================================================
554 void CParticleSystemEdit::OnSharable()
556 bool shared = ((CButton *) GetDlgItem(IDC_SHARABLE))->GetCheck() != 0;
557 _Node->getPSPointer()->enableSharing(shared);
558 updateModifiedFlag();
561 //=====================================================
562 void CParticleSystemEdit::OnEditAutoLod()
564 GetDlgItem(IDC_EDIT_AUTO_LOD)->EnableWindow(FALSE);
565 GetDlgItem(IDC_ENABLE_AUTO_LOD)->EnableWindow(FALSE);
566 GetDlgItem(IDC_SHARABLE)->EnableWindow(FALSE);
567 nlassert(_AutoLODDlg == NULL);
568 CAutoLODDlg *autoLODDlg = new CAutoLODDlg(_Node, _Node->getPSPointer(), this);
569 autoLODDlg->init(this);
570 _AutoLODDlg = autoLODDlg;
573 //=====================================================
574 void CParticleSystemEdit::childPopupClosed(CWnd *child)
576 if (child == _AutoLODDlg)
578 GetDlgItem(IDC_EDIT_AUTO_LOD)->EnableWindow(TRUE);
579 GetDlgItem(IDC_ENABLE_AUTO_LOD)->EnableWindow(TRUE);
580 GetDlgItem(IDC_SHARABLE)->EnableWindow(TRUE);
581 REMOVE_WND(_AutoLODDlg);
583 else
584 if (child == _GlobalColorDlg)
586 GetDlgItem(IDC_GLOBAL_COLOR)->EnableWindow(TRUE);
587 GetDlgItem(IDC_EDIT_GLOBAL_COLOR)->EnableWindow(TRUE);
588 REMOVE_WND(_GlobalColorDlg);
593 //=====================================================
594 void CParticleSystemEdit::OnEnableAutoLod()
596 BOOL bEnable = ((CButton *) GetDlgItem(IDC_ENABLE_AUTO_LOD))->GetCheck() != 0;
597 GetDlgItem(IDC_EDIT_AUTO_LOD)->EnableWindow(bEnable);
598 _Node->getPSPointer()->enableAutoLOD(bEnable ? true : false /* performance warning */);
599 updateModifiedFlag();
602 ///=====================================================================
603 void CParticleSystemEdit::OnEditGlobalColor()
605 nlassert(!_GlobalColorDlg);
606 GetDlgItem(IDC_GLOBAL_COLOR)->EnableWindow(FALSE);
607 GetDlgItem(IDC_EDIT_GLOBAL_COLOR)->EnableWindow(FALSE);
608 CPSGlobalColorDlg *gcd = new CPSGlobalColorDlg(_Node, this, this);
609 gcd->init(this);
610 _GlobalColorDlg = gcd;
611 updateModifiedFlag();
614 ///=====================================================================
615 void CParticleSystemEdit::OnGlobalColor()
617 /// if the system hasn't a global color scheme, add one.
618 if (_Node->getPSPointer()->getColorAttenuationScheme() == NULL)
620 static const NLMISC::CRGBA grad[] = { NLMISC::CRGBA::White, NLMISC::CRGBA::Black };
621 _Node->getPSPointer()->setColorAttenuationScheme(new NL3D::CPSColorGradient(grad, 2, 64, 1.f));
622 GetDlgItem(IDC_EDIT_GLOBAL_COLOR)->EnableWindow(TRUE);
624 else
626 _Node->getPSPointer()->setColorAttenuationScheme(NULL);
627 GetDlgItem(IDC_EDIT_GLOBAL_COLOR)->EnableWindow(FALSE);
629 updateModifiedFlag();
633 /////////////////////////////
634 // WRAPPERS IMPLEMENTATION //
635 /////////////////////////////
637 //=====================================================
638 float CTimeThresholdWrapper::get(void) const
640 NL3D::TAnimationTime t;
641 uint32 max;
642 bool csd;
643 bool klt;
644 PS->getAccurateIntegrationParams(t, max, csd, klt);
645 return t;
648 //=====================================================
649 void CTimeThresholdWrapper::set(const float &tt)
651 NL3D::TAnimationTime t;
652 uint32 max;
653 bool csd;
654 bool klt;
655 PS->getAccurateIntegrationParams(t, max, csd, klt);
656 PS->setAccurateIntegrationParams(tt, max, csd, klt);
660 //=====================================================
661 uint32 CMaxNbIntegrationWrapper::get(void) const
663 NL3D::TAnimationTime t;
664 uint32 max;
665 bool csd;
666 bool klt;
667 PS->getAccurateIntegrationParams(t, max, csd, klt);
668 return max;
671 //=====================================================
672 void CMaxNbIntegrationWrapper::set(const uint32 &nmax)
674 NL3D::TAnimationTime t;
675 uint32 max;
676 bool csd;
677 bool klt;
678 PS->getAccurateIntegrationParams(t, max, csd, klt);
679 PS->setAccurateIntegrationParams(t, nmax, csd, klt);
682 //=====================================================
683 float CUserParamWrapper::get(void) const
685 return PS->getUserParam(Index);
688 //=====================================================
689 void CUserParamWrapper::set(const float &v)
691 PS->setUserParam(Index, v);
694 //=====================================================
695 float CMaxViewDistWrapper::get(void) const
697 return PS->getMaxViewDist();
700 //=====================================================
701 void CMaxViewDistWrapper::set(const float &d)
703 PS->setMaxViewDist(d);
706 //=====================================================
707 float CLODRatioWrapper::get(void) const
709 return PS->getLODRatio();
712 //=====================================================
713 void CLODRatioWrapper::set(const float &v)
715 PS->setLODRatio(v);
718 //=====================================================
719 void CParticleSystemEdit::OnForceLifeTimeUpdate()
721 NL3D::TAnimationTime t;
722 uint32 max;
723 bool csd;
724 bool klt;
725 _Node->getPSPointer()->getAccurateIntegrationParams(t, max, csd, klt);
726 klt = ((CButton *) GetDlgItem(IDC_FORCE_LIFE_TIME_UPDATE))->GetCheck() != 0;
727 _Node->getPSPointer()->setAccurateIntegrationParams(t, max, csd, klt);
728 updateModifiedFlag();
731 //=====================================================
732 void CParticleSystemEdit::OnEnableLoadBalancing()
734 UpdateData(TRUE);
735 if (m_EnableLoadBalancing == FALSE)
737 int result = MessageBox(_T("Are you sure ?"), _T("Load balancing on/off"), MB_OKCANCEL);
738 if (result == IDOK)
740 _Node->getPSPointer()->enableLoadBalancing(false);
742 else
744 m_EnableLoadBalancing = TRUE;
747 else
749 _Node->getPSPointer()->enableLoadBalancing(false);
751 UpdateData(FALSE);
752 updateModifiedFlag();
755 //=====================================================
756 static void chooseGlobalUserParam(uint userParam, NL3D::CParticleSystem *ps, CWnd *parent)
758 nlassert(ps);
759 CChooseName cn(!ps->getGlobalValueName(userParam).empty() ? ps->getGlobalValueName(userParam).c_str() : "", parent);
760 if (cn.DoModal() == IDOK)
762 ps->bindGlobalValueToUserParam(cn.getName().c_str(), userParam);
766 //=====================================================
767 void CParticleSystemEdit::OnGlobalUserParam1()
769 nlassert(_Node->getPSPointer());
770 chooseGlobalUserParam(0, _Node->getPSPointer(), this);
773 //=====================================================
774 void CParticleSystemEdit::OnGlobalUserParam2()
776 chooseGlobalUserParam(1, _Node->getPSPointer(), this);
777 updateModifiedFlag();
780 //=====================================================
781 void CParticleSystemEdit::OnGlobalUserParam3()
783 chooseGlobalUserParam(2, _Node->getPSPointer(), this);
784 updateModifiedFlag();
787 //=====================================================
788 void CParticleSystemEdit::OnGlobalUserParam4()
790 chooseGlobalUserParam(3, _Node->getPSPointer(), this);
791 updateModifiedFlag();
794 //=====================================================
795 void CParticleSystemEdit::OnBypassMaxNumSteps()
797 UpdateData(TRUE);
798 if (m_BypassMaxNumSteps && !_Node->getPSPointer()->canFinish())
800 MessageBox(_T("The system must have a finite duration for this setting! Please check that."), _T("error"), MB_ICONEXCLAMATION);
801 return;
803 _Node->getPSPointer()->setBypassMaxNumIntegrationSteps(m_BypassMaxNumSteps != FALSE);
804 _MaxIntegrationStepDlg->EnableWindow(_Node->getPSPointer()->getBypassMaxNumIntegrationSteps() ? FALSE : TRUE);
805 updateModifiedFlag();
808 //=====================================================
809 void CParticleSystemEdit::OnForceGlobalLighitng()
811 UpdateData(TRUE);
812 _Node->getPSPointer()->setForceGlobalColorLightingFlag(m_ForceLighting != 0);
813 if (_Node && _Node->getPSModel())
815 _Node->getPSModel()->touchLightableState();
817 updateModifiedFlag();
820 //=====================================================
821 void CParticleSystemEdit::OnAutoDelay()
823 UpdateData(TRUE);
824 bool autoDelay = ((CButton *) GetDlgItem(IDC_AUTO_DELAY))->GetCheck() != 0;
825 _Node->getPSPointer()->setAutoComputeDelayBeforeDeathConditionTest(autoDelay);
826 GetDlgItem(IDC_APPLY_AFTER_DELAY)->EnableWindow(autoDelay ? FALSE : TRUE);
827 updateModifiedFlag();
830 //=====================================================
831 void CParticleSystemEdit::refresh()
833 updatePrecomputedBBoxParams();
834 updateIntegrationParams();
835 updateDieOnEventParams();
836 updateLifeMgtPresets();
839 //=====================================================
840 void CParticleSystemEdit::OnChangeBBX()
842 UpdateData();
843 // Trick to track "Enter" keypress: CEdit are multiline. If GetLineCount()>1, then
844 // user has press enter.
845 if(m_BBoxXCtrl.GetLineCount()>1)
847 // must ccat 2 lines of the CEdit.
848 concatEdit2Lines(m_BBoxXCtrl);
849 m_BBoxXCtrl.GetWindowText(m_BBoxX);
850 updateBBoxFromText();
851 updateModifiedFlag();
855 //=====================================================
856 void CParticleSystemEdit::OnChangeBBY()
858 UpdateData();
859 // Trick to track "Enter" keypress: CEdit are multiline. If GetLineCount()>1, then
860 // user has press enter.
861 if(m_BBoxYCtrl.GetLineCount()>1)
863 // must ccat 2 lines of the CEdit.
864 concatEdit2Lines(m_BBoxYCtrl);
865 m_BBoxYCtrl.GetWindowText(m_BBoxY);
866 updateBBoxFromText();
867 updateModifiedFlag();
871 //=====================================================
872 void CParticleSystemEdit::OnChangeBBZ()
874 UpdateData();
875 // Trick to track "Enter" keypress: CEdit are multiline. If GetLineCount()>1, then
876 // user has press enter.
877 if(m_BBoxZCtrl.GetLineCount()>1)
879 // must ccat 2 lines of the CEdit.
880 concatEdit2Lines(m_BBoxZCtrl);
881 m_BBoxZCtrl.GetWindowText(m_BBoxZ);
882 updateBBoxFromText();
883 updateModifiedFlag();
887 //=====================================================
888 void CParticleSystemEdit::OnAutoBbox()
890 nlassert(_ParticleTreeCtrl);
891 _ParticleTreeCtrl->getParticleDlg()->setAutoBBox(!_ParticleTreeCtrl->getParticleDlg()->getAutoBBox());
892 updatePrecomputedBBoxParams();
893 updateModifiedFlag();
896 //=====================================================
897 void CParticleSystemEdit::OnResetBBox()
899 nlassert(_ParticleTreeCtrl);
900 _ParticleTreeCtrl->getParticleDlg()->resetAutoBBox();
901 updateModifiedFlag();
904 //=====================================================
905 void CParticleSystemEdit::OnLockFrameDelay()
907 bool locked = !_ParticleTreeCtrl->getParticleDlg()->getObjectViewer()->getFrameDelayDlg()->isLockedToPS();
908 _ParticleTreeCtrl->getParticleDlg()->getObjectViewer()->getFrameDelayDlg()->lockToPS(locked);
909 CString buttonStr;
910 buttonStr.LoadString(locked ? IDS_UNLOCK_PS : IDS_LOCK_PS);
911 GetDlgItem(IDC_LOCK_FRAME_DELAY)->SetWindowText(buttonStr);