diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index d42c982961..12683d7bc9 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -53,6 +53,7 @@ * `Proper Entity Shading` (Enabled By Default) * `Fix Sugar Position In Hand` (Enabled By Default) * `Fix Reloading Textures On Resize` (Enabled By Default) + * `Improved UI Scaling` (Enabled By Default) * Existing Functionality (All Enabled By Default) * `Fix Screen Rendering When Hiding HUD` * `Sanitize Usernames` diff --git a/images/start.png b/images/start.png index 62d07a7541..b33650714e 100644 Binary files a/images/start.png and b/images/start.png differ diff --git a/launcher/src/client/ui.cpp b/launcher/src/client/ui.cpp index 24484e9b5e..d5bf89eec6 100644 --- a/launcher/src/client/ui.cpp +++ b/launcher/src/client/ui.cpp @@ -1,5 +1,6 @@ #include #include +#include #include @@ -138,14 +139,16 @@ void ConfigurationUI::draw_main() const { state.render_distance = render_distances[render_distance_index]; } // UI Scale - std::string scale_format = "%i"; - scale_format += 'x'; + const int precision = std::floor(state.gui_scale) == state.gui_scale ? 0 : 1; + std::string scale_format = "%." + std::to_string(precision) + "fx"; if (state.gui_scale <= AUTO_GUI_SCALE) { scale_format = "Auto"; } - int gui_scale_int = int(state.gui_scale); - if (ImGui::SliderInt(labels[2], &gui_scale_int, 0, 8, scale_format.c_str())) { - state.gui_scale = float(gui_scale_int); + char display_gui_scale[64]; + sprintf(display_gui_scale, scale_format.c_str(), state.gui_scale); + float new_gui_scale = state.gui_scale; + if (ImGui::SliderFloat(labels[2], &new_gui_scale, 0, 8, display_gui_scale, ImGuiSliderFlags_NoRoundToFormat)) { + state.gui_scale = step_value(new_gui_scale); if (state.gui_scale < AUTO_GUI_SCALE) { state.gui_scale = AUTO_GUI_SCALE; } diff --git a/libreborn/include/libreborn/util.h b/libreborn/include/libreborn/util.h index d3900b0b6c..7cb3fd266b 100644 --- a/libreborn/include/libreborn/util.h +++ b/libreborn/include/libreborn/util.h @@ -64,4 +64,7 @@ std::string format_time(const char *fmt, int time); // Default MCPI Port // This Macro DOES NOT Control MCPI -#define DEFAULT_MULTIPLAYER_PORT 19132 \ No newline at end of file +#define DEFAULT_MULTIPLAYER_PORT 19132 + +// Step Value +float step_value(float value, float step = 0.5f); \ No newline at end of file diff --git a/libreborn/src/util/flags/available-feature-flags b/libreborn/src/util/flags/available-feature-flags index 3cedc4b29c..96370eb2f0 100644 --- a/libreborn/src/util/flags/available-feature-flags +++ b/libreborn/src/util/flags/available-feature-flags @@ -44,6 +44,7 @@ CATEGORY User Interface TRUE Improved Button Hover Behavior TRUE Classic Item Count UI TRUE Click Buttons On Mouse Down + TRUE Improved UI Scaling CATEGORY Rendering CATEGORY Optimizations TRUE Optimized Chunk Sorting diff --git a/libreborn/src/util/util.cpp b/libreborn/src/util/util.cpp index 7343f4e50b..b9475a745f 100644 --- a/libreborn/src/util/util.cpp +++ b/libreborn/src/util/util.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -135,3 +136,8 @@ std::string format_time(const char *fmt, const int time) { // This Will Break In 2038 return _format_time(fmt, time); } + +// Step +float step_value(const float value, const float step) { + return std::round(value / step) * step; +} \ No newline at end of file diff --git a/mods/src/misc/ui.cpp b/mods/src/misc/ui.cpp index cd8f8fa909..97755d17c1 100644 --- a/mods/src/misc/ui.cpp +++ b/mods/src/misc/ui.cpp @@ -1,8 +1,11 @@ #include #include +#include #include +#include + #include #include @@ -245,6 +248,29 @@ static void LocalPlayer_openTextEdit_injection(__attribute__((unused)) LocalPlay } } +// Better GUI Scaling +static void set_gui_scale(const float new_scale) { + union { + float a; + void *b; + } pun = {}; + pun.a = new_scale; + patch_address((void *) 0x17520, pun.b); +} +static float calculate_scale(const float value, const float default_value) { + constexpr float initial_scale = 2.5f; + const float scale = initial_scale * (value / default_value); + return step_value(scale); +} +static void Minecraft_setSize_injection(Minecraft_setSize_t original, Minecraft *self, const int width, const int height) { + // Calculate Scale + const float a = calculate_scale(float(width), DEFAULT_WIDTH); + const float b = calculate_scale(float(height), DEFAULT_HEIGHT); + set_gui_scale(std::min(a, b)); + // Call Original Method + original(self, width, height); +} + // Init void _init_misc_ui() { // Food Overlay @@ -303,19 +329,25 @@ void _init_misc_ui() { } // Custom GUI Scale + bool patch_gui_scaling = false; const char *gui_scale_str = getenv(MCPI_GUI_SCALE_ENV); if (gui_scale_str != nullptr) { float gui_scale; env_value_to_obj(gui_scale, gui_scale_str); if (gui_scale > 0) { - unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop" - patch((void *) 0x173e8, nop_patch); - patch((void *) 0x173f0, nop_patch); - uint32_t gui_scale_raw; - memcpy(&gui_scale_raw, &gui_scale, sizeof (gui_scale_raw)); - patch_address((void *) 0x17520, (void *) gui_scale_raw); + patch_gui_scaling = true; + set_gui_scale(gui_scale); } } + if (feature_has("Improved UI Scaling", server_disabled) && !patch_gui_scaling) { + overwrite_calls(Minecraft_setSize, Minecraft_setSize_injection); + patch_gui_scaling = true; + } + if (patch_gui_scaling) { + unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop" + patch((void *) 0x173e8, nop_patch); + patch((void *) 0x173f0, nop_patch); + } // Don't Wrap Text On '\r' Or '\t' Because They Are Actual Characters In MCPI if (feature_has("Fix Text Wrapping", server_disabled)) { diff --git a/symbols/src/game/Minecraft.def b/symbols/src/game/Minecraft.def index 85ce5dea49..5b0bf21507 100644 --- a/symbols/src/game/Minecraft.def +++ b/symbols/src/game/Minecraft.def @@ -17,6 +17,7 @@ method LevelStorageSource *getLevelSource() = 0x16e84; method void handleMouseDown(int param_1, bool can_destroy) = 0x1584c; method void handleBuildAction(uint *build_action_intention) = 0x15920; method void joinMultiplayer(const PingedCompatibleServer &server) = 0x165f4; +method void setSize(int width, int height) = 0x173a4; virtual-method void update() = 0x24; virtual-method int handleBack(bool do_nothing) = 0x34;