ImGui Hello World

This commit is contained in:
TheBrokenRail 2024-11-20 12:22:36 -05:00
parent fc7ecd528a
commit 0b542701c5
17 changed files with 235 additions and 80 deletions

View File

@ -13,12 +13,18 @@ add_executable(launcher
src/logger/crash-report.cpp src/logger/crash-report.cpp
src/options/parser.cpp src/options/parser.cpp
src/main.cpp src/main.cpp
src/ui/frame.cpp
src/client/configuration.cpp src/client/configuration.cpp
src/client/cache.cpp src/client/cache.cpp
src/client/available-feature-flags # Show In IDE src/client/available-feature-flags # Show In IDE
) )
embed_resource(launcher src/client/available-feature-flags) embed_resource(launcher src/client/available-feature-flags)
target_link_libraries(launcher reborn-util LIB_LIEF trampoline-headers) target_link_libraries(launcher
reborn-util
LIB_LIEF
imgui
trampoline-headers
)
# RPath # RPath
set_target_properties(launcher PROPERTIES INSTALL_RPATH "$ORIGIN/lib/native") set_target_properties(launcher PROPERTIES INSTALL_RPATH "$ORIGIN/lib/native")
target_link_options(launcher PRIVATE "LINKER:--disable-new-dtags") target_link_options(launcher PRIVATE "LINKER:--disable-new-dtags")

View File

@ -45,7 +45,6 @@ FALSE Remove Forced GUI Lag (Can Break Joining Servers)
TRUE Add Buckets TRUE Add Buckets
TRUE Classic HUD TRUE Classic HUD
TRUE Translucent Toolbar TRUE Translucent Toolbar
FALSE Force EGL
TRUE Improved Classic Title Screen TRUE Improved Classic Title Screen
FALSE Disable Speed Bridging FALSE Disable Speed Bridging
FALSE Disable Creative Mode Mining Delay FALSE Disable Creative Mode Mining Delay

View File

