11#include " gui.h"
22#include < fmt/core.h>
33#include < imgui.h>
4+ #include < platform/windows/utils/platform_tools.h>
45#include " config.h"
56#include " imgui/imgui_impl_opengl3.h"
67#include " imgui/imgui_impl_sdl.h"
78#include " platform/windows/input/key.h"
89#include " platform/windows/gui/icons.h"
910#include " system.h"
11+ #include " state/state.h"
1012#include " utils/file.h"
1113#include " utils/string.h"
14+ #include " images.h"
15+
16+ float GUI::scale = 1 .f;
1217
1318GUI::GUI (SDL_Window* window, void * glContext) : window(window) {
1419 ImGui::CreateContext ();
@@ -21,19 +26,19 @@ GUI::GUI(SDL_Window* window, void* glContext) : window(window) {
2126 io.ConfigFlags |= ImGuiConfigFlags_IsTouchScreen;
2227#endif
2328
24- float scaleFactor = 1 .f ;
29+ scale = 1 .f ;
2530#ifdef ANDROID
2631 float dpi = 1 .f ;
2732 if (SDL_GetDisplayDPI (0 , &dpi, nullptr , nullptr ) == 0 ) {
28- scaleFactor = dpi / 160 .f ;
33+ scale = dpi / 160 .f ;
2934 }
3035#endif
31- float fontSize = 16 .f * scaleFactor ;
36+ float fontSize = 16 .f * scale ;
3237
3338 ImGuiStyle& style = ImGui::GetStyle ();
3439 style.GrabRounding = 6 .f ;
3540 style.FrameRounding = 6 .f ;
36- style.ScaleAllSizes (scaleFactor );
41+ style.ScaleAllSizes (scale );
3742#ifdef ANDROID
3843 style.TouchExtraPadding = ImVec2 (10 .f , 10 .f );
3944#endif
@@ -51,7 +56,7 @@ GUI::GUI(SDL_Window* window, void* glContext) : window(window) {
5156
5257 {
5358 ImFontConfig config;
54- config.SizePixels = 13 .f * scaleFactor ;
59+ config.SizePixels = 13 .f * scale ;
5560 io.Fonts ->AddFontDefault (&config);
5661 }
5762
@@ -85,6 +90,13 @@ void GUI::mainMenu(std::unique_ptr<System>& sys) {
8590 }
8691 if (ImGui::BeginMenu (" File" )) {
8792 ImGui::MenuItem (" Open" , nullptr , &openFile.openWindowOpen );
93+ #if defined(__APPLE__) || defined(__WIN32__) || defined(__WIN64__) || defined(__linux__)
94+ ImGui::Separator ();
95+ if (ImGui::MenuItem (" Open Avocado directory" )) {
96+ openFileBrowser (avocado::PATH_USER.c_str ());
97+ }
98+ #endif
99+ ImGui::Separator ();
88100 if (ImGui::MenuItem (" Exit" , " Esc" )) bus.notify (Event::File::Exit{});
89101 ImGui::EndMenu ();
90102 }
@@ -112,7 +124,9 @@ void GUI::mainMenu(std::unique_ptr<System>& sys) {
112124 ImGui::Separator ();
113125
114126 if (ImGui::MenuItem (" Quick save" , " F5" )) bus.notify (Event::System::SaveState{});
115- if (ImGui::MenuItem (" Quick load" , " F7" )) bus.notify (Event::System::LoadState{});
127+
128+ bool quickLoadStateExists = fs::exists (state::getStatePath (sys.get ()));
129+ if (ImGui::MenuItem (" Quick load" , " F7" , nullptr , quickLoadStateExists)) bus.notify (Event::System::LoadState{});
116130
117131 if (ImGui::BeginMenu (" Save" )) {
118132 for (int i = 1 ; i <= 5 ; i++) {
@@ -122,8 +136,17 @@ void GUI::mainMenu(std::unique_ptr<System>& sys) {
122136 }
123137
124138 if (ImGui::BeginMenu (" Load" )) {
139+ bool anySaveExists = false ;
125140 for (int i = 1 ; i <= 5 ; i++) {
126- if (ImGui::MenuItem (fmt::format (" Slot {}##load" , i).c_str ())) bus.notify (Event::System::LoadState{i});
141+ auto path = state::getStatePath (sys.get (), i);
142+ if (fs::exists (path)) {
143+ anySaveExists = true ;
144+ if (ImGui::MenuItem (fmt::format (" Slot {}##load" , i).c_str ())) bus.notify (Event::System::LoadState{i});
145+ }
146+ }
147+
148+ if (!anySaveExists) {
149+ ImGui::TextUnformatted (" No save states" );
127150 }
128151 ImGui::EndMenu ();
129152 }
@@ -200,11 +223,27 @@ void GUI::mainMenu(std::unique_ptr<System>& sys) {
200223 ImGui::EndMenu ();
201224 }
202225
203- // Print info
204- auto info = fmt::format (" fps: {:.2f}" , 60 .f );
226+ std::string info;
227+ if (statusMouseLocked) {
228+ info += " | Press Alt to unlock mouse" ;
229+ }
230+ if (sys->state == System::State::pause) {
231+ info += " | Paused" ;
232+ } else {
233+ info += fmt::format (" | {:.0f} FPS" , statusFps);
234+ if (!statusFramelimitter) {
235+ info += " (Unlimited)" ;
236+ }
237+ }
205238 auto size = ImGui::CalcTextSize (info.c_str ());
206- ImGui::SameLine (ImGui::GetWindowWidth () - size.x * 1 . 2f );
239+ ImGui::SameLine (ImGui::GetWindowWidth () - size.x - ImGui::GetStyle (). FramePadding . x * 4 );
207240 ImGui::TextUnformatted (info.c_str ());
241+
242+ if (ImGui::IsItemHovered ()) {
243+ ImGui::BeginTooltip ();
244+ ImGui::TextUnformatted (fmt::format (" Frame time: {:.2f} ms\n Tab to disable frame limiting" , (1000.0 / statusFps)).c_str ());
245+ ImGui::EndTooltip ();
246+ }
208247 ImGui::EndMainMenuBar ();
209248}
210249
@@ -262,6 +301,9 @@ void GUI::render(std::unique_ptr<System>& sys) {
262301
263302 drawControls (sys);
264303
304+ // Work in progress
305+ // renderController();
306+
265307 ImGui::Render ();
266308 ImGui_ImplOpenGL3_RenderDrawData (ImGui::GetDrawData ());
267309}
@@ -339,8 +381,10 @@ void GUI::drawControls(std::unique_ptr<System>& sys) {
339381
340382 symbolButton (" Save/Load" , ICON_FA_SAVE);
341383 if (ImGui::BeginPopupContextItem (nullptr , 0 )) {
342- if (ImGui::Selectable (" Quick load" )) bus.notify (Event::System::LoadState{});
343- ImGui::Separator ();
384+ if (fs::exists (state::getStatePath (sys.get ()))) {
385+ if (ImGui::Selectable (" Quick load" )) bus.notify (Event::System::LoadState{});
386+ ImGui::Separator ();
387+ }
344388 if (ImGui::Selectable (" Quick save" )) bus.notify (Event::System::SaveState{});
345389 ImGui::EndPopup ();
346390 }
@@ -381,4 +425,38 @@ void GUI::drawControls(std::unique_ptr<System>& sys) {
381425
382426 ImGui::End ();
383427 ImGui::PopStyleVar (3 );
384- }
428+ }
429+
430+ void GUI::renderController () {
431+ ImDrawList* drawList = ImGui::GetBackgroundDrawList ();
432+ float size = 64 .f ;
433+ auto button = [drawList, size](const char * button, float _x, float _y) {
434+ auto btn = getImage (button, avocado::assetsPath (" buttons/" ));
435+ if (!btn) return ;
436+ // AddImage(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min = ImVec2(0, 0), const
437+ // ImVec2& uv_max = ImVec2(1, 1), ImU32 col = IM_COL32_WHITE);
438+ float x = ImGui::GetIO ().DisplaySize .x * _x;
439+ float y = ImGui::GetIO ().DisplaySize .y * lerp (0 .3f , 0 .6f , _y);
440+ float r = size / 2 * 1.2 ;
441+
442+ drawList->AddCircleFilled (ImVec2 (x, y), r, ImColor (0 , 0 , 0 , 128 ));
443+ drawList->AddImage ((ImTextureID)btn->id , ImVec2 (x - size / 2 , y - size / 2 ), ImVec2 (x + size / 2 , y + size / 2 ), ImVec2 (0 , 0 ),
444+ ImVec2 (1 , 1 ), ImColor (0xff , 0xff , 0xff , 192 ));
445+ };
446+
447+ float COL = 1 .f / 12 .f ;
448+ float ROW = 1 .f / 3 .f ;
449+
450+ button (" dpad_up" , 2 * COL, 1 * ROW);
451+ button (" dpad_left" , 1 * COL, 2 * ROW);
452+ button (" dpad_right" , 3 * COL, 2 * ROW);
453+ button (" dpad_down" , 2 * COL, 3 * ROW);
454+
455+ button (" select" , 5 * COL, 3 * ROW);
456+ button (" start" , 7 * COL, 3 * ROW);
457+
458+ button (" triangle" , 1 - 2 * COL, 1 * ROW);
459+ button (" square" , 1 - 1 * COL, 2 * ROW);
460+ button (" circle" , 1 - 3 * COL, 2 * ROW);
461+ button (" cross" , 1 - 2 * COL, 3 * ROW);
462+ }
0 commit comments