WIP UI Scale Slider

This commit is contained in:
TheBrokenRail 2024-11-28 02:42:22 -05:00
parent c531e7ba7d
commit cfac7d0a12
12 changed files with 167 additions and 84 deletions

View File

@ -17,6 +17,57 @@ static std::string get_cache_path() {
} }
// Load // Load
static void read_cache(std::ifstream &stream, State &ret) {
// Cache Version
unsigned char cache_version;
stream.read((char *) &cache_version, 1);
if (stream.eof()) {
// Unable To Read Version
WARN("Unable To Read Launcher Cache Version");
return;
}
// Support Older Versions
bool load_gui_scale = true;
if (cache_version == 0) {
// Pre-v3.0.0 Cache
load_gui_scale = false;
} else if (cache_version != (unsigned char) CACHE_VERSION) {
// Invalid Version
WARN("Invalid Launcher Cache Version (Expected: %i, Actual: %i)", CACHE_VERSION, (int) cache_version);
return;
}
// Load Username And Render Distance
State state;
std::getline(stream, state.username, '\0');
std::getline(stream, state.render_distance, '\0');
if (load_gui_scale) {
stream.read((char *) &state.gui_scale, sizeof(float));
}
// Load Feature Flags
std::unordered_map<std::string, bool> flags;
std::string flag;
while (!stream.eof() && std::getline(stream, flag, '\0')) {
if (!flag.empty()) {
bool is_enabled = false;
stream.read((char *) &is_enabled, sizeof(bool));
flags[flag] = is_enabled;
}
stream.peek();
}
state.flags.from_cache(flags);
// Check For Error
if (!stream) {
WARN("Failure While Loading Launcher Cache");
return;
}
// Success
ret = state;
}
State load_cache() { State load_cache() {
// Log // Log
DEBUG("Loading Launcher Cache..."); DEBUG("Loading Launcher Cache...");
@ -35,42 +86,8 @@ State load_cache() {
// Lock File // Lock File
int lock_fd = lock_file(get_cache_path().c_str()); int lock_fd = lock_file(get_cache_path().c_str());
// Check Version // Load
unsigned char cache_version; read_cache(stream, ret);
stream.read((char *) &cache_version, 1);
if (stream.eof()) {
// Unable To Read Version
WARN("Unable To Read Launcher Cache Version");
} else if (cache_version != (unsigned char) CACHE_VERSION) {
// Invalid Version
WARN("Invalid Launcher Cache Version (Expected: %i, Actual: %i)", CACHE_VERSION, (int) cache_version);
} else {
// Load Username And Render Distance
State state;
std::getline(stream, state.username, '\0');
std::getline(stream, state.render_distance, '\0');
// Load Feature Flags
std::unordered_map<std::string, bool> flags;
std::string flag;
while (!stream.eof() && std::getline(stream, flag, '\0')) {
if (!flag.empty()) {
bool is_enabled = false;
stream.read((char *) &is_enabled, sizeof(bool));
flags[flag] = is_enabled;
}
stream.peek();
}
state.flags.from_cache(flags);
// Check For Error
if (!stream) {
WARN("Failure While Loading Launcher Cache");
} else {
// Success
ret = state;
}
}
// Close // Close
stream.close(); stream.close();
@ -84,9 +101,26 @@ State load_cache() {
} }
// Save // Save
static void write_env_to_stream(std::ofstream &stream, const std::string &value) { static void write_env_to_stream(std::ostream &stream, const std::string &value) {
stream.write(value.c_str(), int(value.size()) + 1); stream.write(value.c_str(), int(value.size()) + 1);
} }
void write_cache(std::ostream &stream, const State &state) {
// Save Cache Version
constexpr unsigned char cache_version = CACHE_VERSION;
stream.write((const char *) &cache_version, 1);
// Save Username And Render Distance
write_env_to_stream(stream, state.username);
write_env_to_stream(stream, state.render_distance);
stream.write((const char *) &state.gui_scale, sizeof(float));
// Save Feature Flags
const std::unordered_map<std::string, bool> flags_cache = state.flags.to_cache();
for (const std::pair<const std::string, bool> &it : flags_cache) {
stream.write(it.first.c_str(), int(it.first.size()) + 1);
stream.write((const char *) &it.second, sizeof(bool));
}
}
void save_cache(const State &state) { void save_cache(const State &state) {
// Log // Log
DEBUG("Saving Launcher Cache..."); DEBUG("Saving Launcher Cache...");
@ -98,22 +132,10 @@ void save_cache(const State &state) {
WARN("Unable To Open Launcher Cache For Saving"); WARN("Unable To Open Launcher Cache For Saving");
} else { } else {
// Lock File // Lock File
int lock_fd = lock_file(get_cache_path().c_str()); const int lock_fd = lock_file(get_cache_path().c_str());
// Save Cache Version // Write
constexpr unsigned char cache_version = CACHE_VERSION; write_cache(stream, state);
stream.write((const char *) &cache_version, 1);
// Save Username And Render Distance
write_env_to_stream(stream, state.username);
write_env_to_stream(stream, state.render_distance);
// Save Feature Flags
const std::unordered_map<std::string, bool> flags_cache = state.flags.to_cache();
for (const std::pair<const std::string, bool> &it : flags_cache) {
stream.write(it.first.c_str(), int(it.first.size()) + 1);
stream.write((const char *) &it.second, sizeof(bool));
}
// Finish // Finish
stream.close(); stream.close();

View File

@ -1,13 +1,16 @@
#pragma once #pragma once
#include <ostream>
// Cache Version // Cache Version
#define CACHE_VERSION 0 #define CACHE_VERSION 1
// Load Cache // Load Cache
struct State; struct State;
State load_cache(); State load_cache();
// Save Cache // Save Cache
void write_cache(std::ostream &stream, const State &state);
void save_cache(const State &state); void save_cache(const State &state);
// Wipe Cache // Wipe Cache

View File

@ -1,6 +1,7 @@
#include <sstream>
#include <libreborn/env.h> #include <libreborn/env.h>
#include "../util/util.h"
#include "configuration.h" #include "configuration.h"
#include "cache.h" #include "cache.h"
@ -8,17 +9,17 @@
State::State(): flags("") { State::State(): flags("") {
username = DEFAULT_USERNAME; username = DEFAULT_USERNAME;
render_distance = DEFAULT_RENDER_DISTANCE; render_distance = DEFAULT_RENDER_DISTANCE;
gui_scale = AUTO_GUI_SCALE;
flags = Flags::get(); flags = Flags::get();
} }
template <typename T> template <typename T>
static void update_from_env(const char *env, T &value, const bool save) { static void update_from_env(const char *env, T &value, const bool save) {
if (save) { if (save) {
const std::string str = static_cast<std::string>(value); set_and_print_env(env, obj_to_env_value(value).c_str());
set_and_print_env(env, str.c_str());
} else { } else {
const char *env_value = getenv(env); const char *env_value = getenv(env);
if (env_value != nullptr) { if (env_value != nullptr) {
value = env_value; env_value_to_obj(value, env_value);
} }
} }
} }
@ -26,11 +27,14 @@ void State::update(const bool save) {
update_from_env(MCPI_FEATURE_FLAGS_ENV, flags, save); update_from_env(MCPI_FEATURE_FLAGS_ENV, flags, save);
update_from_env(MCPI_USERNAME_ENV, username, save); update_from_env(MCPI_USERNAME_ENV, username, save);
update_from_env(MCPI_RENDER_DISTANCE_ENV, render_distance, save); update_from_env(MCPI_RENDER_DISTANCE_ENV, render_distance, save);
update_from_env(MCPI_GUI_SCALE_ENV, gui_scale, save);
} }
bool State::operator==(const State &other) const { bool State::operator==(const State &other) const {
#define test(x) static_cast<std::string>(x) == static_cast<std::string>(other.x) std::ostringstream one;
return test(username) && test(render_distance) && test(flags); write_cache(one, *this);
#undef test std::ostringstream two;
write_cache(two, other);
return one.str() == two.str();
} }
// Handle Non-Launch Commands // Handle Non-Launch Commands

View File

@ -11,6 +11,7 @@
// Default Configuration // Default Configuration
#define DEFAULT_USERNAME "StevePi" #define DEFAULT_USERNAME "StevePi"
#define DEFAULT_RENDER_DISTANCE "Short" #define DEFAULT_RENDER_DISTANCE "Short"
#define AUTO_GUI_SCALE 0
// State // State
struct State { struct State {
@ -21,6 +22,7 @@ struct State {
// Properties // Properties
std::string username; std::string username;
std::string render_distance; std::string render_distance;
float gui_scale;
Flags flags; Flags flags;
}; };

View File

@ -16,9 +16,9 @@ static constexpr std::array render_distances = {
}; };
// Tooltips/Text // Tooltips/Text
static constexpr std::string revert_text = "Revert"; static const char *revert_text = "Revert";
static constexpr std::string revert_tooltip_text = "Last Saved"; static const char *revert_tooltip_text = "Last Saved";
static constexpr std::string make_tooltip(const std::string &text, const std::string &type) { static std::string make_tooltip(const std::string &text, const std::string &type) {
return "Use " + text + ' ' + type; return "Use " + text + ' ' + type;
} }
@ -123,20 +123,35 @@ int ConfigurationUI::get_render_distance_index() const {
} }
void ConfigurationUI::draw_main() const { void ConfigurationUI::draw_main() const {
const ImGuiStyle &style = ImGui::GetStyle(); const ImGuiStyle &style = ImGui::GetStyle();
const char *labels[] = {"Username", "Render Distance"}; const char *labels[] = {"Username", "Render Distance", "UI Scale"};
// Calculate Label Size // Calculate Label Size
float label_size = 0; float label_size = 0;
for (const char *label : labels) { for (const char *label : labels) {
label_size = std::max(label_size, ImGui::CalcTextSize(label).x + style.ItemInnerSpacing.x); label_size = std::max(label_size, ImGui::CalcTextSize(label).x + style.ItemInnerSpacing.x);
} }
ImGui::PushItemWidth(-label_size); ImGui::PushItemWidth(-label_size);
// Options // Username
ImGui::InputText(labels[0], &state.username); ImGui::InputText(labels[0], &state.username);
// Render Distance
int render_distance_index = get_render_distance_index(); int render_distance_index = get_render_distance_index();
if (ImGui::Combo(labels[1], &render_distance_index, render_distances.data(), int(render_distances.size()))) { if (ImGui::Combo(labels[1], &render_distance_index, render_distances.data(), int(render_distances.size()))) {
state.render_distance = render_distances[render_distance_index]; state.render_distance = render_distances[render_distance_index];
} }
// UI Scale
std::string scale_format = "%i";
scale_format += 'x';
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);
if (state.gui_scale < AUTO_GUI_SCALE) {
state.gui_scale = AUTO_GUI_SCALE;
}
}
ImGui::PopItemWidth(); ImGui::PopItemWidth();
// Launcher Cache
ImGui::Checkbox("Save Settings On Launch", &save_settings); ImGui::Checkbox("Save Settings On Launch", &save_settings);
} }
@ -193,7 +208,7 @@ void ConfigurationUI::draw_servers() {
// Revert/Save // Revert/Save
int clicked_button = -1; int clicked_button = -1;
ImGui::BeginDisabled(!are_servers_unsaved()); ImGui::BeginDisabled(!are_servers_unsaved());
draw_right_aligned_buttons({revert_text.c_str(), "Save"}, [&clicked_button](const int id, const bool was_clicked) { draw_right_aligned_buttons({revert_text, "Save"}, [&clicked_button](const int id, const bool was_clicked) {
if (id == 0) { if (id == 0) {
ImGui::SetItemTooltip("%s", make_tooltip(revert_tooltip_text, "Server List").c_str()); ImGui::SetItemTooltip("%s", make_tooltip(revert_tooltip_text, "Server List").c_str());
} }

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <string>
#define ENV(name, ...) extern const char *const name##_ENV; #define ENV(name, ...) extern const char *const name##_ENV;
#include "env-list.h" #include "env-list.h"
#undef ENV #undef ENV
@ -9,3 +11,12 @@ void clear_internal_env_vars();
// Set Environmental Variable // Set Environmental Variable
void set_and_print_env(const char *name, const char *value); void set_and_print_env(const char *name, const char *value);
// Convert Variable To Value And Vice-Versa
struct Flags;
std::string obj_to_env_value(const std::string &obj);
std::string obj_to_env_value(const float &obj);
std::string obj_to_env_value(const Flags &obj);
void env_value_to_obj(std::string &out, const char *value);
void env_value_to_obj(float &out, const char *value);
void env_value_to_obj(Flags &out, const char *value);

View File

@ -36,8 +36,9 @@ struct Flags {
explicit Flags(const std::string &data); explicit Flags(const std::string &data);
static Flags get(); static Flags get();
// To/From Strings // To/From Strings
explicit operator std::string() const; std::string to_string() const;
Flags &operator=(const std::string &str); void from_string(const std::string &str);
bool operator==(const Flags &other) const;
// To/From Cache // To/From Cache
[[nodiscard]] std::unordered_map<std::string, bool> to_cache() const; [[nodiscard]] std::unordered_map<std::string, bool> to_cache() const;
void from_cache(const std::unordered_map<std::string, bool> &cache); void from_cache(const std::unordered_map<std::string, bool> &cache);

View File

@ -1,6 +1,7 @@
#include <libreborn/env.h> #include <libreborn/env.h>
#include <libreborn/exec.h> #include <libreborn/exec.h>
#include <libreborn/log.h> #include <libreborn/log.h>
#include <libreborn/flags.h>
// Define Constants // Define Constants
#define ENV(name, ...) const char *const name##_ENV = #name; #define ENV(name, ...) const char *const name##_ENV = #name;
@ -36,3 +37,23 @@ void set_and_print_env(const char *name, const char *value) {
// Print New Value // Print New Value
DEBUG("Set %s = %s", name, value != NULL ? value : "(unset)"); DEBUG("Set %s = %s", name, value != NULL ? value : "(unset)");
} }
// Conversion
std::string obj_to_env_value(const std::string &obj) {
return obj;
}
std::string obj_to_env_value(const float &obj) {
return std::to_string(obj);
}
std::string obj_to_env_value(const Flags &obj) {
return obj.to_string();
}
void env_value_to_obj(std::string &out, const char *value) {
out = value;
}
void env_value_to_obj(float &out, const char *value) {
out = strtof(value, nullptr);
}
void env_value_to_obj(Flags &out, const char *value) {
out.from_string(value);
}

View File

@ -62,7 +62,7 @@ Flags::Flags(const std::string &data) {
} }
}); });
} }
Flags::operator std::string() const { std::string Flags::to_string() const {
std::string out; std::string out;
root.for_each_const([&out](const FlagNode &flag) { root.for_each_const([&out](const FlagNode &flag) {
if (flag.value) { if (flag.value) {
@ -74,7 +74,7 @@ Flags::operator std::string() const {
}); });
return out; return out;
} }
Flags &Flags::operator=(const std::string &str) { void Flags::from_string(const std::string &str) {
// Find Flags To Enable // Find Flags To Enable
std::unordered_set<std::string> to_enable; std::unordered_set<std::string> to_enable;
std::stringstream stream(str); std::stringstream stream(str);
@ -88,7 +88,9 @@ Flags &Flags::operator=(const std::string &str) {
root.for_each([&to_enable](FlagNode &flag) { root.for_each([&to_enable](FlagNode &flag) {
flag.value = to_enable.contains(flag.name); flag.value = to_enable.contains(flag.name);
}); });
return *this; }
bool Flags::operator==(const Flags &other) const {
return to_string() == other.to_string();
} }
std::unordered_map<std::string, bool> Flags::to_cache() const { std::unordered_map<std::string, bool> Flags::to_cache() const {
std::unordered_map<std::string, bool> out; std::unordered_map<std::string, bool> out;

View File

@ -20,7 +20,7 @@ bool _feature_has(const char *name, const int server_default) {
if (!loaded) { if (!loaded) {
const char *env = getenv(MCPI_FEATURE_FLAGS_ENV); const char *env = getenv(MCPI_FEATURE_FLAGS_ENV);
if (env) { if (env) {
flags = env; flags.from_string(env);
} }
loaded = true; loaded = true;
} }

View File

@ -15,9 +15,8 @@
// Heart Food Overlay // Heart Food Overlay
static int heal_amount = 0, heal_amount_drawing = 0; static int heal_amount = 0, heal_amount_drawing = 0;
static void Gui_renderHearts_injection(Gui_renderHearts_t original, Gui *gui) { static void Gui_renderHearts_injection(Gui_renderHearts_t original, Gui *gui) {
// Get heal_amount // Calculate heal_amount
heal_amount = heal_amount_drawing = 0; heal_amount = heal_amount_drawing = 0;
Inventory *inventory = gui->minecraft->player->inventory; Inventory *inventory = gui->minecraft->player->inventory;
const ItemInstance *held_ii = inventory->getSelected(); const ItemInstance *held_ii = inventory->getSelected();
if (held_ii) { if (held_ii) {
@ -30,7 +29,7 @@ static void Gui_renderHearts_injection(Gui_renderHearts_t original, Gui *gui) {
} }
} }
// Call original // Call Original Method
original(gui); original(gui);
} }
#define PINK_HEART_FULL 70 #define PINK_HEART_FULL 70
@ -306,13 +305,16 @@ void _init_misc_ui() {
// Custom GUI Scale // Custom GUI Scale
const char *gui_scale_str = getenv(MCPI_GUI_SCALE_ENV); const char *gui_scale_str = getenv(MCPI_GUI_SCALE_ENV);
if (gui_scale_str != nullptr) { if (gui_scale_str != nullptr) {
unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop" float gui_scale;
patch((void *) 0x173e8, nop_patch); env_value_to_obj(gui_scale, gui_scale_str);
patch((void *) 0x173f0, nop_patch); if (gui_scale > 0) {
const float gui_scale = strtof(gui_scale_str, nullptr); unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
uint32_t gui_scale_raw; patch((void *) 0x173e8, nop_patch);
memcpy(&gui_scale_raw, &gui_scale, sizeof (gui_scale_raw)); patch((void *) 0x173f0, nop_patch);
patch_address((void *) 0x17520, (void *) gui_scale_raw); uint32_t gui_scale_raw;
memcpy(&gui_scale_raw, &gui_scale, sizeof (gui_scale_raw));
patch_address((void *) 0x17520, (void *) gui_scale_raw);
}
} }
// Don't Wrap Text On '\r' Or '\t' Because They Are Actual Characters In MCPI // Don't Wrap Text On '\r' Or '\t' Because They Are Actual Characters In MCPI

View File

@ -103,7 +103,7 @@ static bool draw_splash(StartMenuScreen *screen, const float y_factor, const boo
const int text_width = screen->font->width(current_splash); const int text_width = screen->font->width(current_splash);
float splash_width = float(text_width) * scale; float splash_width = float(text_width) * scale;
if (splash_width > float(max_width)) { if (splash_width > float(max_width)) {
const float multiplier = (float(max_width) / splash_width); const float multiplier = float(max_width) / splash_width;
scale *= multiplier; scale *= multiplier;
splash_width *= multiplier; splash_width *= multiplier;
} }