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 "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;
36 // retrieve the 2 lines.
37 TCHAR tmp0
[2*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
)
62 _TimeThresholdDlg(NULL
),
63 _MaxIntegrationStepDlg(NULL
),
64 _MaxViewDistDlg(NULL
),
67 _GlobalColorDlg(NULL
),
68 _ParticleTreeCtrl(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
;
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
109 const sint xPos
= 80;
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
);
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
);
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);
153 erf
->setWrapper(&_UserParamWrapper
[k
]);
154 erf
->init(xPos
, yPos
, this);
159 NL3D::TAnimationTime t
;
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
);
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
);
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();
224 GetDlgItem(IDC_APPLY_AFTER_DELAY
)->EnableWindow(ew
);
228 if (_Node
->getPSPointer()->getDelayBeforeDeathConditionTest() >= 0)
230 out
.Format(_T("%.2g"), _Node
->getPSPointer()->getDelayBeforeDeathConditionTest());
237 GetDlgItem(IDC_APPLY_AFTER_DELAY
)->SetWindowText(out
);
238 ((CButton
*) GetDlgItem(IDC_AUTO_DELAY
))->SetCheck(autoDelay
? 1 : 0);
241 //=====================================================
242 void CParticleSystemEdit::OnPrecomputeBbox()
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);
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());
283 _Node
->getPSPointer()->computeBBox(b
);
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());
295 //=====================================================
296 void CParticleSystemEdit::OnSelchangePsDieOnEvent()
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
);
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
)
372 /////////////////////////////////////////////////////////////////////////////
373 // CParticleSystemEdit message handlers
375 //=====================================================
376 void CParticleSystemEdit::OnAccurateIntegration()
379 _Node
->getPSPointer()->enableAccurateIntegration(m_AccurateIntegration
? true : false);
380 updateIntegrationParams();
381 updateModifiedFlag();
384 //=====================================================
385 void CParticleSystemEdit::OnEnableSlowDown()
388 NL3D::TAnimationTime t
;
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()
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
413 _Node
->getPSPointer()->setPrecomputedBBox(b
);
417 MessageBox(_T("Invalid entry"), _T("error"), MB_OK
);
421 //=====================================================
422 void CParticleSystemEdit::OnIncBbox()
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()
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()
447 _Node
->getPSPointer()->setDestroyModelWhenOutOfRange(m_DieWhenOutOfRange
? true : false);
448 updateModifiedFlag();
451 //=====================================================
452 void CParticleSystemEdit::OnDieWhenOutOfFrustum()
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;
466 GetDlgItem(IDC_APPLY_AFTER_DELAY
)->GetWindowText(in
, 128);
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()
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());
492 err
.LoadString(IDS_ERROR
);
495 mess
.LoadString(IDS_NO_FINITE_DURATION
);
496 MessageBox((LPCTSTR
) mess
, (LPCTSTR
) err
, MB_ICONEXCLAMATION
);
500 mess
.LoadString(IDS_NO_FINITE_DURATION_FOR_OBJ
);
501 mess
+= lb
->getName().c_str();
502 MessageBox((LPCTSTR
) mess
, (LPCTSTR
) err
, MB_ICONEXCLAMATION
);
507 _Node
->getPSPointer()->activatePresetBehaviour((NL3D::CParticleSystem::TPresetBehaviour
) m_PresetCtrl
.GetCurSel());
508 updateLifeMgtPresets();
509 updateModifiedFlag();
512 //=====================================================
513 void CParticleSystemEdit::OnSelchangeAnimTypeCtrl()
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
;
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
);
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
);
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);
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
);
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
;
644 PS
->getAccurateIntegrationParams(t
, max
, csd
, klt
);
648 //=====================================================
649 void CTimeThresholdWrapper::set(const float &tt
)
651 NL3D::TAnimationTime t
;
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
;
667 PS
->getAccurateIntegrationParams(t
, max
, csd
, klt
);
671 //=====================================================
672 void CMaxNbIntegrationWrapper::set(const uint32
&nmax
)
674 NL3D::TAnimationTime t
;
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
)
718 //=====================================================
719 void CParticleSystemEdit::OnForceLifeTimeUpdate()
721 NL3D::TAnimationTime t
;
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()
735 if (m_EnableLoadBalancing
== FALSE
)
737 int result
= MessageBox(_T("Are you sure ?"), _T("Load balancing on/off"), MB_OKCANCEL
);
740 _Node
->getPSPointer()->enableLoadBalancing(false);
744 m_EnableLoadBalancing
= TRUE
;
749 _Node
->getPSPointer()->enableLoadBalancing(false);
752 updateModifiedFlag();
755 //=====================================================
756 static void chooseGlobalUserParam(uint userParam
, NL3D::CParticleSystem
*ps
, CWnd
*parent
)
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()
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
);
803 _Node
->getPSPointer()->setBypassMaxNumIntegrationSteps(m_BypassMaxNumSteps
!= FALSE
);
804 _MaxIntegrationStepDlg
->EnableWindow(_Node
->getPSPointer()->getBypassMaxNumIntegrationSteps() ? FALSE
: TRUE
);
805 updateModifiedFlag();
808 //=====================================================
809 void CParticleSystemEdit::OnForceGlobalLighitng()
812 _Node
->getPSPointer()->setForceGlobalColorLightingFlag(m_ForceLighting
!= 0);
813 if (_Node
&& _Node
->getPSModel())
815 _Node
->getPSModel()->touchLightableState();
817 updateModifiedFlag();
820 //=====================================================
821 void CParticleSystemEdit::OnAutoDelay()
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()
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()
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()
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
);
910 buttonStr
.LoadString(locked
? IDS_UNLOCK_PS
: IDS_LOCK_PS
);
911 GetDlgItem(IDC_LOCK_FRAME_DELAY
)->SetWindowText(buttonStr
);