ImGui Hello World
This commit is contained in:
parent
fc7ecd528a
commit
0b542701c5
@ -13,12 +13,18 @@ add_executable(launcher
|
||||
src/logger/crash-report.cpp
|
||||
src/options/parser.cpp
|
||||
src/main.cpp
|
||||
src/ui/frame.cpp
|
||||
src/client/configuration.cpp
|
||||
src/client/cache.cpp
|
||||
src/client/available-feature-flags # Show In IDE
|
||||
)
|
||||
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
|
||||
set_target_properties(launcher PROPERTIES INSTALL_RPATH "$ORIGIN/lib/native")
|
||||
target_link_options(launcher PRIVATE "LINKER:--disable-new-dtags")
|
||||
|
@ -45,7 +45,6 @@ FALSE Remove Forced GUI Lag (Can Break Joining Servers)
|
||||
TRUE Add Buckets
|
||||
TRUE Classic HUD
|
||||
TRUE Translucent Toolbar
|
||||
FALSE Force EGL
|
||||
TRUE Improved Classic Title Screen
|
||||
FALSE Disable Speed Bridging
|
||||
FALSE Disable Creative Mode Mining Delay
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "../util/util.h"
|
||||
#include "configuration.h"
|
||||
#include "cache.h"
|
||||
#include "../ui/frame.h"
|
||||
|
||||
// Strip Feature Flag Default
|
||||
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
|
||||
extern unsigned char available_feature_flags[];
|
||||
extern size_t available_feature_flags_len;
|
||||
EMBEDDED_RESOURCE(available_feature_flags);
|
||||
void load_available_feature_flags(const std::function<void(std::string)> &callback) {
|
||||
// Load Data
|
||||
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
|
||||
#define LIST_DIALOG_SIZE "400"
|
||||
void configure_client(const options_t &options) {
|
||||
// Load Cache
|
||||
launcher_cache cache = options.no_cache ? empty_cache : load_cache();
|
||||
|
||||
Test *test = new Test;
|
||||
test->run();
|
||||
delete test;
|
||||
|
||||
// --default
|
||||
if (options.use_default) {
|
||||
// Use Default Feature Flags
|
||||
|
87
launcher/src/ui/frame.cpp
Normal file
87
launcher/src/ui/frame.cpp
Normal 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
21
launcher/src/ui/frame.h
Normal 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);
|
||||
};
|
@ -14,6 +14,10 @@ add_library(reborn-util SHARED
|
||||
src/util/env.cpp
|
||||
)
|
||||
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
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/include"
|
||||
|
11
libreborn/include/libreborn/glfw.h
Normal file
11
libreborn/include/libreborn/glfw.h
Normal 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
|
@ -7,3 +7,4 @@
|
||||
#include "string.h"
|
||||
#include "exec.h"
|
||||
#include "patch.h"
|
||||
#include "glfw.h"
|
@ -3,7 +3,7 @@
|
||||
#include <string>
|
||||
|
||||
// Patching Functions
|
||||
#if defined(REBORN_HAS_PATCH_CODE)
|
||||
#ifdef REBORN_HAS_PATCH_CODE
|
||||
|
||||
// Init
|
||||
void reborn_init_patch();
|
||||
|
@ -74,4 +74,9 @@ const char *get_home_subdirectory_for_game_data();
|
||||
void ensure_directory(const char *path);
|
||||
|
||||
// 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
|
||||
|
68
libreborn/src/util/glfw.cpp
Normal file
68
libreborn/src/util/glfw.cpp
Normal 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);
|
||||
}
|
||||
}
|
@ -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) {
|
||||
return;
|
||||
}
|
||||
// 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 Ratios
|
||||
const double width_ratio = double(framebuffer_width) / double(window_width);
|
||||
const double height_ratio = double(framebuffer_height) / double(window_height);
|
||||
// Get Scale
|
||||
float x_scale = 1;
|
||||
float y_scale = 1;
|
||||
get_glfw_scale(window, &x_scale, &y_scale);
|
||||
// Multiply
|
||||
*xpos *= width_ratio;
|
||||
*ypos *= height_ratio;
|
||||
*xpos *= x_scale;
|
||||
*ypos *= y_scale;
|
||||
}
|
||||
|
||||
// Last Mouse Location
|
||||
|
@ -7,11 +7,6 @@
|
||||
// Window
|
||||
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
|
||||
static bool disable_vsync = false;
|
||||
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
|
||||
#define GL_VERSION 0x1f02
|
||||
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
|
||||
reborn_check_display();
|
||||
glfwSetErrorCallback(glfw_error);
|
||||
if (!glfwInit()) {
|
||||
ERR("Unable To Initialize GLFW");
|
||||
}
|
||||
init_glfw();
|
||||
|
||||
// Create OpenGL Context
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 1);
|
||||
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
|
||||
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
|
||||
glfw_window = glfwCreateWindow(DEFAULT_WIDTH, DEFAULT_HEIGHT, title, nullptr, nullptr);
|
||||
if (!glfw_window) {
|
||||
ERR("Unable To Create GLFW Window");
|
||||
}
|
||||
glfw_window = create_glfw_window(title, DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
||||
|
||||
// Event Handlers
|
||||
_media_register_event_listeners();
|
||||
|
||||
// Make Window Context Current
|
||||
glfwMakeContextCurrent(glfw_window);
|
||||
|
||||
// Debug
|
||||
const glGetString_t glGetString = (glGetString_t) glfwGetProcAddress("glGetString");
|
||||
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
|
||||
void media_cleanup() {
|
||||
if (glfw_window) {
|
||||
// Ignore GLFW Errors During Termination
|
||||
glfwSetErrorCallback(nullptr);
|
||||
|
||||
// Terminate GLFW
|
||||
glfwDestroyWindow(glfw_window);
|
||||
glfwTerminate();
|
||||
cleanup_glfw(glfw_window);
|
||||
|
||||
// Cleanup OpenAL
|
||||
_media_audio_cleanup();
|
||||
|
@ -1,11 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include <media-layer/core.h>
|
||||
|
||||
// Interactivity
|
||||
|
@ -18,7 +18,6 @@ void media_cleanup();
|
||||
void media_get_framebuffer_size(int *width, int *height);
|
||||
void media_set_interactable(int is_interactable);
|
||||
void media_disable_vsync();
|
||||
void media_force_egl();
|
||||
void media_set_raw_mouse_motion_enabled(int enabled);
|
||||
int media_has_extension(const char *name);
|
||||
void media_begin_offscreen_render(int width, int height);
|
||||
|
@ -165,15 +165,6 @@ CALL(64, media_set_raw_mouse_motion_enabled, void, (int enabled))
|
||||
#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))
|
||||
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
|
||||
return trampoline(false, copy_array(name));
|
||||
|
@ -508,11 +508,6 @@ void _init_misc_graphics() {
|
||||
media_disable_vsync();
|
||||
}
|
||||
|
||||
// Force EGL
|
||||
if (feature_has("Force EGL", server_disabled)) {
|
||||
media_force_egl();
|
||||
}
|
||||
|
||||
// Properly Generate Buffers
|
||||
if (feature_has("Proper OpenGL Buffer Generation", server_enabled)) {
|
||||
overwrite_calls(Common_anGenBuffers, anGenBuffers_injection);
|
||||
|
Loading…
Reference in New Issue
Block a user