Skip to content

Commit 3ad10b2

Browse files
committed
gui: moved fps to imgui statusbar
images are now dpi scaled do not show unused save states in load menu
1 parent e772a61 commit 3ad10b2

File tree

9 files changed

+120
-46
lines changed

9 files changed

+120
-46
lines changed

src/config.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,7 @@ KeyBindings mouse() {
157157
// clang-format on
158158
} // namespace DefaultKeyBindings
159159

160-
const avocado_config_t defaultConfig;
161-
avocado_config_t config = defaultConfig;
160+
avocado_config_t config;
162161

163162
namespace avocado {
164163
std::string PATH_DATA = "data/";

src/platform/windows/config_parser.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ void saveConfigFile() {
8383
void loadConfigFile() {
8484
auto file = getFileContents(configPath());
8585
if (file.empty()) {
86+
config = avocado_config_t();
8687
saveConfigFile();
8788
return;
8889
}

src/platform/windows/gui/gui.cpp

Lines changed: 91 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
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

1318
GUI::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\nTab 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+
}

src/platform/windows/gui/gui.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,20 @@ class GUI {
4141

4242
void mainMenu(std::unique_ptr<System>& sys);
4343
void drawControls(std::unique_ptr<System>& sys);
44+
void renderController();
4445

4546
public:
47+
static float scale;
48+
4649
bool singleFrame = false;
4750
bool showGui = true;
4851
bool showMenu = true;
4952

53+
// Status
54+
double statusFps = 0.0;
55+
bool statusFramelimitter = true;
56+
bool statusMouseLocked = false;
57+
5058
GUI(SDL_Window* window, void* glContext);
5159
~GUI();
5260

src/platform/windows/gui/images.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ std::optional<Image> getImage(const std::string& filename, const std::string& pa
4646
return image->second;
4747
}
4848

49-
auto loaded = loadImage(fmt::format("{}/{}.png", path, filename));
49+
auto loaded = loadImage(fmt::format("{}{}.png", path, filename));
5050
images[path + filename] = loaded;
5151

5252
return loaded;
53-
}
53+
}

src/platform/windows/gui/options/options.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
#include <fmt/core.h>
33
#include <imgui.h>
44
#include <magic_enum.hpp>
5+
#include <platform/windows/gui/gui.h>
56
#include "config.h"
67
#include "device/controller/controller_type.h"
78
#include "platform/windows/gui/filesystem.h"
9+
#include "platform/windows/gui/gui.h"
810
#include "platform/windows/gui/images.h"
911
#include "platform/windows/input/sdl_input_manager.h"
1012
#include "renderer/opengl/opengl.h"
@@ -169,6 +171,8 @@ void drawImage(const std::optional<Image> image, float w = 0.f, float h = 0.f) {
169171
} else {
170172
size = ImVec2((float)img->w, (float)img->h);
171173
}
174+
size.x *= GUI::scale;
175+
size.y *= GUI::scale;
172176
ImGui::Image((ImTextureID)(uintptr_t)img->id, size);
173177
}
174178
}
@@ -261,7 +265,7 @@ void controllerSetupWindow() {
261265

262266
auto currentType = config.controller[selectedController - 1].type;
263267

264-
const float leftGroupWidth = 256.f;
268+
const float leftGroupWidth = 192.f * GUI::scale;
265269
ImGui::BeginGroup();
266270
ImGui::BeginChild("##controller_image", ImVec2(leftGroupWidth, -ImGui::GetFrameHeightWithSpacing()));
267271
ImGui::Text("Type");
@@ -280,7 +284,7 @@ void controllerSetupWindow() {
280284
ImGui::PopItemWidth();
281285

282286
if (currentType != ControllerType::none) {
283-
drawImage(getImage(std::string(magic_enum::enum_name(currentType))), leftGroupWidth);
287+
drawImage(getImage(std::string(magic_enum::enum_name(currentType))), leftGroupWidth / GUI::scale);
284288
}
285289
ImGui::EndChild();
286290

src/platform/windows/main.cpp

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,13 @@
2828

2929
#undef main
3030

31-
bool running = true;
32-
3331
// Warning: this method might have 1 or more milliseconds of inaccuracy.
34-
void limitFramerate(std::unique_ptr<System>& sys, SDL_Window* window, bool framelimiter, bool ntsc, bool mouseLocked) {
32+
double limitFramerate(bool framelimiter, bool ntsc) {
3533
static double timeToSkip = 0;
3634
static double counterFrequency = (double)SDL_GetPerformanceFrequency();
3735
static double startTime = SDL_GetPerformanceCounter() / counterFrequency;
38-
static double fps;
3936
static double fpsTime = 0.0;
37+
static double fps = 0;
4038
static int deltaFrames = 0;
4139

4240
double currentTime = SDL_GetPerformanceCounter() / counterFrequency;
@@ -68,28 +66,9 @@ void limitFramerate(std::unique_ptr<System>& sys, SDL_Window* window, bool frame
6866
fps = (double)deltaFrames / fpsTime;
6967
deltaFrames = 0;
7068
fpsTime = 0.0;
71-
72-
std::string title = "";
73-
if (mouseLocked) {
74-
title += "Press Alt to unlock mouse | ";
75-
}
76-
77-
title += "Avocado";
78-
79-
if (sys->cdrom->disc) {
80-
auto cdPath = sys->cdrom->disc->getFile();
81-
if (!cdPath.empty()) {
82-
title += " | " + getFilename(cdPath);
83-
}
84-
}
85-
86-
title += fmt::format(" | FPS: {:.0f} ({:.2f} ms) {}", fps, (1.0 / fps) * 1000.0, !framelimiter ? "unlimited" : "");
87-
88-
if (sys->state == System::State::pause) {
89-
title += " | paused";
90-
}
91-
SDL_SetWindowTitle(window, title.c_str());
9269
}
70+
71+
return fps;
9372
}
9473

9574
void fatalError(const std::string& error) {
@@ -278,6 +257,7 @@ int main(int argc, char** argv) {
278257
}
279258
}
280259

260+
bool running = true;
281261
bool frameLimitEnabled = true;
282262
bool forceRedraw = false;
283263

@@ -384,11 +364,13 @@ int main(int argc, char** argv) {
384364
SDL_GL_GetDrawableSize(window, &opengl->width, &opengl->height);
385365
opengl->render(sys->gpu.get());
386366

367+
gui->statusFramelimitter = frameLimitEnabled;
368+
gui->statusMouseLocked = inputManager->mouseLocked;
387369
gui->render(sys);
388370

389371
SDL_GL_SwapWindow(window);
390372

391-
limitFramerate(sys, window, frameLimitEnabled, sys->gpu->isNtsc(), inputManager->mouseLocked);
373+
gui->statusFps = limitFramerate(frameLimitEnabled, sys->gpu->isNtsc());
392374
}
393375
if (config.options.emulator.preserveState) {
394376
state::saveLastState(sys.get());

src/state/state.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ bool loadFromFile(System* sys, const std::string& path) {
119119
return state::load(sys, state);
120120
}
121121

122-
std::string getStatePath(System* sys, int slot = 0) {
122+
std::string getStatePath(System* sys, int slot) {
123123
std::string name;
124124
if (sys->cdrom->disc) {
125125
std::string discPath = sys->cdrom->disc->getFile();

src/state/state.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ struct System;
66
namespace state {
77
using SaveState = std::string;
88

9+
std::string getStatePath(System* sys, int slot = 0);
10+
911
SaveState save(System* sys);
1012
bool load(System* sys, const SaveState& state);
1113

0 commit comments

Comments
 (0)