Skip to content

Commit

Permalink
gui: moved fps to imgui statusbar
Browse files Browse the repository at this point in the history
images are now dpi scaled
do not show unused save states in load menu
  • Loading branch information
JaCzekanski committed Jun 6, 2020
1 parent e772a61 commit 03972a8
Show file tree
Hide file tree
Showing 11 changed files with 122 additions and 48 deletions.
3 changes: 1 addition & 2 deletions src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,7 @@ KeyBindings mouse() {
// clang-format on
} // namespace DefaultKeyBindings

const avocado_config_t defaultConfig;
avocado_config_t config = defaultConfig;
avocado_config_t config;

namespace avocado {
std::string PATH_DATA = "data/";
Expand Down
1 change: 1 addition & 0 deletions src/platform/windows/config_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ void saveConfigFile() {
void loadConfigFile() {
auto file = getFileContents(configPath());
if (file.empty()) {
config = avocado_config_t();
saveConfigFile();
return;
}
Expand Down
104 changes: 91 additions & 13 deletions src/platform/windows/gui/gui.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
#include "gui.h"
#include <fmt/core.h>
#include <imgui.h>
#include <platform/windows/utils/platform_tools.h>
#include "config.h"
#include "imgui/imgui_impl_opengl3.h"
#include "imgui/imgui_impl_sdl.h"
#include "platform/windows/input/key.h"
#include "platform/windows/gui/icons.h"
#include "system.h"
#include "state/state.h"
#include "utils/file.h"
#include "utils/string.h"
#include "images.h"

float GUI::scale = 1.f;

GUI::GUI(SDL_Window* window, void* glContext) : window(window) {
ImGui::CreateContext();
Expand All @@ -21,19 +26,19 @@ GUI::GUI(SDL_Window* window, void* glContext) : window(window) {
io.ConfigFlags |= ImGuiConfigFlags_IsTouchScreen;
#endif

float scaleFactor = 1.f;
scale = 1.f;
#ifdef ANDROID
float dpi = 1.f;
if (SDL_GetDisplayDPI(0, &dpi, nullptr, nullptr) == 0) {
scaleFactor = dpi / 160.f;
scale = dpi / 160.f;
}
#endif
float fontSize = 16.f * scaleFactor;
float fontSize = 16.f * scale;

ImGuiStyle& style = ImGui::GetStyle();
style.GrabRounding = 6.f;
style.FrameRounding = 6.f;
style.ScaleAllSizes(scaleFactor);
style.ScaleAllSizes(scale);
#ifdef ANDROID
style.TouchExtraPadding = ImVec2(10.f, 10.f);
#endif
Expand All @@ -51,7 +56,7 @@ GUI::GUI(SDL_Window* window, void* glContext) : window(window) {

{
ImFontConfig config;
config.SizePixels = 13.f * scaleFactor;
config.SizePixels = 13.f * scale;
io.Fonts->AddFontDefault(&config);
}

Expand Down Expand Up @@ -85,6 +90,13 @@ void GUI::mainMenu(std::unique_ptr<System>& sys) {
}
if (ImGui::BeginMenu("File")) {
ImGui::MenuItem("Open", nullptr, &openFile.openWindowOpen);
#if defined(__APPLE__) || defined(__WIN32__) || defined(__WIN64__) || defined(__linux__)
ImGui::Separator();
if (ImGui::MenuItem("Open Avocado directory")) {
openFileBrowser(avocado::PATH_USER.c_str());
}
#endif
ImGui::Separator();
if (ImGui::MenuItem("Exit", "Esc")) bus.notify(Event::File::Exit{});
ImGui::EndMenu();
}
Expand Down Expand Up @@ -112,7 +124,9 @@ void GUI::mainMenu(std::unique_ptr<System>& sys) {
ImGui::Separator();

if (ImGui::MenuItem("Quick save", "F5")) bus.notify(Event::System::SaveState{});
if (ImGui::MenuItem("Quick load", "F7")) bus.notify(Event::System::LoadState{});

bool quickLoadStateExists = fs::exists(state::getStatePath(sys.get()));
if (ImGui::MenuItem("Quick load", "F7", nullptr, quickLoadStateExists)) bus.notify(Event::System::LoadState{});

if (ImGui::BeginMenu("Save")) {
for (int i = 1; i <= 5; i++) {
Expand All @@ -122,8 +136,17 @@ void GUI::mainMenu(std::unique_ptr<System>& sys) {
}

if (ImGui::BeginMenu("Load")) {
bool anySaveExists = false;
for (int i = 1; i <= 5; i++) {
if (ImGui::MenuItem(fmt::format("Slot {}##load", i).c_str())) bus.notify(Event::System::LoadState{i});
auto path = state::getStatePath(sys.get(), i);
if (fs::exists(path)) {
anySaveExists = true;
if (ImGui::MenuItem(fmt::format("Slot {}##load", i).c_str())) bus.notify(Event::System::LoadState{i});
}
}

if (!anySaveExists) {
ImGui::TextUnformatted("No save states");
}
ImGui::EndMenu();
}
Expand Down Expand Up @@ -200,11 +223,27 @@ void GUI::mainMenu(std::unique_ptr<System>& sys) {
ImGui::EndMenu();
}

// Print info
auto info = fmt::format("fps: {:.2f}", 60.f);
std::string info;
if (statusMouseLocked) {
info += " | Press Alt to unlock mouse";
}
if (sys->state == System::State::pause) {
info += " | Paused";
} else {
info += fmt::format(" | {:.0f} FPS", statusFps);
if (!statusFramelimitter) {
info += " (Unlimited)";
}
}
auto size = ImGui::CalcTextSize(info.c_str());
ImGui::SameLine(ImGui::GetWindowWidth() - size.x * 1.2f);
ImGui::SameLine(ImGui::GetWindowWidth() - size.x - ImGui::GetStyle().FramePadding.x * 4);
ImGui::TextUnformatted(info.c_str());

if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::TextUnformatted(fmt::format("Frame time: {:.2f} ms\nTab to disable frame limiting", (1000.0 / statusFps)).c_str());
ImGui::EndTooltip();
}
ImGui::EndMainMenuBar();
}

Expand Down Expand Up @@ -262,6 +301,9 @@ void GUI::render(std::unique_ptr<System>& sys) {

drawControls(sys);

// Work in progress
// renderController();

ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
}
Expand Down Expand Up @@ -339,8 +381,10 @@ void GUI::drawControls(std::unique_ptr<System>& sys) {

symbolButton("Save/Load", ICON_FA_SAVE);
if (ImGui::BeginPopupContextItem(nullptr, 0)) {
if (ImGui::Selectable("Quick load")) bus.notify(Event::System::LoadState{});
ImGui::Separator();
if (fs::exists(state::getStatePath(sys.get()))) {
if (ImGui::Selectable("Quick load")) bus.notify(Event::System::LoadState{});
ImGui::Separator();
}
if (ImGui::Selectable("Quick save")) bus.notify(Event::System::SaveState{});
ImGui::EndPopup();
}
Expand Down Expand Up @@ -381,4 +425,38 @@ void GUI::drawControls(std::unique_ptr<System>& sys) {

ImGui::End();
ImGui::PopStyleVar(3);
}
}

void GUI::renderController() {
ImDrawList* drawList = ImGui::GetBackgroundDrawList();
float size = 64.f;
auto button = [drawList, size](const char* button, float _x, float _y) {
auto btn = getImage(button, avocado::assetsPath("buttons/"));
if (!btn) return;
// AddImage(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min = ImVec2(0, 0), const
// ImVec2& uv_max = ImVec2(1, 1), ImU32 col = IM_COL32_WHITE);
float x = ImGui::GetIO().DisplaySize.x * _x;
float y = ImGui::GetIO().DisplaySize.y * lerp(0.3f, 0.6f, _y);
float r = size / 2 * 1.2;

drawList->AddCircleFilled(ImVec2(x, y), r, ImColor(0, 0, 0, 128));
drawList->AddImage((ImTextureID)btn->id, ImVec2(x - size / 2, y - size / 2), ImVec2(x + size / 2, y + size / 2), ImVec2(0, 0),
ImVec2(1, 1), ImColor(0xff, 0xff, 0xff, 192));
};

float COL = 1.f / 12.f;
float ROW = 1.f / 3.f;

button("dpad_up", 2 * COL, 1 * ROW);
button("dpad_left", 1 * COL, 2 * ROW);
button("dpad_right", 3 * COL, 2 * ROW);
button("dpad_down", 2 * COL, 3 * ROW);

button("select", 5 * COL, 3 * ROW);
button("start", 7 * COL, 3 * ROW);

button("triangle", 1 - 2 * COL, 1 * ROW);
button("square", 1 - 1 * COL, 2 * ROW);
button("circle", 1 - 3 * COL, 2 * ROW);
button("cross", 1 - 2 * COL, 3 * ROW);
}
8 changes: 8 additions & 0 deletions src/platform/windows/gui/gui.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,20 @@ class GUI {

void mainMenu(std::unique_ptr<System>& sys);
void drawControls(std::unique_ptr<System>& sys);
void renderController();

public:
static float scale;

bool singleFrame = false;
bool showGui = true;
bool showMenu = true;

// Status
double statusFps = 0.0;
bool statusFramelimitter = true;
bool statusMouseLocked = false;

GUI(SDL_Window* window, void* glContext);
~GUI();

Expand Down
2 changes: 1 addition & 1 deletion src/platform/windows/gui/helper/file_dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ void FileDialog::display(bool& windowOpen) {
if (ImGui::Button("Open in Explorer")) {
openFileBrowser(path.string().c_str());
}
#elif defined(__LINUX__)
#elif defined(__linux__)
if (ImGui::Button("Open in file explorer")) {
openFileBrowser(path.string().c_str());
}
Expand Down
4 changes: 2 additions & 2 deletions src/platform/windows/gui/images.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ std::optional<Image> getImage(const std::string& filename, const std::string& pa
return image->second;
}

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

return loaded;
}
}
8 changes: 6 additions & 2 deletions src/platform/windows/gui/options/options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
#include <fmt/core.h>
#include <imgui.h>
#include <magic_enum.hpp>
#include <platform/windows/gui/gui.h>
#include "config.h"
#include "device/controller/controller_type.h"
#include "platform/windows/gui/filesystem.h"
#include "platform/windows/gui/gui.h"
#include "platform/windows/gui/images.h"
#include "platform/windows/input/sdl_input_manager.h"
#include "renderer/opengl/opengl.h"
Expand Down Expand Up @@ -169,6 +171,8 @@ void drawImage(const std::optional<Image> image, float w = 0.f, float h = 0.f) {
} else {
size = ImVec2((float)img->w, (float)img->h);
}
size.x *= GUI::scale;
size.y *= GUI::scale;
ImGui::Image((ImTextureID)(uintptr_t)img->id, size);
}
}
Expand Down Expand Up @@ -261,7 +265,7 @@ void controllerSetupWindow() {

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

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

if (currentType != ControllerType::none) {
drawImage(getImage(std::string(magic_enum::enum_name(currentType))), leftGroupWidth);
drawImage(getImage(std::string(magic_enum::enum_name(currentType))), leftGroupWidth / GUI::scale);
}
ImGui::EndChild();

Expand Down
34 changes: 8 additions & 26 deletions src/platform/windows/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,13 @@

#undef main

bool running = true;

// Warning: this method might have 1 or more milliseconds of inaccuracy.
void limitFramerate(std::unique_ptr<System>& sys, SDL_Window* window, bool framelimiter, bool ntsc, bool mouseLocked) {
double limitFramerate(bool framelimiter, bool ntsc) {
static double timeToSkip = 0;
static double counterFrequency = (double)SDL_GetPerformanceFrequency();
static double startTime = SDL_GetPerformanceCounter() / counterFrequency;
static double fps;
static double fpsTime = 0.0;
static double fps = 0;
static int deltaFrames = 0;

double currentTime = SDL_GetPerformanceCounter() / counterFrequency;
Expand Down Expand Up @@ -68,28 +66,9 @@ void limitFramerate(std::unique_ptr<System>& sys, SDL_Window* window, bool frame
fps = (double)deltaFrames / fpsTime;
deltaFrames = 0;
fpsTime = 0.0;

std::string title = "";
if (mouseLocked) {
title += "Press Alt to unlock mouse | ";
}

title += "Avocado";

if (sys->cdrom->disc) {
auto cdPath = sys->cdrom->disc->getFile();
if (!cdPath.empty()) {
title += " | " + getFilename(cdPath);
}
}

title += fmt::format(" | FPS: {:.0f} ({:.2f} ms) {}", fps, (1.0 / fps) * 1000.0, !framelimiter ? "unlimited" : "");

if (sys->state == System::State::pause) {
title += " | paused";
}
SDL_SetWindowTitle(window, title.c_str());
}

return fps;
}

void fatalError(const std::string& error) {
Expand Down Expand Up @@ -278,6 +257,7 @@ int main(int argc, char** argv) {
}
}

bool running = true;
bool frameLimitEnabled = true;
bool forceRedraw = false;

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

gui->statusFramelimitter = frameLimitEnabled;
gui->statusMouseLocked = inputManager->mouseLocked;
gui->render(sys);

SDL_GL_SwapWindow(window);

limitFramerate(sys, window, frameLimitEnabled, sys->gpu->isNtsc(), inputManager->mouseLocked);
gui->statusFps = limitFramerate(frameLimitEnabled, sys->gpu->isNtsc());
}
if (config.options.emulator.preserveState) {
state::saveLastState(sys.get());
Expand Down
2 changes: 1 addition & 1 deletion src/platform/windows/utils/platform_tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ void openFileBrowser(const char* path) {
system(fmt::format("open \"{}\"", path).c_str());
#elif defined(__WIN32__) || defined(__WIN64__)
system(fmt::format("explorer \"{}\"", path).c_str());
#elif defined(__LINUX__)
#elif defined(__linux__)
system(fmt::format("xdg-open \"{}\"", path).c_str());
#endif
}
2 changes: 1 addition & 1 deletion src/state/state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ bool loadFromFile(System* sys, const std::string& path) {
return state::load(sys, state);
}

std::string getStatePath(System* sys, int slot = 0) {
std::string getStatePath(System* sys, int slot) {
std::string name;
if (sys->cdrom->disc) {
std::string discPath = sys->cdrom->disc->getFile();
Expand Down
2 changes: 2 additions & 0 deletions src/state/state.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ struct System;
namespace state {
using SaveState = std::string;

std::string getStatePath(System* sys, int slot = 0);

SaveState save(System* sys);
bool load(System* sys, const SaveState& state);

Expand Down

0 comments on commit 03972a8

Please sign in to comment.