Skip to content
This repository has been archived by the owner on Sep 16, 2024. It is now read-only.

Commit

Permalink
UI prettification
Browse files Browse the repository at this point in the history
  • Loading branch information
OFFTKP committed Jan 3, 2024
1 parent 4ba7b52 commit 785e1bc
Show file tree
Hide file tree
Showing 6 changed files with 1,217 additions and 16 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ project(hydra

add_executable(hydra)

set(CMAKE_CXX_STANDARD 20 CACHE STRING "" FORCE)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
target_compile_features(hydra PRIVATE cxx_std_20)
set(WITH_APPS OFF CACHE BOOL "" FORCE)
set(BUILD_SHARED_LIBS OFF)
set(BUILD_STATIC_LIBS ON)
Expand Down Expand Up @@ -177,6 +176,7 @@ set(HYDRA_COMMON_FILES
vendored/stb_image_write.c
vendored/glad/src/glad.c
vendored/miniz/miniz.c
vendored/courier_prime.cxx
)

set(HYDRA_BOT_FILES
Expand Down
16 changes: 16 additions & 0 deletions include/mainwindow.hxx
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
#pragma once

#include "imgui.h"
#include <array>
#include <string>

struct Star
{
float x, y;
float vel_x, vel_y;
};

struct MainWindow
{
MainWindow();
void update();

private:
void draw_cores();
void draw_about();
void draw_settings();
void draw_stars(ImVec2 center, float radius);

float selected_y = 0.0f;
int selected_tab = 0;
std::string core_directory;
std::array<Star, 50> stars;
bool fancy_gui;
};
2 changes: 1 addition & 1 deletion include/settings.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ public:
core_info_initialized() = true;
if (Settings::Get("core_path").empty())
{
Settings::Set("core_path", (std::filesystem::current_path()).string());
Settings::Set("core_path", Settings::GetSavePath() / "cores");
}

if (!std::filesystem::exists(Settings::Get("core_path")))
Expand Down
8 changes: 8 additions & 0 deletions src/app.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ static void MainLoopForEmscripten()
#define EMSCRIPTEN_MAINLOOP_END
#endif

extern unsigned int CourierPrime_compressed_size;
extern unsigned int CourierPrime_compressed_data[44980 / 4];

int imgui_main(int argc, char** argv)
{
// TODO: Joystick
Expand Down Expand Up @@ -91,6 +94,11 @@ int imgui_main(int argc, char** argv)
ImGui_ImplOpenGL3_Init(glsl_version);
Settings::InitCoreIcons();

ImFont* font = io.Fonts->AddFontFromMemoryCompressedTTF(CourierPrime_compressed_data,
CourierPrime_compressed_size, 16.0f);
ImGui::GetIO().Fonts->Build();
ImGui::GetIO().FontDefault = font;

bool done = false;
std::unique_ptr<MainWindow> main_window = std::make_unique<MainWindow>();
#ifdef HYDRA_WEB
Expand Down
162 changes: 149 additions & 13 deletions src/mainwindow.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,76 @@
#include <cmrc/cmrc.hpp>
#include <imgui/imgui.h>
#include <imgui_url.hxx>
#include <numbers>
#include <settings.hxx>

CMRC_DECLARE(hydra);

constexpr int tab_count = 3;
constexpr const char* names[tab_count] = {"Cores", "Settings", "About"};

MainWindow::MainWindow()
{
selected_y = ImGui::GetStyle().WindowPadding.y + ImGui::GetStyle().ItemSpacing.y;
core_directory.resize(4096);
std::string core_dir = Settings::Get("core_path");
strncpy(core_directory.data(), core_dir.c_str(), core_directory.size());

if (core_dir.empty())
{
hydra::log("Core path is empty, shouldn't happen");
}

for (size_t i = 0; i < stars.size(); i++)
{
float angle = (rand() % 100) / 100.0f * 2.0f * std::numbers::pi;
float dist = (rand() % 100) / 100.0f * 50.0f;
stars[i].x = 50.0f + dist * cos(angle);
stars[i].y = 50.0f + dist * sin(angle);
stars[i].vel_x = ((rand() % 100) / 200.0f) - 0.25f;
stars[i].vel_y = ((rand() % 100) / 200.0f) - 0.25f;
}

if (Settings::Get("fancy_gui").empty())
{
Settings::Set("fancy_gui", "true");
}
fancy_gui = Settings::Get("fancy_gui") == "true";
}

void MainWindow::update()
{
ImGui::GetStyle().WindowRounding = 0.0f;
ImGui::BeginGroup();
float screen_height = ImGui::GetIO().DisplaySize.y;
float screen_width = ImGui::GetIO().DisplaySize.x;
float spacing = ImGui::GetStyle().WindowPadding.y * 2 + ImGui::GetStyle().ItemSpacing.y * 2;
ImVec2 tab_size = ImVec2(screen_width * 0.2f, (screen_height - spacing) / tab_count);
float target_y = selected_tab * tab_size.y + ImGui::GetStyle().WindowPadding.y +
ImGui::GetStyle().ItemSpacing.y;
selected_y = selected_y * 0.9f + target_y * 0.1f;
ImVec2 min(ImGui::GetCursorPosX(), selected_y);
ImVec2 max(tab_size.x + min.x, tab_size.y + min.y);
ImVec2 center = ImVec2(min.x + tab_size.x / 2, min.y + tab_size.y / 2);
float radius = std::min(tab_size.x, tab_size.y) * 0.5f;
draw_stars(center, radius);
ImGui::BeginGroup();
ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, ImVec2(0.5f, 0.5f));
if (ImGui::Selectable("Home", selected_tab == 0, 0, tab_size))
{
selected_tab = 0;
}
if (ImGui::Selectable("Settings", selected_tab == 1, 0, tab_size))
{
selected_tab = 1;
}
if (ImGui::Selectable("About", selected_tab == 2, 0, tab_size))
ImDrawList* draw_list = ImGui::GetWindowDrawList();
draw_list->AddCircle(center, radius, 0xFFFFFFFF, 32, 2.0f);

// We draw our own animated rectangle so disable these
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0, 0, 0, 0));
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0, 0, 0, 0));
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0, 0, 0, 0));
for (int i = 0; i < tab_count; i++)
{
selected_tab = 2;
if (ImGui::Selectable(names[i], selected_tab == i, ImGuiSelectableFlags_SpanAllColumns,
tab_size))
{
selected_tab = i;
}
}
ImGui::PopStyleColor(3);
ImGui::PopStyleVar();
ImGui::EndGroup();
ImGui::SameLine();
Expand Down Expand Up @@ -80,14 +123,22 @@ void MainWindow::update()
void MainWindow::draw_cores()
{
ImGui::Text("Cores");
ImGui::BeginChild("##cores", ImVec2(0, 0), ImGuiChildFlags_Border);
auto& cores = Settings::GetCoreInfo();
// Calculate the height of the above text and the input text below
float widget_height = ImGui::CalcTextSize("").y * 2 + ImGui::GetStyle().FramePadding.y * 2.0f +
ImGui::GetStyle().ItemSpacing.y * 2.0f;
ImGui::BeginChild("##cores", ImVec2(0, ImGui::GetWindowHeight() - widget_height),
ImGuiChildFlags_Border);
float image_width = ImGui::GetWindowWidth() * 0.1f;
image_width = std::min(image_width, 128.0f);
image_width = std::max(image_width, 64.0f);
for (size_t i = 0; i < cores.size(); i++)
{
ImGui::PushID(i);
ImGui::BeginChild("##core", ImVec2(0, 128 + ImGui::GetStyle().ItemSpacing.y * 4),
ImGuiChildFlags_Border);
ImGui::Image((ImTextureID)(intptr_t)cores[i].icon_texture, ImVec2(128, 128));
ImGui::Image((ImTextureID)(intptr_t)cores[i].icon_texture,
ImVec2(image_width, image_width));
ImGui::SameLine();
ImGui::BeginGroup();
ImGui::Text("%s %s (%s)\n", cores[i].core_name.c_str(), cores[i].version.c_str(),
Expand Down Expand Up @@ -117,11 +168,96 @@ void MainWindow::draw_cores()
ImGui::PopID();
}
ImGui::EndChild();

float button_width = ImGui::GetWindowWidth() * 0.2f;
button_width = std::min(button_width, 128.0f);
button_width = std::max(button_width, 64.0f);
ImGui::PushItemWidth(ImGui::GetWindowWidth() - button_width - ImGui::GetStyle().ItemSpacing.x);
ImGui::InputText("##coredir", core_directory.data(), core_directory.size(),
ImGuiInputTextFlags_ReadOnly);
ImGui::PopItemWidth();
ImGui::SameLine();
if (ImGui::Button("Browse", ImVec2(button_width, 0)))
{
}
}

void MainWindow::draw_about() {}

void MainWindow::draw_settings()
{
ImGui::Text("Settings");
if (ImGui::Checkbox("Enable fancy GUI", &fancy_gui))
{
Settings::Set("fancy_gui", fancy_gui ? "true" : "false");
}
ImGui::SetItemTooltip("Enable fancy GUI features that may hinder performance");
}

void MainWindow::draw_stars(ImVec2 center, float radius)
{
if (!fancy_gui)
return;

ImVec2 min(center.x - radius, center.y - radius);
ImVec2 max(center.x + radius, center.y + radius);
ImVec2 size(max.x - min.x, max.y - min.y);
for (size_t i = 0; i < stars.size(); i++)
{
float x = stars[i].x - 50.0f;
float y = stars[i].y - 50.0f;
float dist = sqrt(x * x + y * y);
if (dist > 50.0f)
{
stars[i].x = 50.0f;
stars[i].y = 50.0f;
}

float dx = (stars[i].x + stars[i].vel_x) - 50.0f;
float dy = (stars[i].y + stars[i].vel_y) - 50.0f;
float dist2 = sqrt(dx * dx + dy * dy);
if (dist2 > 50.0f)
{
float dot = dx * stars[i].vel_x + dy * stars[i].vel_y;
stars[i].vel_x -= 2.0f * dot * dx / (dist2 * dist2);
stars[i].vel_y -= 2.0f * dot * dy / (dist2 * dist2);
}

stars[i].x += stars[i].vel_x;
stars[i].y += stars[i].vel_y;

ImVec2 pos(min.x + size.x * stars[i].x / 100.0f, min.y + size.y * stars[i].y / 100.0f);
ImGui::GetWindowDrawList()->AddCircleFilled(pos, 0.2f, 0xCCCCCCCC);

for (size_t j = i + 1; j < stars.size(); j++)
{
float dist_x = stars[i].x - stars[j].x;
float dist_y = stars[i].y - stars[j].y;
float dist = sqrt(dist_x * dist_x + dist_y * dist_y);
float max_dist = 50.0f;
if (dist < max_dist)
{
uint32_t color = (uint32_t)(180.0f * (1.0f - dist / max_dist));
color = color << 24 | color << 16 | color << 8 | color;
ImVec2 pos2(min.x + size.x * stars[j].x / 100.0f,
min.y + size.y * stars[j].y / 100.0f);
ImGui::GetWindowDrawList()->AddLine(pos, pos2, color);
}
}

// Connect to cursor if close enough
// first check if cursor is in circle
float dist_x = stars[i].x - (ImGui::GetIO().MousePos.x - min.x) / size.x * 100.0f;
float dist_y = stars[i].y - (ImGui::GetIO().MousePos.y - min.y) / size.y * 100.0f;
dist = sqrt(dist_x * dist_x + dist_y * dist_y);

float max_dist = 40.0f;
if (dist < max_dist)
{
uint32_t color = 180.0f * (1.0f - dist / max_dist);
color = color << 24 | color << 16 | color << 8 | color;
ImVec2 pos2(ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y);
ImGui::GetWindowDrawList()->AddLine(pos, pos2, color);
}
}
}
Loading

0 comments on commit 785e1bc

Please sign in to comment.