@ -12,6 +12,7 @@
#include "../util/util.h" #include "../util/util.h"
#include "configuration.h" #include "configuration.h"
#include "cache.h" #include "cache.h"
#include "../ui/frame.h"
// Strip Feature Flag Default // Strip Feature Flag Default
std::string strip_feature_flag_default(const std::string &flag, bool *default_ret) { std::string strip_feature_flag_default(const std::string &flag, bool *default_ret) {
@ -38,8 +39,7 @@ std::string strip_feature_flag_default(const std::string &flag, bool *default_re
} }
// Load Available Feature Flags // Load Available Feature Flags
extern unsigned char available_feature_flags[]; EMBEDDED_RESOURCE(available_feature_flags);
extern size_t available_feature_flags_len;
void load_available_feature_flags(const std::function<void(std::string)> &callback) { void load_available_feature_flags(const std::function<void(std::string)> &callback) {
// Load Data // Load Data
const std::string data(available_feature_flags, available_feature_flags + available_feature_flags_len); const std::string data(available_feature_flags, available_feature_flags + available_feature_flags_len);
@ -149,12 +149,27 @@ void handle_non_launch_client_only_commands(const options_t &options) {
} }
} }
struct Test final : Frame {
Test(): Frame(DIALOG_TITLE, 640, 480) {}
int render() override {
ImGui::Button("Hello World!");
ImGui::PushFont(monospace);
ImGui::Button("Custom Font");
ImGui::PopFont();
return 0;
}
};
// Configure Client Options // Configure Client Options
#define LIST_DIALOG_SIZE "400" #define LIST_DIALOG_SIZE "400"
void configure_client(const options_t &options) { void configure_client(const options_t &options) {
// Load Cache // Load Cache
launcher_cache cache = options.no_cache ? empty_cache : load_cache(); launcher_cache cache = options.no_cache ? empty_cache : load_cache();
Test *test = new Test;
test->run();
delete test;
// --default // --default
if (options.use_default) { if (options.use_default) {
// Use Default Feature Flags // Use Default Feature Flags

87
launcher/src/ui/frame.cpp Normal file
View File

@ -0,0 +1,87 @@
#include "frame.h"
#include <imgui_impl_glfw.h>
#include <imgui_impl_opengl2.h>
#include <libreborn/libreborn.h>
// Init/Cleanup
Frame::Frame(const char *title, const int width, const int height) {
// Create Window
init_glfw();
window = create_glfw_window(title, width, height);
// V-Sync
glfwSwapInterval(1);
// Setup ImGui Context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO &io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
io.IniFilename = nullptr;
io.LogFilename = nullptr;
// Setup Platform/Renderer Backends
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL2_Init();
}
Frame::~Frame() {
ImGui_ImplOpenGL2_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
cleanup_glfw(window);
}
// Run Loop
int Frame::run() {
int ret = 0;
constexpr ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
while (!glfwWindowShouldClose(window) || ret != 0) {
glfwPollEvents();
// Update Style
static float last_scale = -1.0f;
float scale;
get_glfw_scale(window, &scale, nullptr);
if (scale != last_scale) {
last_scale = scale;
setup_style(scale);
}
// Start Frame
ImGui_ImplOpenGL2_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
// Main Window
ImGui::SetNextWindowPos({0, 0});
int width, height;
glfwGetFramebufferSize(window, &width, &height);
ImGui::SetNextWindowSize({float(width), float(height)});
if (ImGui::Begin("###Main", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse)) {
ret = render();
}
ImGui::End();
// Render To OpenGL
ImGui::Render();
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
glfwSwapBuffers(window);
}
return ret;
}
// Style
EMBEDDED_RESOURCE(Roboto_Medium_ttf);
EMBEDDED_RESOURCE(Cousine_Regular_ttf);
void Frame::setup_style(const float scale) {
// Fonts
const ImGuiIO &io = ImGui::GetIO();
io.Fonts->Clear();
ImFontConfig font_cfg;
font_cfg.FontDataOwnedByAtlas = false;
io.Fonts->AddFontFromMemoryTTF(Roboto_Medium_ttf, int(Roboto_Medium_ttf_len), 24.0f * scale, &font_cfg);
monospace = io.Fonts->AddFontFromMemoryTTF(Cousine_Regular_ttf, int(Cousine_Regular_ttf_len), 18.0f * scale, &font_cfg);
// Style
ImGuiStyle &style = ImGui::GetStyle();
style = ImGuiStyle();
style.WindowBorderSize = 0;
ImGui::StyleColorsDark(&style);
style.ScaleAllSizes(scale);
}

21
launcher/src/ui/frame.h Normal file
View File

@ -0,0 +1,21 @@
#pragma once
#include <imgui.h>
#include <GLFW/glfw3.h>
// UI Frame
struct Frame {
Frame(const char *title, int width, int height);
virtual ~Frame();
// Run
int run();
virtual int render() = 0;
// Properties
protected:
ImFont *monospace = nullptr;
private:
GLFWwindow *window = nullptr;
// Internal
float get_scale();
void setup_style(float scale);
};

View File

@ -14,6 +14,10 @@ add_library(reborn-util SHARED
src/util/env.cpp src/util/env.cpp
) )
target_link_libraries(reborn-util PRIVATE utf8cpp) target_link_libraries(reborn-util PRIVATE utf8cpp)
if(TARGET glfw)
target_sources(reborn-util PRIVATE src/util/glfw.cpp)
target_link_libraries(reborn-util PRIVATE glfw)
endif()
setup_header_dirs(reborn-util setup_header_dirs(reborn-util
"${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/include"
"${CMAKE_CURRENT_BINARY_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}/include"

View File

@ -0,0 +1,11 @@
#pragma once
// GLFW Helpers
#ifdef GLFW_VERSION_MAJOR
void init_glfw();
GLFWwindow *create_glfw_window(const char *title, int width, int height);
void cleanup_glfw(GLFWwindow *window);
void get_glfw_scale(GLFWwindow *window, float *x_scale, float *y_scale);
#endif

View File

@ -7,3 +7,4 @@
#include "string.h" #include "string.h"
#include "exec.h" #include "exec.h"
#include "patch.h" #include "patch.h"
#include "glfw.h"

View File

@ -3,7 +3,7 @@
#include <string> #include <string>
// Patching Functions // Patching Functions
#if defined(REBORN_HAS_PATCH_CODE) #ifdef REBORN_HAS_PATCH_CODE
// Init // Init
void reborn_init_patch(); void reborn_init_patch();

View File

@ -74,4 +74,9 @@ const char *get_home_subdirectory_for_game_data();
void ensure_directory(const char *path); void ensure_directory(const char *path);
// Safe write() // Safe write()
void safe_write(int fd, const void *buf, size_t size); void safe_write(int fd, const void *buf, size_t size);
// embed_resource()
#define EMBEDDED_RESOURCE(name) \
extern unsigned char name[]; \
extern size_t name##_len

View File

@ -0,0 +1,68 @@
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <libreborn/glfw.h>
#include <libreborn/util.h>
#include <libreborn/log.h>
#include <libreborn/config.h>
// Handle GLFW Error
static void glfw_error(__attribute__((unused)) int error, const char *description) {
WARN("GLFW Error: %s", description);
}
// Init
void init_glfw() {
reborn_check_display();
glfwSetErrorCallback(glfw_error);
if (!glfwInit()) {
ERR("Unable To Initialize GLFW");
}
}
// Create Window
GLFWwindow *create_glfw_window(const char *title, const int width, const int height) {
// App ID
glfwWindowHintString(GLFW_X11_CLASS_NAME, MCPI_APP_ID);
glfwWindowHintString(GLFW_WAYLAND_APP_ID, MCPI_APP_ID);
// Create Window
GLFWwindow *window = glfwCreateWindow(width, height, title, nullptr, nullptr);
if (!window) {
ERR("Unable To Create GLFW Window");
}
// Make Window Context Current
glfwMakeContextCurrent(window);
// Return
return window;
}
// Cleanup
void cleanup_glfw(GLFWwindow *window) {
// Ignore GLFW Errors During Termination
glfwSetErrorCallback(nullptr);
// Terminate GLFW
glfwDestroyWindow(window);
glfwTerminate();
}
// Framebuffer Scaling
void get_glfw_scale(GLFWwindow *window, float *x_scale, float *y_scale) {
// Get Window Size
int window_width;
int window_height;
glfwGetWindowSize(window, &window_width, &window_height);
if (window_width <= 0 || window_height <= 0) {
return;
}
// Get Framebuffer Size
int framebuffer_width;
int framebuffer_height;
glfwGetFramebufferSize(window, &framebuffer_width, &framebuffer_height);
// Calculate Scale
if (x_scale) {
*x_scale = float(framebuffer_width) / float(window_width);
}
if (y_scale) {
*y_scale = float(framebuffer_height) / float(window_height);
}
}

View File

@ -179,23 +179,13 @@ static void convert_to_pixels(GLFWwindow *window, double *xpos, double *ypos) {
if (media_SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_ON && raw_mouse_motion_enabled) { if (media_SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_ON && raw_mouse_motion_enabled) {
return; return;
} }
// Get Window Size // Get Scale
int window_width; float x_scale = 1;
int window_height; float y_scale = 1;
glfwGetWindowSize(window, &window_width, &window_height); get_glfw_scale(window, &x_scale, &y_scale);
if (window_width <= 0 || window_height <= 0) {
return;
}
// Get Framebuffer Size
int framebuffer_width;
int framebuffer_height;
glfwGetFramebufferSize(window, &framebuffer_width, &framebuffer_height);
// Calculate Ratios
const double width_ratio = double(framebuffer_width) / double(window_width);
const double height_ratio = double(framebuffer_height) / double(window_height);
// Multiply // Multiply
*xpos *= width_ratio; *xpos *= x_scale;
*ypos *= height_ratio; *ypos *= y_scale;
} }
// Last Mouse Location // Last Mouse Location

View File

@ -7,11 +7,6 @@
// Window // Window
GLFWwindow *glfw_window = nullptr; GLFWwindow *glfw_window = nullptr;
// Handle GLFW Error
static void glfw_error(__attribute__((unused)) int error, const char *description) {
WARN("GLFW Error: %s", description);
}
// Disable V-Sync // Disable V-Sync
static bool disable_vsync = false; static bool disable_vsync = false;
void media_disable_vsync() { void media_disable_vsync() {
@ -21,15 +16,6 @@ void media_disable_vsync() {
} }
} }
// Force EGL
static int force_egl = 0;
void media_force_egl() {
if (force_egl == -1) {
IMPOSSIBLE();
}
force_egl = 1;
}
// Init Media Layer // Init Media Layer
#define GL_VERSION 0x1f02 #define GL_VERSION 0x1f02
typedef const char *(*glGetString_t)(unsigned int name); typedef const char *(*glGetString_t)(unsigned int name);
@ -40,39 +26,20 @@ void media_SDL_WM_SetCaption(const char *title, __attribute__((unused)) const ch
} }
// Init GLFW // Init GLFW
reborn_check_display(); init_glfw();
glfwSetErrorCallback(glfw_error);
if (!glfwInit()) {
ERR("Unable To Initialize GLFW");
}
// Create OpenGL Context // Create OpenGL Context
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 1); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 1);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
// Use EGL
if (force_egl) {
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
}
force_egl = -1;
// Extra Settings // Extra Settings
glfwWindowHint(GLFW_AUTO_ICONIFY, GLFW_FALSE); glfwWindowHint(GLFW_AUTO_ICONIFY, GLFW_FALSE);
glfwWindowHint(GLFW_ALPHA_BITS, 0); // Fix Transparent Window On Wayland
// App ID
glfwWindowHintString(GLFW_X11_CLASS_NAME, MCPI_APP_ID);
glfwWindowHintString(GLFW_WAYLAND_APP_ID, MCPI_APP_ID);
// Create Window // Create Window
glfw_window = glfwCreateWindow(DEFAULT_WIDTH, DEFAULT_HEIGHT, title, nullptr, nullptr); glfw_window = create_glfw_window(title, DEFAULT_WIDTH, DEFAULT_HEIGHT);
if (!glfw_window) {
ERR("Unable To Create GLFW Window");
}
// Event Handlers // Event Handlers
_media_register_event_listeners(); _media_register_event_listeners();
// Make Window Context Current
glfwMakeContextCurrent(glfw_window);
// Debug // Debug
const glGetString_t glGetString = (glGetString_t) glfwGetProcAddress("glGetString"); const glGetString_t glGetString = (glGetString_t) glfwGetProcAddress("glGetString");
DEBUG("Using OpenGL %s", (*glGetString)(GL_VERSION)); DEBUG("Using OpenGL %s", (*glGetString)(GL_VERSION));
@ -93,12 +60,8 @@ void media_SDL_WM_SetCaption(const char *title, __attribute__((unused)) const ch
// Cleanup Media Layer // Cleanup Media Layer
void media_cleanup() { void media_cleanup() {
if (glfw_window) { if (glfw_window) {
// Ignore GLFW Errors During Termination
glfwSetErrorCallback(nullptr);
// Terminate GLFW // Terminate GLFW
glfwDestroyWindow(glfw_window); cleanup_glfw(glfw_window);
glfwTerminate();
// Cleanup OpenAL // Cleanup OpenAL
_media_audio_cleanup(); _media_audio_cleanup();

View File

@ -1,11 +1,11 @@
#pragma once #pragma once
#include <SDL/SDL.h>
#include <libreborn/libreborn.h>
#define GLFW_INCLUDE_NONE #define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <SDL/SDL.h>
#include <libreborn/libreborn.h>
#include <media-layer/core.h> #include <media-layer/core.h>
// Interactivity // Interactivity

View File

@ -18,7 +18,6 @@ void media_cleanup();
void media_get_framebuffer_size(int *width, int *height); void media_get_framebuffer_size(int *width, int *height);
void media_set_interactable(int is_interactable); void media_set_interactable(int is_interactable);
void media_disable_vsync(); void media_disable_vsync();
void media_force_egl();
void media_set_raw_mouse_motion_enabled(int enabled); void media_set_raw_mouse_motion_enabled(int enabled);
int media_has_extension(const char *name); int media_has_extension(const char *name);
void media_begin_offscreen_render(int width, int height); void media_begin_offscreen_render(int width, int height);

View File

@ -165,15 +165,6 @@ CALL(64, media_set_raw_mouse_motion_enabled, void, (int enabled))
#endif #endif
} }
CALL(66, media_force_egl, void, ())
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
trampoline(true);
#else
func();
return 0;
#endif
}
CALL(71, media_has_extension, int, (const char *name)) CALL(71, media_has_extension, int, (const char *name))
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
return trampoline(false, copy_array(name)); return trampoline(false, copy_array(name));

View File

@ -508,11 +508,6 @@ void _init_misc_graphics() {
media_disable_vsync(); media_disable_vsync();
} }
// Force EGL
if (feature_has("Force EGL", server_disabled)) {
media_force_egl();
}
// Properly Generate Buffers // Properly Generate Buffers
if (feature_has("Proper OpenGL Buffer Generation", server_enabled)) { if (feature_has("Proper OpenGL Buffer Generation", server_enabled)) {
overwrite_calls(Common_anGenBuffers, anGenBuffers_injection); overwrite_calls(Common_anGenBuffers, anGenBuffers_injection);