khanat-opennel-code/code/nel/tools/3d/object_viewer/particle_system_edit.cpp

906 lines
28 KiB
C++

// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "std_afx.h"
#include "object_viewer.h"
#include "particle_system_edit.h"
#include "nel/3d/particle_system.h"
#include "nel/3d/particle_system_model.h"
#include "nel/3d/ps_color.h"
#include "editable_range.h"
#include "auto_lod_dlg.h"
#include "ps_global_color_dlg.h"
#include "choose_name.h"
#include "particle_tree_ctrl.h"
#include "particle_dlg.h"
#include "choose_frame_delay.h"
static void concatEdit2Lines(CEdit &edit)
{
const uint lineLen= 1000;
uint n;
// retrieve the 2 lines.
char tmp0[2*lineLen];
char tmp1[lineLen];
n= edit.GetLine(0, tmp0, lineLen); tmp0[n]= 0;
n= edit.GetLine(1, tmp1, lineLen); tmp1[n]= 0;
// concat and update the CEdit.
edit.SetWindowText(strcat(tmp0, tmp1));
}
/////////////////////////////////////////////////////////////////////////////
// CParticleSystemEdit dialog
CTimeThresholdWrapper CParticleSystemEdit::_TimeThresholdWrapper;
CMaxViewDistWrapper CParticleSystemEdit::_MaxViewDistWrapper;
CMaxNbIntegrationWrapper CParticleSystemEdit::_MaxNbIntegrationWrapper;
CLODRatioWrapper CParticleSystemEdit::_LODRatioWrapper;
CUserParamWrapper CParticleSystemEdit::_UserParamWrapper[4];
//=====================================================
CParticleSystemEdit::CParticleSystemEdit(CParticleWorkspace::CNode *ownerNode, CParticleTreeCtrl *ptc)
: _Node(ownerNode),
_TimeThresholdDlg(NULL),
_MaxIntegrationStepDlg(NULL),
_MaxViewDistDlg(NULL),
_LODRatioDlg(NULL),
_AutoLODDlg(NULL),
_GlobalColorDlg(NULL),
_ParticleTreeCtrl(ptc)
{
nlassert(ptc);
//{{AFX_DATA_INIT(CParticleSystemEdit)
m_AccurateIntegration = FALSE;
m_EnableSlowDown = FALSE;
m_DieWhenOutOfRange = FALSE;
m_DieWhenOutOfFrustum = FALSE;
m_EnableLoadBalancing = FALSE;
m_BypassMaxNumSteps = FALSE;
m_ForceLighting = FALSE;
m_BBoxX = _T("");
m_BBoxY = _T("");
m_BBoxZ = _T("");
//}}AFX_DATA_INIT
}
//=====================================================
CParticleSystemEdit::~CParticleSystemEdit()
{
#define REMOVE_WND(wnd) if (wnd) { wnd->DestroyWindow(); delete wnd; wnd = NULL; }
REMOVE_WND(_TimeThresholdDlg);
REMOVE_WND(_MaxIntegrationStepDlg);
REMOVE_WND(_MaxViewDistDlg);
REMOVE_WND(_LODRatioDlg);
REMOVE_WND(_AutoLODDlg);
REMOVE_WND(_GlobalColorDlg);
//_ParticleTreeCtrl->getParticleDlg()->getObjectViewer()->getFrameDelayDlg()->lockToPS(false);
}
//=====================================================
void CParticleSystemEdit::init(CWnd *pParent) // standard constructor
{
Create(CParticleSystemEdit::IDD, pParent);
// TODO : remove all ugly hardcoded values
RECT r;
const sint xPos = 80;
sint yPos = 162;
_MaxViewDistDlg = new CEditableRangeFloat (std::string("MAX VIEW DIST"), _Node, 0, 100.f);
_MaxViewDistWrapper.PS = _Node->getPSPointer();
_MaxViewDistDlg->enableLowerBound(0, true);
_MaxViewDistDlg->setWrapper(&_MaxViewDistWrapper);
_MaxViewDistDlg->init(87, 325, this);
_LODRatioDlg = new CEditableRangeFloat (std::string("LOD RATIO"), _Node, 0, 1.f);
_LODRatioWrapper.PS = _Node->getPSPointer();
_LODRatioDlg->enableLowerBound(0, true);
_LODRatioDlg->enableUpperBound(1, true);
_LODRatioDlg->setWrapper(&_LODRatioWrapper);
_LODRatioDlg->init(87, 357, this);
_TimeThresholdDlg = new CEditableRangeFloat (std::string("TIME THRESHOLD"), _Node, 0.005f, 0.3f);
_TimeThresholdWrapper.PS = _Node->getPSPointer();
_TimeThresholdDlg->enableLowerBound(0, true);
_TimeThresholdDlg->setWrapper(&_TimeThresholdWrapper);
GetDlgItem(IDC_TIME_THRESHOLD_PLACE_HOLDER)->GetWindowRect(&r);
ScreenToClient(&r);
_TimeThresholdDlg->init(r.left, r.top, this);
_MaxIntegrationStepDlg = new CEditableRangeUInt (std::string("MAX INTEGRATION STEPS"), _Node, 0, 4);
_MaxNbIntegrationWrapper.PS = _Node->getPSPointer();
_MaxIntegrationStepDlg->enableLowerBound(0, true);
_MaxIntegrationStepDlg->setWrapper(&_MaxNbIntegrationWrapper);
GetDlgItem(IDC_MAX_STEP_PLACE_HOLDER)->GetWindowRect(&r);
ScreenToClient(&r);
_MaxIntegrationStepDlg->init(r.left, r.top, this);
for (uint k = 0; k < 4; ++k)
{
_UserParamWrapper[k].PS = _Node->getPSPointer();
_UserParamWrapper[k].Index = k;
CEditableRangeFloat *erf = new CEditableRangeFloat (std::string("USER PARAM") + (char) (k + 65), NULL, 0, 1.0f);
erf->enableLowerBound(0, false);
erf->enableUpperBound(1, false);
pushWnd(erf);
erf->setWrapper(&_UserParamWrapper[k]);
erf->init(xPos, yPos, this);
yPos += 35;
}
NL3D::TAnimationTime t;
uint32 max;
bool csd;
bool klt;
_Node->getPSPointer()->getAccurateIntegrationParams(t, max, csd, klt);
m_PrecomputeBBoxCtrl.SetCheck(_Node->getPSPointer()->getAutoComputeBBox() ? 0 : 1);
((CButton *) GetDlgItem(IDC_AUTO_BBOX))->SetCheck(_ParticleTreeCtrl->getParticleDlg()->getAutoBBox() ? 1 : 0);
m_EnableSlowDown = csd;
((CButton *) GetDlgItem(IDC_SHARABLE))->SetCheck(_Node->getPSPointer()->isSharingEnabled());
m_AccurateIntegration = _Node->getPSPointer()->isAccurateIntegrationEnabled();
BOOL bAutoLOD = _Node->getPSPointer()->isAutoLODEnabled();
((CButton *) GetDlgItem(IDC_ENABLE_AUTO_LOD))->SetCheck(bAutoLOD);
GetDlgItem(IDC_EDIT_AUTO_LOD)->EnableWindow(bAutoLOD);
/// global color
int bGlobalColor = _Node->getPSPointer()->getColorAttenuationScheme() != NULL ? 1 : 0;
((CButton *) GetDlgItem(IDC_GLOBAL_COLOR))->SetCheck(bGlobalColor);
GetDlgItem(IDC_EDIT_GLOBAL_COLOR)->EnableWindow(bGlobalColor);
updateIntegrationParams();
updatePrecomputedBBoxParams();
updateLifeMgtPresets();
m_EnableLoadBalancing = _Node->getPSPointer()->isLoadBalancingEnabled();
_MaxIntegrationStepDlg->EnableWindow(_Node->getPSPointer()->getBypassMaxNumIntegrationSteps() ? FALSE : TRUE);
m_ForceLighting = _Node->getPSPointer()->getForceGlobalColorLightingFlag();
CString lockButtonStr;
lockButtonStr.LoadString(IDS_LOCK_PS);
GetDlgItem(IDC_LOCK_FRAME_DELAY)->SetWindowText(lockButtonStr);
UpdateData(FALSE);
ShowWindow(SW_SHOW);
}
//=====================================================
void CParticleSystemEdit::updateIntegrationParams()
{
BOOL ew = _Node->getPSPointer()->isAccurateIntegrationEnabled();
_TimeThresholdDlg->EnableWindow(ew);
_MaxIntegrationStepDlg->EnableWindow(ew);
m_EnableSlowDownCtrl.EnableWindow(ew);
}
//=====================================================
void CParticleSystemEdit::updateDieOnEventParams()
{
BOOL ew = _Node->getPSPointer()->getDestroyCondition() == NL3D::CParticleSystem::none ? FALSE : TRUE;
GetDlgItem(IDC_AUTO_DELAY)->EnableWindow(ew);
bool autoDelay = _Node->getPSPointer()->getAutoComputeDelayBeforeDeathConditionTest();
if (autoDelay)
{
ew = FALSE;
}
GetDlgItem(IDC_APPLY_AFTER_DELAY)->EnableWindow(ew);
char out[128];
if (_Node->getPSPointer()->getDelayBeforeDeathConditionTest() >= 0)
{
sprintf(out, "%.2g", _Node->getPSPointer()->getDelayBeforeDeathConditionTest());
}
else
{
strcpy(out,"???");
}
GetDlgItem(IDC_APPLY_AFTER_DELAY)->SetWindowText(out);
((CButton *) GetDlgItem(IDC_AUTO_DELAY))->SetCheck(autoDelay ? 1 : 0);
}
//=====================================================
void CParticleSystemEdit::OnPrecomputeBbox()
{
UpdateData();
_Node->getPSPointer()->setAutoComputeBBox(!_Node->getPSPointer()->getAutoComputeBBox() ? true : false);
if (!_Node->getPSPointer()->getAutoComputeBBox())
{
_ParticleTreeCtrl->getParticleDlg()->setAutoBBox(true);
_ParticleTreeCtrl->getParticleDlg()->resetAutoBBox();
((CButton *) GetDlgItem(IDC_AUTO_BBOX))->SetCheck(1);
}
else
{
_ParticleTreeCtrl->getParticleDlg()->setAutoBBox(false);
((CButton *) GetDlgItem(IDC_AUTO_BBOX))->SetCheck(0);
}
updatePrecomputedBBoxParams();
updateModifiedFlag();
}
//=====================================================
void CParticleSystemEdit::updatePrecomputedBBoxParams()
{
nlassert(_ParticleTreeCtrl);
BOOL ew = !_ParticleTreeCtrl->getParticleDlg()->getAutoBBox() && !_Node->getPSPointer()->getAutoComputeBBox();
m_BBoxXCtrl.EnableWindow(ew);
m_BBoxYCtrl.EnableWindow(ew);
m_BBoxZCtrl.EnableWindow(ew);
GetDlgItem(IDC_DEC_BBOX)->EnableWindow(!_Node->getPSPointer()->getAutoComputeBBox());
GetDlgItem(IDC_INC_BBOX)->EnableWindow(!_Node->getPSPointer()->getAutoComputeBBox());
GetDlgItem(IDC_AUTO_BBOX)->EnableWindow(!_Node->getPSPointer()->getAutoComputeBBox());
if (!ew)
{
m_BBoxX = "";
m_BBoxY = "";
m_BBoxZ = "";
}
else
{
NLMISC::CAABBox b;
_Node->getPSPointer()->computeBBox(b);
char out[128];
sprintf(out, "%.3g", b.getHalfSize().x); m_BBoxX = out;
sprintf(out, "%.3g", b.getHalfSize().y); m_BBoxY = out;
sprintf(out, "%.3g", b.getHalfSize().z); m_BBoxZ = out;
}
GetDlgItem(IDC_RESET_BBOX)->EnableWindow(_ParticleTreeCtrl->getParticleDlg()->getAutoBBox() && !_Node->getPSPointer()->getAutoComputeBBox());
UpdateData(FALSE);
}
//=====================================================
void CParticleSystemEdit::OnSelchangePsDieOnEvent()
{
UpdateData();
_Node->getPSPointer()->setDestroyCondition((NL3D::CParticleSystem::TDieCondition) m_DieOnEvent.GetCurSel());
updateDieOnEventParams();
updateModifiedFlag();
updateModifiedFlag();
}
//=====================================================
void CParticleSystemEdit::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CParticleSystemEdit)
DDX_Control(pDX, IDC_BYPASS_MAX_NUM_STEPS, m_BypassMaxNumStepsCtrl);
DDX_Control(pDX, IDC_FORCE_LIFE_TIME_UPDATE, m_ForceLifeTimeUpdate);
DDX_Control(pDX, IDC_DIE_WHEN_OUT_OF_FRUSTRUM, m_DieWhenOutOfFrustumCtrl);
DDX_Control(pDX, IDC_DIE_WHEN_OUT_OF_RANGE, m_DieWhenOutOfRangeCtrl);
DDX_Control(pDX, IDC_ANIM_TYPE_CTRL, m_AnimTypeCtrl);
DDX_Control(pDX, IDC_LIFE_MGT_PRESETS, m_PresetCtrl);
DDX_Control(pDX, IDC_PS_DIE_ON_EVENT, m_DieOnEvent);
DDX_Control(pDX, IDC_PRECOMPUTE_BBOX, m_PrecomputeBBoxCtrl);
DDX_Control(pDX, IDC_BB_Z, m_BBoxZCtrl);
DDX_Control(pDX, IDC_BB_Y, m_BBoxYCtrl);
DDX_Control(pDX, IDC_BB_X, m_BBoxXCtrl);
DDX_Control(pDX, IDC_ENABLE_SLOW_DOWN, m_EnableSlowDownCtrl);
DDX_Check(pDX, IDC_ACCURATE_INTEGRATION, m_AccurateIntegration);
DDX_Check(pDX, IDC_ENABLE_SLOW_DOWN, m_EnableSlowDown);
DDX_Check(pDX, IDC_DIE_WHEN_OUT_OF_RANGE, m_DieWhenOutOfRange);
DDX_Check(pDX, IDC_DIE_WHEN_OUT_OF_FRUSTRUM, m_DieWhenOutOfFrustum);
DDX_Check(pDX, IDC_ENABLE_LOAD_BALANCING, m_EnableLoadBalancing);
DDX_Check(pDX, IDC_BYPASS_MAX_NUM_STEPS, m_BypassMaxNumSteps);
DDX_Check(pDX, IDC_FORCE_GLOBAL_LIGHITNG, m_ForceLighting);
DDX_Text(pDX, IDC_BB_X, m_BBoxX);
DDX_Text(pDX, IDC_BB_Y, m_BBoxY);
DDX_Text(pDX, IDC_BB_Z, m_BBoxZ);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CParticleSystemEdit, CDialog)
//{{AFX_MSG_MAP(CParticleSystemEdit)
ON_BN_CLICKED(IDC_ACCURATE_INTEGRATION, OnAccurateIntegration)
ON_BN_CLICKED(IDC_ENABLE_SLOW_DOWN, OnEnableSlowDown)
ON_BN_CLICKED(IDC_PRECOMPUTE_BBOX, OnPrecomputeBbox)
ON_BN_CLICKED(IDC_INC_BBOX, OnIncBbox)
ON_BN_CLICKED(IDC_DEC_BBOX, OnDecBbox)
ON_BN_CLICKED(IDC_DIE_WHEN_OUT_OF_RANGE, OnDieWhenOutOfRange)
ON_CBN_SELCHANGE(IDC_PS_DIE_ON_EVENT, OnSelchangePsDieOnEvent)
ON_EN_CHANGE(IDC_APPLY_AFTER_DELAY, OnChangeApplyAfterDelay)
ON_BN_CLICKED(IDC_DIE_WHEN_OUT_OF_FRUSTRUM, OnDieWhenOutOfFrustum)
ON_CBN_SELCHANGE(IDC_LIFE_MGT_PRESETS, OnSelchangeLifeMgtPresets)
ON_CBN_SELCHANGE(IDC_ANIM_TYPE_CTRL, OnSelchangeAnimTypeCtrl)
ON_BN_CLICKED(IDC_SHARABLE, OnSharable)
ON_BN_CLICKED(IDC_EDIT_AUTO_LOD, OnEditAutoLod)
ON_BN_CLICKED(IDC_ENABLE_AUTO_LOD, OnEnableAutoLod)
ON_BN_CLICKED(IDC_FORCE_LIFE_TIME_UPDATE, OnForceLifeTimeUpdate)
ON_BN_CLICKED(IDC_EDIT_GLOBAL_COLOR, OnEditGlobalColor)
ON_BN_CLICKED(IDC_GLOBAL_COLOR, OnGlobalColor)
ON_BN_CLICKED(IDC_ENABLE_LOAD_BALANCING, OnEnableLoadBalancing)
ON_BN_CLICKED(IDC_GLOBAL_USER_PARAM_1, OnGlobalUserParam1)
ON_BN_CLICKED(IDC_GLOBAL_USER_PARAM_2, OnGlobalUserParam2)
ON_BN_CLICKED(IDC_GLOBAL_USER_PARAM_3, OnGlobalUserParam3)
ON_BN_CLICKED(IDC_GLOBAL_USER_PARAM_4, OnGlobalUserParam4)
ON_BN_CLICKED(IDC_BYPASS_MAX_NUM_STEPS, OnBypassMaxNumSteps)
ON_BN_CLICKED(IDC_FORCE_GLOBAL_LIGHITNG, OnForceGlobalLighitng)
ON_BN_CLICKED(IDC_AUTO_DELAY, OnAutoDelay)
ON_EN_CHANGE(IDC_BB_Z, OnChangeBBZ)
ON_EN_CHANGE(IDC_BB_X, OnChangeBBX)
ON_EN_CHANGE(IDC_BB_Y, OnChangeBBY)
ON_BN_CLICKED(IDC_AUTO_BBOX, OnAutoBbox)
ON_BN_CLICKED(IDC_RESET_BBOX, OnResetBBox)
ON_BN_CLICKED(IDC_LOCK_FRAME_DELAY, OnLockFrameDelay)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CParticleSystemEdit message handlers
//=====================================================
void CParticleSystemEdit::OnAccurateIntegration()
{
UpdateData();
_Node->getPSPointer()->enableAccurateIntegration(m_AccurateIntegration ? true : false);
updateIntegrationParams();
updateModifiedFlag();
}
//=====================================================
void CParticleSystemEdit::OnEnableSlowDown()
{
UpdateData();
NL3D::TAnimationTime t;
uint32 max;
bool csd;
bool klt;
_Node->getPSPointer()->getAccurateIntegrationParams(t, max, csd, klt);
_Node->getPSPointer()->setAccurateIntegrationParams(t, max, m_EnableSlowDown ? true : false, klt);
updateModifiedFlag();
}
//=====================================================
void CParticleSystemEdit::updateBBoxFromText()
{
NLMISC::CVector h;
char inX[128], inY[128], inZ[128];
m_BBoxXCtrl.GetWindowText(inX, 128);
m_BBoxYCtrl.GetWindowText(inY, 128);
m_BBoxZCtrl.GetWindowText(inZ, 128);
if (sscanf(inX, "%f", &h.x) == 1
&& sscanf(inY, "%f", &h.y) == 1
&& sscanf(inZ, "%f", &h.z) == 1
)
{
NLMISC::CAABBox b;
b.setHalfSize(h);
_Node->getPSPointer()->setPrecomputedBBox(b);
}
else
{
MessageBox("Invalid entry","error", MB_OK);
}
}
//=====================================================
void CParticleSystemEdit::OnIncBbox()
{
NLMISC::CAABBox b;
_Node->getPSPointer()->computeBBox(b);
b.setHalfSize(1.1f * b.getHalfSize());
_Node->getPSPointer()->setPrecomputedBBox(b);
updatePrecomputedBBoxParams();
updateModifiedFlag();
}
//=====================================================
void CParticleSystemEdit::OnDecBbox()
{
NLMISC::CAABBox b;
_Node->getPSPointer()->computeBBox(b);
b.setHalfSize(0.9f * b.getHalfSize());
_Node->getPSPointer()->setPrecomputedBBox(b);
updatePrecomputedBBoxParams();
updateModifiedFlag();
}
//=====================================================
void CParticleSystemEdit::OnDieWhenOutOfRange()
{
UpdateData();
_Node->getPSPointer()->setDestroyModelWhenOutOfRange(m_DieWhenOutOfRange ? true : false);
updateModifiedFlag();
}
//=====================================================
void CParticleSystemEdit::OnDieWhenOutOfFrustum()
{
UpdateData();
_Node->getPSPointer()->destroyWhenOutOfFrustum(m_DieWhenOutOfFrustum ? true : false);
m_AnimTypeCtrl.EnableWindow(!m_DieWhenOutOfFrustum);
updateModifiedFlag();
}
//=====================================================
void CParticleSystemEdit::OnChangeApplyAfterDelay()
{
if (_Node->getPSPointer()->getAutoComputeDelayBeforeDeathConditionTest()) return;
//
char in[128];
GetDlgItem(IDC_APPLY_AFTER_DELAY)->GetWindowText(in, 128);
float value;
if (sscanf(in, "%f", &value) == 1)
{
if (_Node->getPSPointer()->getDelayBeforeDeathConditionTest() != value)
{
_Node->getPSPointer()->setDelayBeforeDeathConditionTest(value);
updateModifiedFlag();
}
}
}
//=====================================================
void CParticleSystemEdit::OnSelchangeLifeMgtPresets()
{
UpdateData(TRUE);
if (m_PresetCtrl.GetCurSel() == NL3D::CParticleSystem::SpellFX ||
m_PresetCtrl.GetCurSel() == NL3D::CParticleSystem::SpawnedEnvironmentFX)
{
NL3D::CPSLocatedBindable *lb;
if (!_Node->getPSPointer()->canFinish(&lb))
{
m_PresetCtrl.SetCurSel((int) _Node->getPSPointer()->getBehaviourType());
CString mess;
CString err;
err.LoadString(IDS_ERROR);
if (!lb)
{
mess.LoadString(IDS_NO_FINITE_DURATION);
MessageBox((LPCTSTR) mess, (LPCTSTR) err, MB_ICONEXCLAMATION);
}
else
{
mess.LoadString(IDS_NO_FINITE_DURATION_FOR_OBJ);
mess += lb->getName().c_str();
MessageBox((LPCTSTR) mess, (LPCTSTR) err, MB_ICONEXCLAMATION);
}
return;
}
}
_Node->getPSPointer()->activatePresetBehaviour((NL3D::CParticleSystem::TPresetBehaviour) m_PresetCtrl.GetCurSel());
updateLifeMgtPresets();
updateModifiedFlag();
}
//=====================================================
void CParticleSystemEdit::OnSelchangeAnimTypeCtrl()
{
UpdateData(TRUE);
_Node->getPSPointer()->setAnimType((NL3D::CParticleSystem::TAnimType) m_AnimTypeCtrl.GetCurSel());
updateModifiedFlag();
}
//=====================================================
void CParticleSystemEdit::updateLifeMgtPresets()
{
m_PresetCtrl.SetCurSel((int) _Node->getPSPointer()->getBehaviourType());
m_DieWhenOutOfRange = _Node->getPSPointer()->getDestroyModelWhenOutOfRange();
m_DieWhenOutOfFrustum = _Node->getPSPointer()->doesDestroyWhenOutOfFrustum();
m_BypassMaxNumSteps = _Node->getPSPointer()->getBypassMaxNumIntegrationSteps();
m_DieOnEvent.SetCurSel((int) _Node->getPSPointer()->getDestroyCondition());
m_AnimTypeCtrl.SetCurSel((int) _Node->getPSPointer()->getAnimType());
updateDieOnEventParams();
NL3D::TAnimationTime t;
uint32 max;
bool csd;
bool klt;
_Node->getPSPointer()->getAccurateIntegrationParams(t, max, csd, klt);
((CButton *) GetDlgItem(IDC_FORCE_LIFE_TIME_UPDATE))->SetCheck(klt);
BOOL bEnable = _Node->getPSPointer()->getBehaviourType() == NL3D::CParticleSystem::UserBehaviour ? TRUE : FALSE;
m_DieWhenOutOfRangeCtrl.EnableWindow(bEnable);
m_DieWhenOutOfFrustumCtrl.EnableWindow(bEnable);
m_DieOnEvent.EnableWindow(bEnable);
m_AnimTypeCtrl.EnableWindow(bEnable);
m_ForceLifeTimeUpdate.EnableWindow(bEnable);
m_BypassMaxNumStepsCtrl.EnableWindow(bEnable);
_MaxIntegrationStepDlg->EnableWindow(_Node->getPSPointer()->getBypassMaxNumIntegrationSteps() ? FALSE : TRUE);
UpdateData(FALSE);
}
//=====================================================
void CParticleSystemEdit::OnSharable()
{
bool shared = ((CButton *) GetDlgItem(IDC_SHARABLE))->GetCheck() != 0;
_Node->getPSPointer()->enableSharing(shared);
updateModifiedFlag();
}
//=====================================================
void CParticleSystemEdit::OnEditAutoLod()
{
GetDlgItem(IDC_EDIT_AUTO_LOD)->EnableWindow(FALSE);
GetDlgItem(IDC_ENABLE_AUTO_LOD)->EnableWindow(FALSE);
GetDlgItem(IDC_SHARABLE)->EnableWindow(FALSE);
nlassert(_AutoLODDlg == NULL);
CAutoLODDlg *autoLODDlg = new CAutoLODDlg(_Node, _Node->getPSPointer(), this);
autoLODDlg->init(this);
_AutoLODDlg = autoLODDlg;
}
//=====================================================
void CParticleSystemEdit::childPopupClosed(CWnd *child)
{
if (child == _AutoLODDlg)
{
GetDlgItem(IDC_EDIT_AUTO_LOD)->EnableWindow(TRUE);
GetDlgItem(IDC_ENABLE_AUTO_LOD)->EnableWindow(TRUE);
GetDlgItem(IDC_SHARABLE)->EnableWindow(TRUE);
REMOVE_WND(_AutoLODDlg);
}
else
if (child == _GlobalColorDlg)
{
GetDlgItem(IDC_GLOBAL_COLOR)->EnableWindow(TRUE);
GetDlgItem(IDC_EDIT_GLOBAL_COLOR)->EnableWindow(TRUE);
REMOVE_WND(_GlobalColorDlg);
}
}
//=====================================================
void CParticleSystemEdit::OnEnableAutoLod()
{
BOOL bEnable = ((CButton *) GetDlgItem(IDC_ENABLE_AUTO_LOD))->GetCheck() != 0;
GetDlgItem(IDC_EDIT_AUTO_LOD)->EnableWindow(bEnable);
_Node->getPSPointer()->enableAutoLOD(bEnable ? true : false /* performance warning */);
updateModifiedFlag();
}
///=====================================================================
void CParticleSystemEdit::OnEditGlobalColor()
{
nlassert(!_GlobalColorDlg);
GetDlgItem(IDC_GLOBAL_COLOR)->EnableWindow(FALSE);
GetDlgItem(IDC_EDIT_GLOBAL_COLOR)->EnableWindow(FALSE);
CPSGlobalColorDlg *gcd = new CPSGlobalColorDlg(_Node, this, this);
gcd->init(this);
_GlobalColorDlg = gcd;
updateModifiedFlag();
}
///=====================================================================
void CParticleSystemEdit::OnGlobalColor()
{
/// if the system hasn't a global color scheme, add one.
if (_Node->getPSPointer()->getColorAttenuationScheme() == NULL)
{
static const NLMISC::CRGBA grad[] = { NLMISC::CRGBA::White, NLMISC::CRGBA::Black };
_Node->getPSPointer()->setColorAttenuationScheme(new NL3D::CPSColorGradient(grad, 2, 64, 1.f));
GetDlgItem(IDC_EDIT_GLOBAL_COLOR)->EnableWindow(TRUE);
}
else
{
_Node->getPSPointer()->setColorAttenuationScheme(NULL);
GetDlgItem(IDC_EDIT_GLOBAL_COLOR)->EnableWindow(FALSE);
}
updateModifiedFlag();
}
/////////////////////////////
// WRAPPERS IMPLEMENTATION //
/////////////////////////////
//=====================================================
float CTimeThresholdWrapper::get(void) const
{
NL3D::TAnimationTime t;
uint32 max;
bool csd;
bool klt;
PS->getAccurateIntegrationParams(t, max, csd, klt);
return t;
}
//=====================================================
void CTimeThresholdWrapper::set(const float &tt)
{
NL3D::TAnimationTime t;
uint32 max;
bool csd;
bool klt;
PS->getAccurateIntegrationParams(t, max, csd, klt);
PS->setAccurateIntegrationParams(tt, max, csd, klt);
}
//=====================================================
uint32 CMaxNbIntegrationWrapper::get(void) const
{
NL3D::TAnimationTime t;
uint32 max;
bool csd;
bool klt;
PS->getAccurateIntegrationParams(t, max, csd, klt);
return max;
}
//=====================================================
void CMaxNbIntegrationWrapper::set(const uint32 &nmax)
{
NL3D::TAnimationTime t;
uint32 max;
bool csd;
bool klt;
PS->getAccurateIntegrationParams(t, max, csd, klt);
PS->setAccurateIntegrationParams(t, nmax, csd, klt);
}
//=====================================================
float CUserParamWrapper::get(void) const
{
return PS->getUserParam(Index);
}
//=====================================================
void CUserParamWrapper::set(const float &v)
{
PS->setUserParam(Index, v);
}
//=====================================================
float CMaxViewDistWrapper::get(void) const
{
return PS->getMaxViewDist();
}
//=====================================================
void CMaxViewDistWrapper::set(const float &d)
{
PS->setMaxViewDist(d);
}
//=====================================================
float CLODRatioWrapper::get(void) const
{
return PS->getLODRatio();
}
//=====================================================
void CLODRatioWrapper::set(const float &v)
{
PS->setLODRatio(v);
}
//=====================================================
void CParticleSystemEdit::OnForceLifeTimeUpdate()
{
NL3D::TAnimationTime t;
uint32 max;
bool csd;
bool klt;
_Node->getPSPointer()->getAccurateIntegrationParams(t, max, csd, klt);
klt = ((CButton *) GetDlgItem(IDC_FORCE_LIFE_TIME_UPDATE))->GetCheck() != 0;
_Node->getPSPointer()->setAccurateIntegrationParams(t, max, csd, klt);
updateModifiedFlag();
}
//=====================================================
void CParticleSystemEdit::OnEnableLoadBalancing()
{
UpdateData(TRUE);
if (m_EnableLoadBalancing == FALSE)
{
int result = MessageBox("Are you sure ?", "Load balancing on/off", MB_OKCANCEL);
if (result == IDOK)
{
_Node->getPSPointer()->enableLoadBalancing(false);
}
else
{
m_EnableLoadBalancing = TRUE;
}
}
else
{
_Node->getPSPointer()->enableLoadBalancing(false);
}
UpdateData(FALSE);
updateModifiedFlag();
}
//=====================================================
static void chooseGlobalUserParam(uint userParam, NL3D::CParticleSystem *ps, CWnd *parent)
{
nlassert(ps);
CChooseName cn(!ps->getGlobalValueName(userParam).empty() ? ps->getGlobalValueName(userParam).c_str() : "", parent);
if (cn.DoModal() == IDOK)
{
ps->bindGlobalValueToUserParam(cn.getName().c_str(), userParam);
}
}
//=====================================================
void CParticleSystemEdit::OnGlobalUserParam1()
{
nlassert(_Node->getPSPointer());
chooseGlobalUserParam(0, _Node->getPSPointer(), this);
}
//=====================================================
void CParticleSystemEdit::OnGlobalUserParam2()
{
chooseGlobalUserParam(1, _Node->getPSPointer(), this);
updateModifiedFlag();
}
//=====================================================
void CParticleSystemEdit::OnGlobalUserParam3()
{
chooseGlobalUserParam(2, _Node->getPSPointer(), this);
updateModifiedFlag();
}
//=====================================================
void CParticleSystemEdit::OnGlobalUserParam4()
{
chooseGlobalUserParam(3, _Node->getPSPointer(), this);
updateModifiedFlag();
}
//=====================================================
void CParticleSystemEdit::OnBypassMaxNumSteps()
{
UpdateData(TRUE);
if (m_BypassMaxNumSteps && !_Node->getPSPointer()->canFinish())
{
MessageBox("The system must have a finite duration for this setting! Please check that.", "error", MB_ICONEXCLAMATION);
return;
}
_Node->getPSPointer()->setBypassMaxNumIntegrationSteps(m_BypassMaxNumSteps != FALSE);
_MaxIntegrationStepDlg->EnableWindow(_Node->getPSPointer()->getBypassMaxNumIntegrationSteps() ? FALSE : TRUE);
updateModifiedFlag();
}
//=====================================================
void CParticleSystemEdit::OnForceGlobalLighitng()
{
UpdateData(TRUE);
_Node->getPSPointer()->setForceGlobalColorLightingFlag(m_ForceLighting != 0);
if (_Node && _Node->getPSModel())
{
_Node->getPSModel()->touchLightableState();
}
updateModifiedFlag();
}
//=====================================================
void CParticleSystemEdit::OnAutoDelay()
{
UpdateData(TRUE);
bool autoDelay = ((CButton *) GetDlgItem(IDC_AUTO_DELAY))->GetCheck() != 0;
_Node->getPSPointer()->setAutoComputeDelayBeforeDeathConditionTest(autoDelay);
GetDlgItem(IDC_APPLY_AFTER_DELAY)->EnableWindow(autoDelay ? FALSE : TRUE);
updateModifiedFlag();
}
//=====================================================
void CParticleSystemEdit::refresh()
{
updatePrecomputedBBoxParams();
updateIntegrationParams();
updateDieOnEventParams();
updateLifeMgtPresets();
}
//=====================================================
void CParticleSystemEdit::OnChangeBBX()
{
UpdateData();
// Trick to track "Enter" keypress: CEdit are multiline. If GetLineCount()>1, then
// user has press enter.
if(m_BBoxXCtrl.GetLineCount()>1)
{
// must ccat 2 lines of the CEdit.
concatEdit2Lines(m_BBoxXCtrl);
m_BBoxXCtrl.GetWindowText(m_BBoxX);
updateBBoxFromText();
updateModifiedFlag();
}
}
//=====================================================
void CParticleSystemEdit::OnChangeBBY()
{
UpdateData();
// Trick to track "Enter" keypress: CEdit are multiline. If GetLineCount()>1, then
// user has press enter.
if(m_BBoxYCtrl.GetLineCount()>1)
{
// must ccat 2 lines of the CEdit.
concatEdit2Lines(m_BBoxYCtrl);
m_BBoxYCtrl.GetWindowText(m_BBoxY);
updateBBoxFromText();
updateModifiedFlag();
}
}
//=====================================================
void CParticleSystemEdit::OnChangeBBZ()
{
UpdateData();
// Trick to track "Enter" keypress: CEdit are multiline. If GetLineCount()>1, then
// user has press enter.
if(m_BBoxZCtrl.GetLineCount()>1)
{
// must ccat 2 lines of the CEdit.
concatEdit2Lines(m_BBoxZCtrl);
m_BBoxZCtrl.GetWindowText(m_BBoxZ);
updateBBoxFromText();
updateModifiedFlag();
}
}
//=====================================================
void CParticleSystemEdit::OnAutoBbox()
{
nlassert(_ParticleTreeCtrl);
_ParticleTreeCtrl->getParticleDlg()->setAutoBBox(!_ParticleTreeCtrl->getParticleDlg()->getAutoBBox());
updatePrecomputedBBoxParams();
updateModifiedFlag();
}
//=====================================================
void CParticleSystemEdit::OnResetBBox()
{
nlassert(_ParticleTreeCtrl);
_ParticleTreeCtrl->getParticleDlg()->resetAutoBBox();
updateModifiedFlag();
}
//=====================================================
void CParticleSystemEdit::OnLockFrameDelay()
{
bool locked = !_ParticleTreeCtrl->getParticleDlg()->getObjectViewer()->getFrameDelayDlg()->isLockedToPS();
_ParticleTreeCtrl->getParticleDlg()->getObjectViewer()->getFrameDelayDlg()->lockToPS(locked);
CString buttonStr;
buttonStr.LoadString(locked ? IDS_UNLOCK_PS : IDS_LOCK_PS);
GetDlgItem(IDC_LOCK_FRAME_DELAY)->SetWindowText(buttonStr);
}