Merge branch 'fixes' into main/rendor-staging
[ryzomcore.git] / nel / tools / 3d / object_viewer / snapshot_tool_dlg.cpp
blobded81bdcd2fa81413d57f5fbdda5221acb5ecbb4
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2019-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "std_afx.h"
22 #include "object_viewer.h"
23 #include "main_frame.h"
24 #include "snapshot_tool_dlg.h"
25 #include "choose_name.h"
26 #include "object_viewer.h"
28 #include "nel/misc/path.h"
29 #include "nel/misc/algo.h"
30 #include "nel/misc/file.h"
32 #include "nel/3d/u_scene.h"
33 #include "nel/3d/u_driver.h"
35 #include "nel/3d/driver.h"
36 #include "nel/3d/driver_user.h"
37 #include "nel/3d/shape_bank.h"
38 #include "nel/3d/camera.h"
39 #include "nel/3d/texture_multi_file.h"
40 #include "nel/3d/mesh_base.h"
41 #include "nel/3d/particle_system.h"
42 #include "nel/3d/particle_system_shape.h"
43 #include "nel/3d/particle_system_model.h"
48 #define NEL_OV_SNAPSHOT_TOOL_REGKEY _T("Software\\Nevrax\\nel\\object_viewer\\snapshot_dlg")
51 using namespace NLMISC;
52 using namespace NL3D;
54 /////////////////////////////////////////////////////////////////////////////
55 // CSnapshotToolDlg dialog
57 //****************************************************************************************
58 CSnapshotToolDlg::CSnapshotToolDlg(CObjectViewer *ov, CWnd* pParent /*=NULL*/)
59 : CDialog(CSnapshotToolDlg::IDD, pParent)
61 nlassert(ov);
62 _ObjectViewer = ov;
63 //{{AFX_DATA_INIT(CSnapshotToolDlg)
64 m_OutputPath = _T("");
65 m_InputPath = _T("");
66 m_RecurseSubFolder = FALSE;
67 m_OutputHeight = 100;
68 m_OutputWidth = 160;
69 m_Format = -1;
70 m_OutputPathOption = -1;
71 m_DumpTextureSets = FALSE;
72 m_ViewBack = FALSE;
73 m_ViewBottom = FALSE;
74 m_ViewFront = FALSE;
75 m_ViewLeft = FALSE;
76 m_ViewRight = FALSE;
77 m_ViewTop = FALSE;
78 m_PostFixViewName = FALSE;
79 //}}AFX_DATA_INIT
82 //****************************************************************************************
83 CSnapshotToolDlg::~CSnapshotToolDlg()
87 //****************************************************************************************
88 void CSnapshotToolDlg::DoDataExchange(CDataExchange* pDX)
90 CDialog::DoDataExchange(pDX);
91 //{{AFX_DATA_MAP(CSnapshotToolDlg)
92 DDX_Control(pDX, IDC_LOG, m_Log);
93 DDX_Control(pDX, IDC_FILTERS, m_Filters);
94 DDX_Text(pDX, IDC_OUTPUT_PATH, m_OutputPath);
95 DDX_Text(pDX, IDC_INPUT_PATH, m_InputPath);
96 DDX_Check(pDX, IDC_RECURSE_SUBFOLDER, m_RecurseSubFolder);
97 DDX_Text(pDX, IDC_HEIGHT, m_OutputHeight);
98 DDV_MinMaxUInt(pDX, m_OutputHeight, 1, 1024);
99 DDX_Text(pDX, IDC_WIDTH, m_OutputWidth);
100 DDV_MinMaxUInt(pDX, m_OutputWidth, 1, 1024);
101 DDX_CBIndex(pDX, IDC_FORMAT, m_Format);
102 DDX_CBIndex(pDX, IDC_OUTPUTPATH_OPTION, m_OutputPathOption);
103 DDX_Check(pDX, IDC_DUMP_TEXTURE_SETS, m_DumpTextureSets);
104 DDX_Check(pDX, IDC_VIEW_BACK, m_ViewBack);
105 DDX_Check(pDX, IDC_VIEW_BOTTOM, m_ViewBottom);
106 DDX_Check(pDX, IDC_VIEW_FRONT, m_ViewFront);
107 DDX_Check(pDX, IDC_VIEW_LEFT, m_ViewLeft);
108 DDX_Check(pDX, IDC_VIEW_RIGHT, m_ViewRight);
109 DDX_Check(pDX, IDC_VIEW_TOP, m_ViewTop);
110 DDX_Check(pDX, IDC_POSTFIX_VIEWNAME, m_PostFixViewName);
111 //}}AFX_DATA_MAP
114 //****************************************************************************************
115 void CSnapshotToolDlg::stringFromRegistry(HKEY hKey, const TCHAR *name, CString &dest, const CString &defaultStr)
117 DWORD type;
118 DWORD size;
119 LONG result = RegQueryValueEx(hKey, name, NULL, &type, NULL, &size);
121 if (type != REG_SZ || result != ERROR_SUCCESS || size == 0)
123 dest = defaultStr;
124 return;
127 std::vector<TCHAR> tmpDest(size);
128 result = RegQueryValueEx(hKey, name, NULL, &type, (BYTE*)&tmpDest[0], &size);
130 if (result != ERROR_SUCCESS)
132 dest = defaultStr;
133 return;
136 dest = &tmpDest[0];
140 //****************************************************************************************
141 template <class T, class U> void integralTypeFromRegistry(HKEY hKey, const TCHAR *name, T &dest, const U &defaultValue)
143 if (hKey == 0)
145 dest = defaultValue;
146 return;
148 DWORD type;
149 DWORD size;
150 LONG result = RegQueryValueEx(hKey, name, NULL, &type, NULL, &size);
152 if (type != REG_DWORD || result != ERROR_SUCCESS || size == 0)
154 dest = (T) defaultValue;
155 return;
158 DWORD value;
159 result = RegQueryValueEx(hKey, name, NULL, &type, LPBYTE(&value), &size);
161 if (result != ERROR_SUCCESS)
163 dest = defaultValue;
164 return;
167 dest = (T) value;
171 //****************************************************************************************
172 void CSnapshotToolDlg::fromRegistry()
174 HKEY hKey = 0;
175 RegOpenKeyEx(HKEY_CURRENT_USER, NEL_OV_SNAPSHOT_TOOL_REGKEY, 0, KEY_READ, &hKey);
176 stringFromRegistry(hKey, _T("InputPath"), m_InputPath, "");
177 stringFromRegistry(hKey, _T("OutputPath"), m_OutputPath, "");
179 CString filters;
180 stringFromRegistry(hKey, _T("Filters"), filters, "*.shape");
182 std::vector<std::string> filterList;
183 NLMISC::splitString(tStrToUtf8(filters), ",", filterList);
185 m_Filters.ResetContent();
187 for (uint k = 0; k < filterList.size(); ++k)
189 m_Filters.AddString(nlUtf8ToTStr(filterList[k]));
192 integralTypeFromRegistry(hKey, _T("RecurseSubFolder"), (int &) m_RecurseSubFolder, FALSE);
193 integralTypeFromRegistry(hKey, _T("DumpTextureSets"), (int &) m_DumpTextureSets, TRUE);
194 integralTypeFromRegistry(hKey, _T("PostFixViewName"), (int &) m_PostFixViewName, TRUE);
195 integralTypeFromRegistry(hKey, _T("ViewBack"), (int &) m_ViewBack, FALSE);
196 integralTypeFromRegistry(hKey, _T("ViewBottom"), (int &) m_ViewBottom, FALSE);
197 integralTypeFromRegistry(hKey, _T("ViewFront"), (int &) m_ViewFront, TRUE);
198 integralTypeFromRegistry(hKey, _T("ViewLeft"), (int &) m_ViewLeft, FALSE);
199 integralTypeFromRegistry(hKey, _T("ViewRight"), (int &) m_ViewRight, FALSE);
200 integralTypeFromRegistry(hKey, _T("ViewTop"), (int &) m_ViewTop, FALSE);
201 integralTypeFromRegistry(hKey, _T("OutputWidth"), m_OutputWidth, 128);
202 integralTypeFromRegistry(hKey, _T("OutputHeight"), m_OutputHeight, 128);
203 integralTypeFromRegistry(hKey, _T("Format"), m_Format, 0);
204 integralTypeFromRegistry(hKey, _T("OutputPathOption"), m_OutputPathOption, 1);
205 UpdateData(FALSE);
206 updateUIEnabledState();
209 //****************************************************************************************
210 void CSnapshotToolDlg::toRegistry()
212 UpdateData();
213 HKEY hKey;
214 if (RegCreateKey(HKEY_CURRENT_USER, NEL_OV_SNAPSHOT_TOOL_REGKEY, &hKey)==ERROR_SUCCESS)
216 RegSetValueEx(hKey, _T("InputPath"), 0, REG_SZ, (BYTE*) (LPCTSTR) m_InputPath, (m_InputPath.GetLength() + 1) * sizeof(TCHAR));
217 RegSetValueEx(hKey, _T("OutputPath"), 0, REG_SZ, (BYTE*) (LPCTSTR) m_OutputPath, (m_OutputPath.GetLength() + 1) * sizeof(TCHAR));
218 CString filters;
219 for (uint k = 0; k < (uint) m_Filters.GetCount(); ++k)
221 if (k!=0) filters += ",";
222 CString filter;
223 m_Filters.GetText(k, filter);
224 filters += filter;
227 RegSetValueEx(hKey, _T("Filters"), 0, REG_SZ, (BYTE*) (LPCTSTR) filters, (filters.GetLength() + 1) * sizeof(TCHAR));
228 DWORD recurseSubFolder = m_RecurseSubFolder;
229 DWORD dumpTextureSets = m_DumpTextureSets;
230 DWORD width = (DWORD) m_OutputWidth;
231 DWORD height = (DWORD) m_OutputHeight;
232 DWORD format = m_Format;
233 DWORD outputPathOption = m_OutputPathOption;
234 DWORD postFixViewName = m_PostFixViewName;
235 integralTypeFromRegistry(hKey, _T("PostFixViewName"), (int &) m_PostFixViewName, TRUE);
236 RegSetValueEx(hKey, _T("ViewBack"), 0, REG_DWORD, (const BYTE *) &m_ViewBack, sizeof(DWORD));
237 RegSetValueEx(hKey, _T("ViewBottom"), 0, REG_DWORD, (const BYTE *) &m_ViewBottom, sizeof(DWORD));
238 RegSetValueEx(hKey, _T("ViewFront"), 0, REG_DWORD, (const BYTE *) &m_ViewFront, sizeof(DWORD));
239 RegSetValueEx(hKey, _T("ViewLeft"), 0, REG_DWORD, (const BYTE *) &m_ViewLeft, sizeof(DWORD));
240 RegSetValueEx(hKey, _T("ViewRight"), 0, REG_DWORD, (const BYTE *) &m_ViewRight, sizeof(DWORD));
241 RegSetValueEx(hKey, _T("ViewTop"), 0, REG_DWORD, (const BYTE *) &m_ViewTop, sizeof(DWORD));
242 RegSetValueEx(hKey, _T("RecurseSubFolder"), 0, REG_DWORD, (const BYTE *) &recurseSubFolder, sizeof(DWORD));
243 RegSetValueEx(hKey, _T("DumpTextureSets"), 0, REG_DWORD, (const BYTE *) &dumpTextureSets, sizeof(DWORD));
244 RegSetValueEx(hKey, _T("OutputWidth"), 0, REG_DWORD, (const BYTE *) &width, sizeof(DWORD));
245 RegSetValueEx(hKey, _T("OutputHeight"), 0, REG_DWORD, (const BYTE *) &height, sizeof(DWORD));
246 RegSetValueEx(hKey, _T("Format"), 0, REG_DWORD, (const BYTE *) &format, sizeof(DWORD));
247 RegSetValueEx(hKey, _T("OutputPathOption"), 0, REG_DWORD, (const BYTE *) &outputPathOption, sizeof(DWORD));
252 BEGIN_MESSAGE_MAP(CSnapshotToolDlg, CDialog)
253 //{{AFX_MSG_MAP(CSnapshotToolDlg)
254 ON_BN_CLICKED(IDC_BROWSE_INPUT_PATH, OnBrowseInputPath)
255 ON_BN_CLICKED(IDC_BROWSE_OUTPUT_PATH, OnBrowseOutputPath)
256 ON_BN_CLICKED(IDC_GO, OnGo)
257 ON_BN_CLICKED(IDC_ADD_FILTER, OnAddFilter)
258 ON_BN_CLICKED(IDC_REMOVE_FILTER, OnRemoveFilter)
259 ON_BN_CLICKED(IDC_EDIT_FILTER, OnEditFilter)
260 ON_WM_CLOSE()
261 ON_EN_CHANGE(IDC_WIDTH, OnChangeWidth)
262 ON_EN_KILLFOCUS(IDC_HEIGHT, OnKillfocusHeight)
263 ON_EN_KILLFOCUS(IDC_WIDTH, OnKillfocusWidth)
264 ON_CBN_SELCHANGE(IDC_OUTPUTPATH_OPTION, OnSelchangeOutputpathOption)
265 ON_CBN_SELCHANGE(IDC_FORMAT, OnSelchangeFormat)
266 ON_BN_CLICKED(IDC_CLOSE, OnCloseButton)
267 ON_WM_TIMER()
268 ON_BN_CLICKED(IDC_STOP, OnStopSnapshots)
269 ON_BN_CLICKED(IDC_VIEW_FRONT, OnViewFront)
270 ON_BN_CLICKED(IDC_VIEW_LEFT, OnViewLeft)
271 ON_BN_CLICKED(IDC_VIEW_RIGHT, OnViewRight)
272 ON_BN_CLICKED(IDC_VIEW_TOP, OnViewTop)
273 ON_BN_CLICKED(IDC_VIEW_ALL, OnViewAll)
274 ON_BN_CLICKED(IDC_VIEW_NONE, OnViewNone)
275 ON_BN_CLICKED(IDC_POSTFIX_VIEWNAME, OnPostFixViewName)
276 //}}AFX_MSG_MAP
277 END_MESSAGE_MAP()
279 /////////////////////////////////////////////////////////////////////////////
280 // CSnapshotToolDlg message handlers
283 //****************************************************************************************
284 BOOL CSnapshotToolDlg::OnInitDialog()
286 CDialog::OnInitDialog();
287 fromRegistry();
288 SetTimer(1, 10, NULL);
289 return TRUE; // return TRUE unless you set the focus to a control
290 // EXCEPTION: OCX Property Pages should return FALSE
293 //****************************************************************************************
294 void CSnapshotToolDlg::OnClose()
296 toRegistry();
297 CDialog::OnClose();
301 //****************************************************************************************
302 void CSnapshotToolDlg::OnBrowseInputPath()
304 browseFolder(getStrRsc(IDS_CHOOSE_SNAPSHOT_INPUT_PATH), m_InputPath, this->m_hWnd);
305 UpdateData(FALSE);
306 toRegistry();
309 //****************************************************************************************
310 void CSnapshotToolDlg::OnBrowseOutputPath()
312 browseFolder(getStrRsc(IDS_CHOOSE_SNAPSHOT_OUTPUT_PATH), m_OutputPath, this->m_hWnd);
313 UpdateData(FALSE);
314 toRegistry();
318 //****************************************************************************************
319 void CSnapshotToolDlg::OnAddFilter()
321 CChooseName cn("*.shape", this);
322 if (cn.DoModal() == IDOK && !cn.m_Name.IsEmpty())
324 m_Filters.AddString(cn.m_Name);
326 toRegistry();
329 //****************************************************************************************
330 void CSnapshotToolDlg::OnRemoveFilter()
332 if (m_Filters.GetCurSel() != LB_ERR)
334 m_Filters.DeleteString(m_Filters.GetCurSel());
339 //****************************************************************************************
340 void CSnapshotToolDlg::OnEditFilter()
342 if (m_Filters.GetCurSel() != LB_ERR)
344 CString current;
345 m_Filters.GetText(m_Filters.GetCurSel(), current);
346 CChooseName cn((LPCTSTR) current, this);
347 if (cn.DoModal() == IDOK && !cn.m_Name.IsEmpty())
349 int curSel = m_Filters.GetCurSel();
350 m_Filters.DeleteString(m_Filters.GetCurSel());
351 m_Filters.InsertString(curSel, cn.m_Name);
352 m_Filters.SetCurSel(curSel);
355 toRegistry();
359 //****************************************************************************************
360 uint CSnapshotToolDlg::getSelectedViewCount()
362 UpdateData();
363 return (m_ViewBack ? 1 : 0) +
364 (m_ViewBottom ? 1 : 0) +
365 (m_ViewFront ? 1 : 0) +
366 (m_ViewLeft ? 1 : 0) +
367 (m_ViewRight ? 1 : 0) +
368 (m_ViewTop ? 1 : 0);
371 //****************************************************************************************
372 void CSnapshotToolDlg::updateUIEnabledState()
374 BOOL enabled = _FilteredFiles.empty() ? TRUE : FALSE;
375 m_Filters.EnableWindow(enabled);
376 GetDlgItem(IDC_INPUT_PATH)->EnableWindow(enabled);
377 GetDlgItem(IDC_BROWSE_INPUT_PATH)->EnableWindow(enabled);
378 GetDlgItem(IDC_OUTPUT_PATH)->EnableWindow(enabled && m_OutputPathOption == OutputPath_Custom);
379 GetDlgItem(IDC_BROWSE_OUTPUT_PATH)->EnableWindow(enabled);
380 GetDlgItem(IDC_RECURSE_SUBFOLDER)->EnableWindow(enabled);
381 GetDlgItem(IDC_OUTPUTPATH_OPTION)->EnableWindow(enabled);
382 GetDlgItem(IDC_FILTERS)->EnableWindow(enabled);
383 GetDlgItem(IDC_ADD_FILTER)->EnableWindow(enabled);
384 GetDlgItem(IDC_REMOVE_FILTER)->EnableWindow(enabled);
385 GetDlgItem(IDC_EDIT_FILTER)->EnableWindow(enabled);
386 GetDlgItem(IDC_WIDTH)->EnableWindow(enabled);
387 GetDlgItem(IDC_HEIGHT)->EnableWindow(enabled);
388 GetDlgItem(IDC_FORMAT)->EnableWindow(enabled);
389 GetDlgItem(IDC_GO)->EnableWindow(enabled);
390 GetDlgItem(IDC_DUMP_TEXTURE_SETS)->EnableWindow(enabled);
391 GetDlgItem(IDC_STOP)->EnableWindow(!enabled);
392 GetDlgItem(IDC_POSTFIX_VIEWNAME)->EnableWindow((enabled && getSelectedViewCount() == 1) ? TRUE : FALSE);
393 //GetDlgItem(IDC_CLOSE)->EnaleWindow(enabled);
397 //****************************************************************************************
398 void CSnapshotToolDlg::OnGo()
400 UpdateData();
401 if (getSelectedViewCount() == 0)
403 MessageBox(getStrRsc(IDS_SNAPSHOT_NO_VIEW_SELECTED), getStrRsc(IDS_OBJECT_VIEWER), MB_ICONEXCLAMATION);
404 return;
406 if (m_InputPath.IsEmpty())
408 MessageBox(getStrRsc(IDS_SNAPSHOT_EMPTY_INPUT_PATH), getStrRsc(IDS_OBJECT_VIEWER), MB_ICONEXCLAMATION);
409 return;
411 if (!NLMISC::CFile::isDirectory(tStrToUtf8(m_InputPath)))
413 MessageBox(getStrRsc(IDS_SNAPSHOT_EMPTY_INPUT_PATH_NOT_FOUND), getStrRsc(IDS_OBJECT_VIEWER), MB_ICONEXCLAMATION);
414 return;
416 if (m_OutputPathOption == OutputPath_Custom && m_OutputPath.IsEmpty())
418 MessageBox(getStrRsc(IDS_SNAPSHOT_EMPTY_OUTPUT_PATH), getStrRsc(IDS_OBJECT_VIEWER), MB_ICONEXCLAMATION);
419 return;
421 if (m_OutputPathOption == OutputPath_Custom && !NLMISC::CFile::isDirectory(tStrToUtf8(m_OutputPath)))
423 if (MessageBox(getStrRsc(IDS_SNAPSHOT_CREATE_OUTPUT_DIRECTORY), getStrRsc(IDS_OBJECT_VIEWER), MB_OKCANCEL) != IDOK)
425 return;
427 if(!NLMISC::CFile::createDirectoryTree(tStrToUtf8(m_OutputPath)))
429 MessageBox(getStrRsc(IDS_SNAPSHOT_OUTPUT_PATH_CREATION_FAILED), getStrRsc(IDS_OBJECT_VIEWER), MB_ICONEXCLAMATION);
430 return;
434 // make sure that the screen can contains the window client area
435 RECT desktopSize;
436 ::GetClientRect(::GetDesktopWindow(), &desktopSize);
437 if (desktopSize.right < LONG(m_OutputWidth) ||
438 desktopSize.bottom < LONG(m_OutputHeight))
440 MessageBox(getStrRsc(IDS_DESKTOP_TOO_SMALL_FOR_SNAPSHOT), getStrRsc(IDS_OBJECT_VIEWER), MB_ICONEXCLAMATION);
441 return;
444 m_Log.ResetContent();
445 m_Log.AddString(getStrRsc(IDS_GETTING_PATH_CONTENT));
446 std::vector<std::string> files;
447 CPath::getPathContent(tStrToUtf8(m_InputPath), m_RecurseSubFolder == TRUE, false, true, files);
448 if (files.empty())
450 m_Log.AddString(getStrRsc(IDS_SNAPSHOT_NO_FILES_FOUND));
451 return;
453 _FilteredFiles.clear();
454 for (uint k = 0; k < files.size(); ++k)
456 for (uint l = 0; l < uint(m_Filters.GetCount()); ++l)
458 CString wildCard;
459 m_Filters.GetText(l, wildCard);
460 wildCard.MakeLower();
461 if (testWildCard(toLowerAscii(NLMISC::CFile::getFilename(files[k])).c_str(), tStrToUtf8(wildCard).c_str()))
463 _FilteredFiles.push_back(files[k]);
464 break;
468 if (_FilteredFiles.empty())
470 m_Log.AddString(getStrRsc(IDS_SNAPSHOT_NO_FILTER_MATCH_FOUND));
471 return;
473 m_Log.AddString(toString("%d", (int) _FilteredFiles.size()).c_str() + getStrRsc(IDS_SNAPSHOT_FILES_TO_PROCESS));
474 updateUIEnabledState();
477 //****************************************************************************************
478 void CSnapshotToolDlg::OnChangeWidth()
480 // TODO: If this is a RICHEDIT control, the control will not
481 // send this notification unless you override the CDialog::OnInitDialog()
482 // function and call CRichEditCtrl().SetEventMask()
483 // with the ENM_CHANGE flag ORed into the mask.
485 // TODO: Add your control notification handler code here
489 //****************************************************************************************
490 void CSnapshotToolDlg::OnKillfocusHeight()
492 toRegistry();
495 //****************************************************************************************
496 void CSnapshotToolDlg::OnKillfocusWidth()
498 toRegistry();
501 //****************************************************************************************
502 void CSnapshotToolDlg::OnSelchangeOutputpathOption()
504 toRegistry();
505 updateUIEnabledState();
509 //****************************************************************************************
510 void CSnapshotToolDlg::OnSelchangeFormat()
512 toRegistry();
516 //****************************************************************************************
517 void CSnapshotToolDlg::OnCloseButton()
519 toRegistry();
520 SendMessage(WM_CLOSE);
523 //****************************************************************************************
524 void CSnapshotToolDlg::setCamFromView(uint view, CCamera *cam, const CAABBox &bbox)
526 static const CVector camBackDir[] =
528 -CVector::J,
529 CVector::I,
530 -CVector::I,
531 CVector::K,
532 -CVector::K,
533 CVector::J
535 const float viewDistScale = 3.f;
536 CVector halfSize = bbox.getHalfSize();
537 if (view == SnapshotAngle_Top) // top
539 CMatrix camMat;
540 camMat.setRot(CVector::I, -CVector::K, CVector::J);
541 camMat.setPos(bbox.getCenter() + viewDistScale * CVector::K);
542 cam->setMatrix(camMat);
544 else if (view == SnapshotAngle_Bottom)
546 CMatrix camMat;
547 camMat.setRot(CVector::I, CVector::K, -CVector::J);
548 camMat.setPos(bbox.getCenter() - viewDistScale * CVector::K);
549 cam->setMatrix(camMat);
551 else
553 // standard lookat for other directions
554 cam->lookAt(bbox.getCenter() + viewDistScale * maxof(halfSize.x, halfSize.y, halfSize.z) * camBackDir[view], bbox.getCenter());
558 //****************************************************************************************
559 std::string CSnapshotToolDlg::viewToString(uint view)
561 switch(view)
563 case SnapshotAngle_Front: return "front";
564 case SnapshotAngle_Right: return "right";
565 case SnapshotAngle_Left: return "left";
566 case SnapshotAngle_Top: return "top";
567 case SnapshotAngle_Bottom: return "bottom";
568 case SnapshotAngle_Back: return "back";
570 nlassert(0);
571 return "";
574 //****************************************************************************************
575 void CSnapshotToolDlg::OnTimer(UINT_PTR nIDEvent)
577 if (_FilteredFiles.empty()) return;
578 if (nIDEvent == 1)
580 // resize the window if needed
581 HWND wnd = (HWND) NL3D::CNELU::Driver->getDisplay();
582 CScene scene(true /* small scene */);
584 scene.initDefaultRoots();
585 scene.setDriver(CNELU::Driver);
586 scene.initQuadGridClipManager();
587 NL3D::CViewport vp;
588 vp.init(0.f, 0.f, 1.f, 1.f);
589 scene.setViewport(vp);
590 scene.enableLightingSystem(true);
591 scene.setAmbientGlobal(CRGBA::White);
593 CShapeBank sb;
594 scene.setShapeBank(&sb);
595 CCamera *cam= safe_cast<CCamera *>(scene.createModel(CameraId));
596 scene.setCam(cam);
597 cam->setFrustum(0.1f, 0.1f, 0.1f, 5000.f);
602 CShapeStream ss;
603 m_Log.AddString(nlUtf8ToTStr(_FilteredFiles[0]));
604 CIFile stream(_FilteredFiles[0]);
605 ss.serial(stream);
606 nlassert(ss.getShapePointer());
607 CAABBox bbox;
608 ss.getShapePointer()->getAABBox(bbox);
609 sb.add("shape", ss.getShapePointer());
610 CTransformShape *model = scene.createInstance("shape");
611 CMatrix initTM = model->getMatrix();
612 model->setTransformMode(CTransform::DirectMatrix);
613 initTM.setPos(CVector::Null);
614 model->setMatrix(initTM);
615 CVector newBBoxCenter = initTM * bbox.getCenter();
616 CVector newBBoxHalfSize = initTM.mulVector(bbox.getHalfSize());
617 bbox.setCenter(newBBoxCenter);
618 bbox.setHalfSize(newBBoxHalfSize);
619 if (model)
621 CMeshBaseInstance *mbi = dynamic_cast<CMeshBaseInstance *>(model);
622 uint textureSetCount = 1;
623 CMeshBase *mb = dynamic_cast<CMeshBase *>((IShape *) model->Shape);
624 CMesh *mesh = dynamic_cast<CMesh *>((IShape *) model->Shape);
625 if (m_DumpTextureSets && mbi)
627 if (mb)
629 const uint numMat = mb->getNbMaterial();
630 // see which material are selectable
631 for(uint k = 0; k < numMat; ++k)
633 CMaterial &mat = mb->getMaterial(k);
634 for(uint l = 0; l < IDRV_MAT_MAXTEXTURES; ++l)
636 CTextureMultiFile *tmf = dynamic_cast<CTextureMultiFile *>(mat.getTexture(l));
637 if (tmf)
639 textureSetCount = std::max(textureSetCount, (uint) tmf->getNumFileName());
645 // for particle systems : simulate until half duration, then capture bbox
646 CParticleSystemModel *psm = dynamic_cast<CParticleSystemModel *>(model);
647 if (psm)
649 psm->forceInstanciate();
650 CParticleSystem *ps = psm->getPS();
651 if (ps)
653 float duration = ps->evalDuration();
654 float deltaT = .5f * ps->getTimeTheshold();
655 for (float date = 0.f; date < duration * 0.5f; date += deltaT)
657 ps->setSysMat(&CMatrix::Identity);
658 ps->step(CParticleSystem::Anim, deltaT, *safe_cast<CParticleSystemShape *>((IShape *) psm->Shape), *psm);
660 ps->computeBBox(bbox);
664 cam->setTransformMode(ITransformable::DirectMatrix);
665 BOOL views[] =
667 m_ViewFront,
668 m_ViewRight,
669 m_ViewLeft,
670 m_ViewTop,
671 m_ViewBottom,
672 m_ViewBack
674 for (uint viewIndex = 0; viewIndex < 6; ++viewIndex)
676 if (!views[viewIndex]) continue;
677 setCamFromView(viewIndex, cam, bbox);
678 for (uint textureSet = 0; textureSet < textureSetCount; ++textureSet)
680 if (mbi)
682 mbi->selectTextureSet(textureSet);
685 CNELU::Driver->clear2D(_ObjectViewer->getBackGroundColor());
686 CNELU::Driver->clearZBuffer();
687 scene.render();
688 NLMISC::CBitmap snapshot;
689 CNELU::Driver->getBuffer(snapshot);
690 if (snapshot.getWidth() == 0 || snapshot.getHeight() == 0)
692 m_Log.AddString(getStrRsc(IDS_SNAPSHOT_NO_CONTENT_RETRIEVED));
694 else
696 snapshot.resample(m_OutputWidth, m_OutputHeight);
697 size_t lastPoint = _FilteredFiles[0].find_last_of('.');
698 std::string outputFilename = _FilteredFiles[0].substr(0, lastPoint);
699 if (textureSetCount > 1)
701 outputFilename += toString("_%u", (unsigned int) textureSet);
703 if (getSelectedViewCount() != 1 || m_PostFixViewName)
705 outputFilename += "_" + viewToString(viewIndex);
708 std::string ext;
709 switch (m_Format)
711 case OutputFormat_Tga:
712 ext = "tga";
713 break;
714 case OutputFormat_Png:
715 ext = "png";
716 break;
717 case OutputFormat_Jpg:
718 ext = "jpg";
719 break;
720 default:
721 nlerror("Unsupported format %d", m_Format);
722 break;
724 outputFilename += "." + ext;
726 switch(m_OutputPathOption)
728 case OutputPath_Custom: // custom output path
729 outputFilename = tStrToUtf8(m_OutputPath) + "\\" + NLMISC::CFile::getFilename(outputFilename);
730 break;
731 case OutputPath_SameAsInput: // Input path
732 outputFilename = tStrToUtf8(m_InputPath) + "\\" + NLMISC::CFile::getFilename(outputFilename);
733 break;
734 case OutputPath_CurrShapeDirectory: // current path
735 // no op
736 break;
738 COFile output(outputFilename);
740 if (m_Format == OutputFormat_Tga)
742 snapshot.writeTGA(output);
744 else if (m_Format == OutputFormat_Png)
746 snapshot.writePNG(output);
748 else
750 snapshot.writeJPG(output);
753 CNELU::Driver->swapBuffers();
756 scene.deleteInstance(model);
758 sb.reset();
760 catch(const std::exception &e)
762 nlwarning(e.what());
765 _FilteredFiles.pop_front();
766 if (_FilteredFiles.empty())
768 m_Log.AddString(getStrRsc(IDS_SNAPSHOT_FINISHED));
769 updateUIEnabledState();
772 CDialog::OnTimer(nIDEvent);
775 //****************************************************************************************
776 void CSnapshotToolDlg::OnStopSnapshots()
778 _FilteredFiles.clear();
779 updateUIEnabledState();
783 //****************************************************************************************
784 void CSnapshotToolDlg::OnViewFront()
786 toRegistry();
787 updateUIEnabledState();
790 //****************************************************************************************
791 void CSnapshotToolDlg::OnViewLeft()
793 toRegistry();
794 updateUIEnabledState();
797 //****************************************************************************************
798 void CSnapshotToolDlg::OnViewRight()
800 toRegistry();
801 updateUIEnabledState();
804 //****************************************************************************************
805 void CSnapshotToolDlg::OnViewTop()
807 toRegistry();
808 updateUIEnabledState();
811 //****************************************************************************************
812 void CSnapshotToolDlg::OnViewAll()
814 m_ViewBack = TRUE;
815 m_ViewBottom = TRUE;
816 m_ViewFront = TRUE;
817 m_ViewLeft = TRUE;
818 m_ViewRight = TRUE;
819 m_ViewTop = TRUE;
820 UpdateData(FALSE);
821 toRegistry();
822 updateUIEnabledState();
825 //****************************************************************************************
826 void CSnapshotToolDlg::OnViewNone()
828 m_ViewBack = FALSE;
829 m_ViewBottom = FALSE;
830 m_ViewFront = FALSE;
831 m_ViewLeft = FALSE;
832 m_ViewRight = FALSE;
833 m_ViewTop = FALSE;
834 UpdateData(FALSE);
835 toRegistry();
836 updateUIEnabledState();
839 //****************************************************************************************
840 void CSnapshotToolDlg::OnPostFixViewName()
842 toRegistry();