@@ -53,19 +53,42 @@ void EditorWindow::_openProject(const std::filesystem::path& filename)
5353 gizmo->Load ();
5454 }
5555
56- TVITEMA item{};
57- item.mask = TVIF_TEXT | TVIF_PARAM ;
58- item.pszText = const_cast <char *>(object->Name .c_str ());
59- item.cChildren = 0 ;
60- item.lParam = i;
56+ ++i;
57+ }
6158
62- TVINSERTSTRUCTA insertStruct{};
63- insertStruct.item = item;
59+ for (int i = 0 ; auto & instance : *(editor->Objects ))
60+ {
61+ auto object = instance.Object .get ();
62+
63+ if (!object->HasParent ())
64+ {
65+ TVITEMA item{};
66+ item.mask = TVIF_TEXT | TVIF_PARAM ;
67+ item.pszText = const_cast <char *>(object->Name .c_str ());
68+ item.cChildren = 1 ;
69+ item.lParam = i;
6470
65- SendMessageA (_treeView, TVM_INSERTITEMA , 0 , reinterpret_cast <LPARAM >(&insertStruct));
71+ TVINSERTSTRUCTA insertStruct{};
72+ insertStruct.item = item;
6673
67- ++i;
74+ SendMessageA (_treeView, TVM_INSERTITEMA , 0 , reinterpret_cast <LPARAM >(&insertStruct));
75+ }
76+ else
77+ {
78+ TVITEMA item{};
79+ item.mask = TVIF_TEXT | TVIF_PARAM ;
80+ item.pszText = const_cast <char *>(object->Name .c_str ());
81+ item.cChildren = 1 ;
82+ item.lParam = i;
83+
84+ TVINSERTSTRUCTA insertStruct{};
85+ // TODO: identify parent object then insert into an parent item
86+
87+ SendMessageA (_treeView, TVM_INSERTITEMA , 0 , reinterpret_cast <LPARAM >(&insertStruct));
88+ }
6889 }
90+
91+ _addRecentProject (filename);
6992}
7093
7194void EditorWindow::_saveProject (const std::filesystem::path &filename)
@@ -101,6 +124,7 @@ void EditorWindow::_writeProject(const std::filesystem::path& fileName)
101124 _changesSaved = true ;
102125 _currentFile = fileName;
103126 Serializer::SaveProject (editor->Objects .get (), editor->Content .get (), fileName);
127+ _addRecentProject (fileName);
104128}
105129
106130void EditorWindow::_findUpdate ()
@@ -319,7 +343,7 @@ EditorWindow::EditorWindow(HINSTANCE hInstance,const std::string &cmdArgs) :
319343 wndclass.hInstance = hInstance;
320344 wndclass.lpfnWndProc = EditorWindow_WndProc;
321345 wndclass.lpszClassName = EditorWindowClassName;
322- wndclass.hIcon = LoadIconA (hInstance,MAKEINTRESOURCEA (IDI_ICON1 ));
346+ wndclass.hIcon = LoadIconA (hInstance, MAKEINTRESOURCEA (IDI_ICON1 ));
323347 wndclass.hCursor = LoadCursorA (nullptr , MAKEINTRESOURCEA (32512 )); // IDI_ARROW
324348
325349 ATOM a = RegisterClassA (&wndclass);
@@ -333,23 +357,27 @@ EditorWindow::EditorWindow(HINSTANCE hInstance,const std::string &cmdArgs) :
333357 if (recentProjectsMenu == nullptr ) throw Exception (" Failed to create File > Recent files menu!" );
334358
335359 std::ifstream recent_projects (RecentProjectFile);
336- // Create the file if it doesn't exist or if it is empty
337- if (recent_projects.bad () || recent_projects.fail ())
338- {
339- std::ofstream create_recent_projects (RecentProjectFile);
340- create_recent_projects.close ();
341360
342- AppendMenuA (recentProjectsMenu, MF_STRING , 0 , " ..." );
361+ int recentCount = 0 ;
362+ if (recent_projects.is_open ()) {
363+ // Loop each line
364+ for (int i = 0 ; recent_projects && i < 10 ; i++)
365+ {
366+ std::string filename;
367+ std::getline (recent_projects, filename);
368+ if (!filename.empty ())
369+ {
370+ _recentFiles.push_back (filename);
371+ AppendMenuA (recentProjectsMenu, MF_STRING , CMD_OpenRecentFile1 + static_cast <UINT_PTR >(i), filename.c_str ());
372+ recentCount++;
373+ }
374+ }
375+ recent_projects.close ();
343376 }
344- // Loop each line
345- for (int i = 0 ; recent_projects; i++)
346- {
347- std::string filename;
348- std::getline (recent_projects, filename);
349- if (!filename.empty ())
350- AppendMenuA (recentProjectsMenu, MF_STRING , CMD_OpenRecentFile1 + static_cast <UINT_PTR >(i), filename.c_str ());
377+
378+ if (recentCount == 0 ) {
379+ AppendMenuA (recentProjectsMenu, MF_STRING | MF_GRAYED , 0 , " No recent projects" );
351380 }
352- recent_projects.close ();
353381
354382 // Create the rest of the menu.
355383 HMENU fileMenu = CreateMenu ();
@@ -489,7 +517,7 @@ EditorWindow::EditorWindow(HINSTANCE hInstance,const std::string &cmdArgs) :
489517 " " ,
490518 WS_CHILD | WS_VISIBLE | WS_BORDER ,
491519 0 ,
492- 0 ,
520+ 0 ,
493521 150 ,
494522 600 ,
495523 _mainWindow,
@@ -650,6 +678,38 @@ void EditorWindow::SelectObject(std::optional<unsigned> id)
650678
651679void SetWorkingDirectory ();
652680
681+ void EditorWindow::OpenRecentProject (uint8_t id)
682+ {
683+ if (id >= _recentFiles.size ()) return ;
684+
685+ SetWorkingDirectory ();
686+ gEditorWindow ->_openProject (gEditorWindow ->_recentFiles [id]);
687+ }
688+
689+ void EditorWindow::_addRecentProject (const std::filesystem::path& filename)
690+ {
691+ // Remove if already present
692+ auto it = std::find (_recentFiles.begin (), _recentFiles.end (), filename);
693+ if (it != _recentFiles.end ())
694+ _recentFiles.erase (it);
695+
696+ // Add to end
697+ _recentFiles.push_back (filename);
698+
699+ // Keep only 10 recent files
700+ if (_recentFiles.size () > 10 )
701+ _recentFiles.erase (_recentFiles.begin ());
702+
703+ // Only write if there are recent files
704+ if (!_recentFiles.empty ()) {
705+ SetWorkingDirectory ();
706+ std::ofstream recent_projects (RecentProjectFile, std::ios::trunc);
707+ for (const auto & file : _recentFiles)
708+ recent_projects << file.string () << std::endl;
709+ recent_projects.close ();
710+ }
711+ }
712+
653713LRESULT __stdcall EditorWindow_WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
654714{
655715 switch (msg)
@@ -719,24 +779,34 @@ LRESULT __stdcall EditorWindow_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARA
719779 }
720780
721781 case CMD_OpenRecentFile1:
782+ gEditorWindow ->OpenRecentProject (0 );
722783 break ;
723784 case CMD_OpenRecentFile1 + 1 :
785+ gEditorWindow ->OpenRecentProject (1 );
724786 break ;
725787 case CMD_OpenRecentFile1 + 2 :
788+ gEditorWindow ->OpenRecentProject (2 );
726789 break ;
727790 case CMD_OpenRecentFile1 + 3 :
791+ gEditorWindow ->OpenRecentProject (3 );
728792 break ;
729793 case CMD_OpenRecentFile1 + 4 :
794+ gEditorWindow ->OpenRecentProject (4 );
730795 break ;
731796 case CMD_OpenRecentFile1 + 5 :
797+ gEditorWindow ->OpenRecentProject (5 );
732798 break ;
733799 case CMD_OpenRecentFile1 + 6 :
800+ gEditorWindow ->OpenRecentProject (6 );
734801 break ;
735802 case CMD_OpenRecentFile1 + 7 :
803+ gEditorWindow ->OpenRecentProject (7 );
736804 break ;
737805 case CMD_OpenRecentFile1 + 8 :
806+ gEditorWindow ->OpenRecentProject (8 );
738807 break ;
739808 case CMD_OpenRecentFile1 + 9 :
809+ gEditorWindow ->OpenRecentProject (9 );
740810 break ;
741811
742812 case CMD_SaveProject:
@@ -988,6 +1058,7 @@ LRESULT __stdcall EditorWindow_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARA
9881058 HMENU objectMenu = CreatePopupMenu ();
9891059 if (objectMenu == nullptr ) throw std::exception (" Failed to create a popup menu!" );
9901060
1061+ AppendMenuA (objectMenu, MF_STRING , CMD_AddChildObject, " Add child object" );
9911062 AppendMenuA (objectMenu, MF_STRING , CMD_EditObject, " Edit object" );
9921063 AppendMenuA (objectMenu, MF_STRING , CMD_DeselectObject, " Deselect object" );
9931064 AppendMenuA (objectMenu, MF_STRING , CMD_DeleteObject, " Delete object" );
0 commit comments