// NeL - MMORPG Framework // 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 . // water_pool_editor.cpp : implementation file // #include "std_afx.h" #include "object_viewer.h" #include "water_pool_editor.h" #include "editable_range.h" #include "nel/3d/water_pool_manager.h" #include "choose_pool_id.h" #include "nel/misc/i_xml.h" #include "nel/misc/o_xml.h" #include "nel/misc/file.h" ///////////////////////////////////////////////////////////////////////////// // CWaterPoolEditor dialog CWaterPoolEditor::CWaterPoolEditor(NL3D::CWaterPoolManager *wpm, CWnd* pParent /*= NULL*/) : CDialog(CWaterPoolEditor::IDD, pParent), _DampingDlg(NULL), _FilterWeightDlg(NULL), _WaterUnitSizeDlg(NULL), _Wpm(wpm) { //{{AFX_DATA_INIT(CWaterPoolEditor) m_AutomaticWavesGeneration = FALSE; m_BordersOnly = FALSE; m_MapSize = -1; //}}AFX_DATA_INIT } CWaterPoolEditor::~CWaterPoolEditor() { #define REMOVE_WINDOW(wnd) if (wnd) { (wnd)->DestroyWindow(); delete (wnd); } REMOVE_WINDOW(_DampingDlg); REMOVE_WINDOW(_FilterWeightDlg); REMOVE_WINDOW(_WaterUnitSizeDlg); REMOVE_WINDOW(_ImpulsionStrenghtDlg); REMOVE_WINDOW(_WavePeriodDlg); REMOVE_WINDOW(_WaveImpulsionRadiusDlg); REMOVE_WINDOW(_PropagationTimeDlg); } void CWaterPoolEditor::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CWaterPoolEditor) DDX_Control(pDX, IDC_POOL_LIST, m_PoolList); DDX_Check(pDX, IDC_AUTOMATIC_WAVES_GENERATION, m_AutomaticWavesGeneration); DDX_Check(pDX, IDC_BORDERS_ONLY, m_BordersOnly); DDX_CBIndex(pDX, IDC_MAP_SIZE, m_MapSize); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CWaterPoolEditor, CDialog) //{{AFX_MSG_MAP(CWaterPoolEditor) ON_LBN_SELCHANGE(IDC_POOL_LIST, OnSelchangePoolList) ON_BN_CLICKED(IDC_AUTOMATIC_WAVES_GENERATION, OnAutomaticWavesGeneration) ON_BN_CLICKED(IDC_BORDERS_ONLY, OnBordersOnly) ON_BN_CLICKED(IDC_ADD_POOL, OnAddPool) ON_BN_CLICKED(IDC_DELETE_POOL, OnDeletePool) ON_CBN_SELCHANGE(IDC_MAP_SIZE, OnSelchangeMapSize) ON_BN_CLICKED(IDC_LOAD_POOL, OnLoadPool) ON_BN_CLICKED(IDC_SAVE_POOL, OnSavePool) ON_BN_CLICKED(IDC_RENAME_POOL, OnRenamePool) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CWaterPoolEditor message handlers BOOL CWaterPoolEditor::OnInitDialog() { CDialog::OnInitDialog(); RECT r; fillPoolList(); // damping GetDlgItem(IDC_DAMPING)->GetWindowRect(&r); ScreenToClient(&r); _DampingDlg = new CEditableRangeFloat("WATER_DAMPING", NULL,0.9f ,0.999f); _DampingDlg->setWrapper(&_DampingWrapper); _DampingDlg->init(r.left, r.top, this); _DampingDlg->enableLowerBound(0, false); _DampingDlg->enableUpperBound(1, true); // filter weight GetDlgItem(IDC_FILTER_WEIGHT)->GetWindowRect(&r); ScreenToClient(&r); _FilterWeightDlg = new CEditableRangeFloat("FILTER_WEIGHT", NULL, 4, 10); _FilterWeightDlg->setWrapper(&_FilterWeightWrapper); _FilterWeightDlg->init(r.left, r.top, this); _FilterWeightDlg->enableLowerBound(0, false); // water unit size GetDlgItem(IDC_WATER_UNIT_SIZE)->GetWindowRect(&r); ScreenToClient(&r); _WaterUnitSizeDlg = new CEditableRangeFloat("WATER_UNIT_SIZE", NULL, 0.1f, 1); _WaterUnitSizeDlg->setWrapper(&_WaterUnitSizeWrapper); _WaterUnitSizeDlg->init(r.left, r.top, this); _WaterUnitSizeDlg->enableLowerBound(0, true); // wave impulsion strenght GetDlgItem(IDC_IMPULSION_STRENGHT)->GetWindowRect(&r); ScreenToClient(&r); _ImpulsionStrenghtDlg = new CEditableRangeFloat("WAVE_IMPULSION_STRENGHT", NULL, 0.2f, 3.0f); _ImpulsionStrenghtDlg->setWrapper(&_ImpulsionStrenghtWrapper); _ImpulsionStrenghtDlg->init(r.left, r.top, this); // wave period GetDlgItem(IDC_PERIOD)->GetWindowRect(&r); ScreenToClient(&r); _WavePeriodDlg = new CEditableRangeFloat("WAVE_PERIOD", NULL, 0, 5); _WavePeriodDlg->setWrapper(&_WavePeriodWrapper); _WavePeriodDlg->init(r.left, r.top, this); _WavePeriodDlg->enableLowerBound(0, false); // propagation time GetDlgItem(IDC_PROPAGATION_TIME)->GetWindowRect(&r); ScreenToClient(&r); _PropagationTimeDlg = new CEditableRangeFloat("PROPAGATION_TIME", NULL, 0, 2); _PropagationTimeDlg->setWrapper(&_PropagationTimeWrapper); _PropagationTimeDlg->init(r.left, r.top, this); _PropagationTimeDlg->enableLowerBound(0, false); // wave impulsion radius GetDlgItem(IDC_IMPULSION_RADIUS)->GetWindowRect(&r); ScreenToClient(&r); _WaveImpulsionRadiusDlg = new CEditableRangeUInt("WAVE_IMPULSION_RADIUS", NULL, 2, 5); _WaveImpulsionRadiusDlg->setWrapper(&_WaveImpulsionRadiusWrapper); _WaveImpulsionRadiusDlg->init(r.left, r.top, this); _WaveImpulsionRadiusDlg->enableLowerBound(0, true); updateWaveControls(); updateWaveParams(); updateMapSizeCtrl(); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } int CWaterPoolEditor::addPool(uint32 ID) { char poolId[128]; sprintf(poolId, "%d (%s)", ID, _Wpm->getPoolByID(ID).getName().c_str()); int index = m_PoolList.AddString(poolId); nlassert(index != LB_ERR); m_PoolList.SetItemData(index, ID); return index; } //===================================================================== void CWaterPoolEditor::fillPoolList() { UpdateData(); m_PoolList.ResetContent(); uint numPools = _Wpm->getNumPools(); if (numPools == 0) // we must have least have one pool { _Wpm->createWaterPool(); numPools = 1; } for (uint k = 0; k < numPools; ++k) { addPool(_Wpm->getPoolID(k)); } m_PoolList.SetCurSel(0); updateWrappers(); UpdateData(FALSE); } //=================================================================== uint32 CWaterPoolEditor::getCurrentPoolID() { UpdateData(); nlassert(m_PoolList.GetCurSel() != LB_ERR); // must always have something selected return (uint32)m_PoolList.GetItemData(m_PoolList.GetCurSel()); } //=================================================================== NL3D::CWaterHeightMap &CWaterPoolEditor::getCurrentPool() { return _Wpm->getPoolByID(getCurrentPoolID()); } //=================================================================== void CWaterPoolEditor::updateWrappers() { NL3D::CWaterHeightMap *whm = &getCurrentPool(); _DampingWrapper.Whm = whm; _FilterWeightWrapper.Whm = whm; _WaterUnitSizeWrapper.Whm = whm; _ImpulsionStrenghtWrapper.Whm = whm; _WavePeriodWrapper.Whm = whm; _WaveImpulsionRadiusWrapper.Whm = whm; _PropagationTimeWrapper.Whm = whm; } //=================================================================== void CWaterPoolEditor::OnSelchangePoolList() { updateWrappers(); _DampingDlg->update(); _FilterWeightDlg->update(); _WaterUnitSizeDlg->update(); _ImpulsionStrenghtDlg->update(); _WavePeriodDlg->update(); _WaveImpulsionRadiusDlg->update(); updateWaveControls(); updateWaveParams(); updateMapSizeCtrl(); } //=================================================================== void CWaterPoolEditor::OnAutomaticWavesGeneration() { UpdateData(); getCurrentPool().enableWaves(m_AutomaticWavesGeneration ? true : false /* VC++ warning */); updateWaveParams(); } //=================================================================== void CWaterPoolEditor::updateWaveParams() { bool enabled = getCurrentPool().areWavesEnabled(); _ImpulsionStrenghtDlg->EnableWindow(enabled); _WavePeriodDlg->EnableWindow(enabled); _WaveImpulsionRadiusDlg->EnableWindow(enabled); GetDlgItem(IDC_BORDERS_ONLY)->EnableWindow(enabled); } //=================================================================== void CWaterPoolEditor::OnBordersOnly() { UpdateData();; NL3D::CWaterHeightMap &whm = getCurrentPool(); whm.setWaves(whm.getWaveIntensity(), whm.getWavePeriod(), whm.getWaveImpulsionRadius(), m_BordersOnly ? true : false /* VC++ Warning */); } //=================================================================== void CWaterPoolEditor::updateWaveControls() { const NL3D::CWaterHeightMap &whm = getCurrentPool(); m_AutomaticWavesGeneration = whm.areWavesEnabled(); m_BordersOnly = whm.getBorderWaves(); UpdateData(FALSE); } //=================================================================== void CWaterPoolEditor::updateMapSizeCtrl() { switch(getCurrentPool().getSize()) { case 16: m_MapSize = 0; break; case 32: m_MapSize = 1; break; case 64: m_MapSize = 2; break; case 128: m_MapSize = 3; break; case 256: m_MapSize = 4; break; case 512: m_MapSize = 5; break; default: nlassert(0); break; } UpdateData(FALSE); } //=================================================================== void CWaterPoolEditor::OnAddPool() { CChoosePoolID cpi(false); cpi.PoolID = getCurrentPoolID(); if (cpi.DoModal() == IDOK) { if (_Wpm->hasPool(cpi.PoolID) ) { MessageBox("Pool already exists", "error"); } else { NL3D::CWaterPoolManager::CWaterHeightMapBuild whmb; whmb.ID = cpi.PoolID; whmb.Name = cpi.Name; _Wpm->createWaterPool(whmb); m_PoolList.SetCurSel(addPool(cpi.PoolID)); OnSelchangePoolList(); } } } //=================================================================== void CWaterPoolEditor::OnDeletePool() { UpdateData(); if (m_PoolList.GetCount() == 1) { MessageBox("Must have at least one water pool", "error"); } else { _Wpm->removePool(getCurrentPoolID()); m_PoolList.DeleteString(m_PoolList.GetCurSel()); m_PoolList.SetCurSel(0); OnSelchangePoolList(); } UpdateData(FALSE); } //=================================================================== void CWaterPoolEditor::OnSelchangeMapSize() { UpdateData(); static const uint size[] = { 16, 32, 64, 128, 256, 512 }; const uint tabSize = sizeof(size) / sizeof(uint); nlassert(m_MapSize < tabSize); getCurrentPool().setSize(size[m_MapSize]); } void CWaterPoolEditor::OnLoadPool() { static char BASED_CODE szFilter[] = "NeL Water Pool Files (*.wpf)|*.wpf||"; CFileDialog fileDlg( TRUE, ".wpf", "*.wpf", OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, szFilter); if (fileDlg.DoModal()==IDOK) { try { NLMISC::CIXml iXml; NLMISC::CIFile iF; if (iF.open((LPCTSTR) fileDlg.GetPathName())) { if (iXml.init (iF)) { _Wpm->serial(iXml); iXml.release(); iF.close(); fillPoolList(); } else { iF.close(); MessageBox (("Unable to init xml stream from file : " + std::string((LPCTSTR) fileDlg.GetPathName())).c_str(), "NeL object viewer", MB_OK|MB_ICONEXCLAMATION); } } else { MessageBox (("Unable to open file : " + std::string((LPCTSTR) fileDlg.GetPathName())).c_str(), "NeL object viewer", MB_OK|MB_ICONEXCLAMATION); } } catch (NLMISC::Exception& e) { MessageBox (e.what(), "NeL object viewer", MB_OK|MB_ICONEXCLAMATION); } } } void CWaterPoolEditor::OnSavePool() { static char BASED_CODE szFilter[] = "NeL Water Pool Files (*.wpf)|*.wpf||"; CFileDialog fileDlg( TRUE, ".wpf", "*.wpf", OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, szFilter); if (fileDlg.DoModal()==IDOK) { try { NLMISC::COXml oXml; NLMISC::COFile oF; if (oF.open((LPCTSTR) fileDlg.GetPathName())) { if (oXml.init (&oF)) { _Wpm->serial(oXml); oXml.flush(); oF.close(); } else { oF.close(); MessageBox (("Unable to init xml stream from file : " + std::string((LPCTSTR) fileDlg.GetPathName())).c_str(), "NeL object viewer", MB_OK|MB_ICONEXCLAMATION); } } else { MessageBox (("Unable to open file : " + std::string((LPCTSTR) fileDlg.GetPathName())).c_str(), "NeL object viewer", MB_OK|MB_ICONEXCLAMATION); } } catch (NLMISC::Exception& e) { MessageBox (e.what(), "NeL object viewer", MB_OK|MB_ICONEXCLAMATION); } } } void CWaterPoolEditor::OnRenamePool() { CChoosePoolID cpi(true); cpi.PoolID = getCurrentPoolID(); cpi.Name = getCurrentPool().getName(); if (cpi.DoModal() == IDOK) { getCurrentPool().setName(cpi.Name); fillPoolList(); } }