mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
overlay: UI scaling option (#495)
## Link to GitHub Issue, if one exists #477 ## Description of change Add a new option for scaling the overlay. Gitadora Arena will receive 250% by default. Various overlay windows have been updated to scale properly, not perfect but they are at least usable.
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
#include "cfg/configurator.h"
|
||||
#include "hooks/audio/mme.h"
|
||||
#include "hooks/graphics/graphics.h"
|
||||
#include "overlay/overlay.h"
|
||||
#include "util/cpuutils.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/libutils.h"
|
||||
@@ -212,6 +213,13 @@ namespace games::gitadora {
|
||||
log_fatal("gitadora", "Cabinet type 3 (SD2) not supported on XG series");
|
||||
}
|
||||
#endif
|
||||
|
||||
// arena model launches a tiny window yet backbuffer at 4k, resulting in unusable overlay
|
||||
// force scaling to make things usable
|
||||
if (!overlay::UI_SCALE_PERCENT.has_value() && is_arena_model() &&
|
||||
GRAPHICS_WINDOWED && !cfg::CONFIGURATOR_STANDALONE) {
|
||||
overlay::UI_SCALE_PERCENT = 250;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -959,6 +959,12 @@ int main_implementation(int argc, char *argv[]) {
|
||||
if (options[launcher::Options::DisableOverlay].value_bool()) {
|
||||
overlay::ENABLED = false;
|
||||
}
|
||||
if (options[launcher::Options::OverlayScaling].is_active() && !cfg::CONFIGURATOR_STANDALONE && !cfg_run) {
|
||||
const auto val = options[launcher::Options::OverlayScaling].value_uint32();
|
||||
if (10 <= val && val <= 400 && val != 100) {
|
||||
overlay::UI_SCALE_PERCENT = options[launcher::Options::OverlayScaling].value_uint32();
|
||||
}
|
||||
}
|
||||
if (options[launcher::Options::DisableAudioHooks].value_bool()) {
|
||||
hooks::audio::ENABLED = false;
|
||||
deferredlogs::defer_error_messages({
|
||||
|
||||
@@ -383,12 +383,24 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.disabled = true,
|
||||
},
|
||||
{
|
||||
// DisableOverlay
|
||||
.title = "Disable Spice Overlay",
|
||||
.name = "overlaydisable",
|
||||
.desc = "Disables the in-game overlay",
|
||||
.type = OptionType::Bool,
|
||||
.category = "Overlay",
|
||||
},
|
||||
{
|
||||
// OverlayScaling
|
||||
.title = "Spice Overlay UI Scale %",
|
||||
.name = "overlayscale",
|
||||
.desc = "Forces UI scaling for the overlay, "
|
||||
"things can look off since the UI was written for 100% scaling. "
|
||||
"Enter value in percentage, between 10-400, inclusive",
|
||||
.type = OptionType::Integer,
|
||||
.setting_name = "200",
|
||||
.category = "Overlay",
|
||||
},
|
||||
{
|
||||
// spice2x_FpsAutoShow
|
||||
.title = "Auto Show FPS/Clock",
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace launcher {
|
||||
SOFTID,
|
||||
VREnable,
|
||||
DisableOverlay,
|
||||
OverlayScaling,
|
||||
spice2x_FpsAutoShow,
|
||||
spice2x_FpsOpposite,
|
||||
spice2x_SubScreenAutoShow,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "avs/game.h"
|
||||
#include "cfg/configurator.h"
|
||||
#include "games/io.h"
|
||||
#include "games/gitadora/gitadora.h"
|
||||
#include "games/iidx/iidx.h"
|
||||
#include "hooks/graphics/graphics.h"
|
||||
#include "misc/eamuse.h"
|
||||
@@ -51,16 +52,26 @@ namespace overlay {
|
||||
bool AUTO_SHOW_IOPANEL = false;
|
||||
bool AUTO_SHOW_KEYPAD_P1 = false;
|
||||
bool AUTO_SHOW_KEYPAD_P2 = false;
|
||||
|
||||
bool USE_WM_CHAR_FOR_IMGUI_CHAR_INPUT = false;
|
||||
|
||||
bool FPS_SHOULD_FLIP = false;
|
||||
std::optional<uint32_t> UI_SCALE_PERCENT;
|
||||
|
||||
// global
|
||||
std::mutex OVERLAY_MUTEX;
|
||||
std::unique_ptr<overlay::SpiceOverlay> OVERLAY = nullptr;
|
||||
ImFont* DSEG_FONT = nullptr;
|
||||
bool SHOW_DEBUG_LOG_WINDOW = false;
|
||||
|
||||
ImVec2 apply_scaling_to_vector(float x, float y) {
|
||||
if (!UI_SCALE_PERCENT.has_value()) {
|
||||
return ImVec2(x, y);
|
||||
}
|
||||
return ImVec2(apply_scaling(x), apply_scaling(y));
|
||||
}
|
||||
|
||||
ImVec2 apply_scaling_to_vector(const ImVec2& input) {
|
||||
return apply_scaling_to_vector(input.x, input.y);
|
||||
}
|
||||
}
|
||||
|
||||
static void *ImGui_Alloc(size_t sz, void *user_data) {
|
||||
@@ -170,6 +181,12 @@ void overlay::SpiceOverlay::init() {
|
||||
style.WindowRounding = 0;
|
||||
}
|
||||
|
||||
if (UI_SCALE_PERCENT.has_value()) {
|
||||
const auto scale = static_cast<float>(UI_SCALE_PERCENT.value()) / 100.f;
|
||||
ImGui::GetStyle().ScaleAllSizes(scale);
|
||||
ImGui::GetIO().FontGlobalScale = scale;
|
||||
}
|
||||
|
||||
// red theme based on:
|
||||
// https://github.com/ocornut/imgui/issues/707#issuecomment-760220280
|
||||
// r, g, b, a
|
||||
@@ -245,7 +262,6 @@ void overlay::SpiceOverlay::init() {
|
||||
|
||||
if (!cfg::CONFIGURATOR_STANDALONE) {
|
||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
|
||||
}
|
||||
if (is_touch_available("SpiceOverlay::init")) {
|
||||
io.ConfigFlags |= ImGuiConfigFlags_IsTouchScreen;
|
||||
@@ -366,7 +382,8 @@ void overlay::SpiceOverlay::init() {
|
||||
window_iopanel = new overlay::windows::IIDXIOPanel(this);
|
||||
} else if (avs::game::is_model("MDX")) {
|
||||
window_iopanel = new overlay::windows::DDRIOPanel(this);
|
||||
} else if (avs::game::is_model({"J32", "J33", "K32", "K33", "L32", "L33", "M32"})) {
|
||||
} else if (avs::game::is_model({"J32", "J33", "K32", "K33", "L32", "L33", "M32"}) &&
|
||||
!games::gitadora::is_arena_model()) {
|
||||
window_iopanel = new overlay::windows::GitadoraIOPanel(this);
|
||||
} else {
|
||||
window_iopanel = new overlay::windows::IOPanel(this);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
#include <windows.h>
|
||||
#include <d3d9.h>
|
||||
@@ -27,6 +28,18 @@ namespace overlay {
|
||||
extern bool USE_WM_CHAR_FOR_IMGUI_CHAR_INPUT;
|
||||
extern bool FPS_SHOULD_FLIP;
|
||||
extern bool SHOW_DEBUG_LOG_WINDOW;
|
||||
extern std::optional<uint32_t> UI_SCALE_PERCENT;
|
||||
|
||||
template <typename T>
|
||||
float apply_scaling(T input) {
|
||||
if (!UI_SCALE_PERCENT.has_value()) {
|
||||
return input;
|
||||
}
|
||||
return static_cast<float>(input) * UI_SCALE_PERCENT.value() / 100.f;
|
||||
}
|
||||
|
||||
ImVec2 apply_scaling_to_vector(const ImVec2& input);
|
||||
ImVec2 apply_scaling_to_vector(float x, float y);
|
||||
|
||||
class SpiceOverlay {
|
||||
public:
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace overlay::windows {
|
||||
CameraControl::CameraControl(SpiceOverlay *overlay) : Window(overlay) {
|
||||
this->title = "IIDX Camera Control";
|
||||
this->flags |= ImGuiWindowFlags_AlwaysAutoResize;
|
||||
this->init_pos = ImVec2(40, 40);
|
||||
this->init_pos = overlay::apply_scaling_to_vector(40, 40);
|
||||
this->toggle_button = games::OverlayButtons::ToggleCameraControl;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace overlay::windows {
|
||||
|
||||
CardManager::CardManager(SpiceOverlay *overlay) : Window(overlay) {
|
||||
this->title = "Card Manager";
|
||||
this->init_size = ImVec2(420, 420);
|
||||
this->init_size = overlay::apply_scaling_to_vector(ImVec2(420, 420));
|
||||
|
||||
if (cfg::CONFIGURATOR_STANDALONE) {
|
||||
this->init_pos = ImVec2(40, 40);
|
||||
@@ -303,7 +303,7 @@ namespace overlay::windows {
|
||||
//
|
||||
// setting ImGuiInputTextFlags_CallbackCharFilter and pressing escape doesn't cause below
|
||||
// to return true, making it necessary to provide a callback...
|
||||
ImGui::SetNextItemWidth(240);
|
||||
ImGui::SetNextItemWidth(overlay::apply_scaling(240));
|
||||
if (ImGui::InputTextWithHint("", "Type here to search..", &this->search_filter)) {
|
||||
this->current_card = nullptr;
|
||||
this->search_filter_in_lower_case = strtolower(this->search_filter);
|
||||
|
||||
@@ -42,8 +42,8 @@ namespace overlay::windows {
|
||||
Config::Config(overlay::SpiceOverlay *overlay) : Window(overlay) {
|
||||
this->title = "Configuration";
|
||||
this->toggle_button = games::OverlayButtons::ToggleConfig;
|
||||
this->init_size = ImVec2(800, 600);
|
||||
this->size_min = ImVec2(100, 200);
|
||||
this->init_size = overlay::apply_scaling_to_vector(ImVec2(800, 600));
|
||||
this->size_min = overlay::apply_scaling_to_vector(ImVec2(100, 200));
|
||||
this->init_pos = ImVec2(0, 0);
|
||||
if (cfg::CONFIGURATOR_STANDALONE && cfg::CONFIGURATOR_TYPE == cfg::ConfigType::Config) {
|
||||
this->active = true;
|
||||
@@ -238,8 +238,8 @@ namespace overlay::windows {
|
||||
// tab selection
|
||||
auto tab_selected_new = ConfigTab::CONFIG_TAB_INVALID;
|
||||
if (ImGui::BeginTabBar("Config Tabs", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) {
|
||||
const int page_offset = cfg::CONFIGURATOR_STANDALONE ? 88 : 110;
|
||||
const int page_offset2 = cfg::CONFIGURATOR_STANDALONE ? 65 : 87;
|
||||
const int page_offset = overlay::apply_scaling(cfg::CONFIGURATOR_STANDALONE ? 88 : 110);
|
||||
const int page_offset2 = overlay::apply_scaling(cfg::CONFIGURATOR_STANDALONE ? 65 : 87);
|
||||
|
||||
if (ImGui::BeginTabItem("Buttons")) {
|
||||
tab_selected_new = ConfigTab::CONFIG_TAB_BUTTONS;
|
||||
@@ -575,7 +575,7 @@ namespace overlay::windows {
|
||||
if (ImGui::BeginTable("ButtonsTable", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg)) {
|
||||
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch);
|
||||
ImGui::TableSetupColumn("Binding", ImGuiTableColumnFlags_WidthStretch);
|
||||
ImGui::TableSetupColumn("Actions", ImGuiTableColumnFlags_WidthFixed, 240);
|
||||
ImGui::TableSetupColumn("Actions", ImGuiTableColumnFlags_WidthFixed, overlay::apply_scaling(240));
|
||||
|
||||
// check if empty
|
||||
if (!buttons || buttons->empty()) {
|
||||
@@ -1644,7 +1644,7 @@ namespace overlay::windows {
|
||||
if (ImGui::BeginTable("AnalogsTable", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg)) {
|
||||
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch);
|
||||
ImGui::TableSetupColumn("Binding", ImGuiTableColumnFlags_WidthStretch);
|
||||
ImGui::TableSetupColumn("Actions", ImGuiTableColumnFlags_WidthFixed, 240);
|
||||
ImGui::TableSetupColumn("Actions", ImGuiTableColumnFlags_WidthFixed, overlay::apply_scaling(240));
|
||||
|
||||
// check if empty
|
||||
if (!analogs || analogs->empty()) {
|
||||
@@ -2086,7 +2086,7 @@ namespace overlay::windows {
|
||||
if (ImGui::BeginTable("LightsTable", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg)) {
|
||||
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch);
|
||||
ImGui::TableSetupColumn("Binding", ImGuiTableColumnFlags_WidthStretch);
|
||||
ImGui::TableSetupColumn("Actions", ImGuiTableColumnFlags_WidthFixed, 240);
|
||||
ImGui::TableSetupColumn("Actions", ImGuiTableColumnFlags_WidthFixed, overlay::apply_scaling(240));
|
||||
|
||||
// check if empty
|
||||
if (!lights || lights->empty()) {
|
||||
@@ -2643,8 +2643,14 @@ namespace overlay::windows {
|
||||
// tables must share the same ID to have synced column settings
|
||||
if (ImGui::BeginTable("OptionsTable", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg)) {
|
||||
ImGui::TableSetupColumn("Option", ImGuiTableColumnFlags_WidthStretch);
|
||||
ImGui::TableSetupColumn("CMD Line Parameter", ImGuiTableColumnFlags_WidthFixed, 216);
|
||||
ImGui::TableSetupColumn("Setting", ImGuiTableColumnFlags_WidthFixed, 240);
|
||||
ImGui::TableSetupColumn(
|
||||
"CMD Line Parameter",
|
||||
ImGuiTableColumnFlags_WidthFixed,
|
||||
overlay::apply_scaling(216));
|
||||
ImGui::TableSetupColumn(
|
||||
"Setting",
|
||||
ImGuiTableColumnFlags_WidthFixed,
|
||||
overlay::apply_scaling(240));
|
||||
|
||||
// iterate options
|
||||
options_count = 0;
|
||||
@@ -3056,7 +3062,11 @@ namespace overlay::windows {
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.34f, 0.14f, 0.14f, 0.54f));
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(0.34f, 0.14f, 0.14f, 0.54f));
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(0.34f, 0.14f, 0.14f, 0.64f));
|
||||
ImGui::PushItemWidth(MIN(700, MAX(100, ImGui::GetWindowSize().x - 400)));
|
||||
ImGui::PushItemWidth(
|
||||
MIN(overlay::apply_scaling(700),
|
||||
MAX(overlay::apply_scaling(100),
|
||||
ImGui::GetWindowSize().x - overlay::apply_scaling(400))));
|
||||
|
||||
ImGui::Combo("##game_selector", game_selected, games_names.data(), (int)games_list.size());
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::PopStyleColor(3);
|
||||
@@ -3080,8 +3090,8 @@ namespace overlay::windows {
|
||||
// draw popups
|
||||
{
|
||||
const ImVec2 popup_size(
|
||||
std::min(ImGui::GetIO().DisplaySize.x * 0.9f, 800.f),
|
||||
std::min(ImGui::GetIO().DisplaySize.y * 0.9f, 800.f));
|
||||
std::min(ImGui::GetIO().DisplaySize.x * 0.9f, overlay::apply_scaling(800.f)),
|
||||
std::min(ImGui::GetIO().DisplaySize.y * 0.9f, overlay::apply_scaling(800.f)));
|
||||
|
||||
const ImVec2 popup_pos(
|
||||
ImGui::GetIO().DisplaySize.x / 2 - popup_size.x / 2,
|
||||
|
||||
@@ -10,10 +10,10 @@ namespace overlay::windows {
|
||||
this->title = "spice2x";
|
||||
this->init_size = ImVec2(
|
||||
(ImGui::GetFontSize() * 14) + (ImGui::GetStyle().ItemSpacing.x * 2),
|
||||
120);
|
||||
overlay::apply_scaling(120));
|
||||
this->init_pos = ImVec2(
|
||||
ImGui::GetIO().DisplaySize.x / 2 - this->init_size.x / 2,
|
||||
10);
|
||||
overlay::apply_scaling(10));
|
||||
|
||||
this->flags = ImGuiWindowFlags_NoResize
|
||||
| ImGuiWindowFlags_NoCollapse
|
||||
|
||||
@@ -20,8 +20,11 @@ namespace overlay::windows {
|
||||
|
||||
void FPS::calculate_initial_window() {
|
||||
// width is 114x82 px with window decoration, 98x47 for the content
|
||||
int pos_x = overlay::FPS_SHOULD_FLIP ? 8 : ImGui::GetIO().DisplaySize.x - 122;
|
||||
this->init_pos = ImVec2(pos_x, 8);
|
||||
int pos_x =
|
||||
overlay::FPS_SHOULD_FLIP ?
|
||||
overlay::apply_scaling(8) :
|
||||
ImGui::GetIO().DisplaySize.x - overlay::apply_scaling(122);
|
||||
this->init_pos = ImVec2(pos_x, overlay::apply_scaling(8));
|
||||
}
|
||||
|
||||
void FPS::build_content() {
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace overlay::windows {
|
||||
this->flags = ImGuiWindowFlags_AlwaysAutoResize;
|
||||
|
||||
this->init_size = ImVec2(
|
||||
80,
|
||||
overlay::apply_scaling(80),
|
||||
ImGui::GetFrameHeight() +
|
||||
ImGui::GetStyle().WindowPadding.y * 2 +
|
||||
ImGui::GetFrameHeightWithSpacing() * 3 +
|
||||
@@ -58,7 +58,7 @@ namespace overlay::windows {
|
||||
void IOPanel::build_io_panel() {}
|
||||
|
||||
void IOPanel::build_operator_menu() {
|
||||
const ImVec2 wide(60, 0);
|
||||
const ImVec2 wide = overlay::apply_scaling_to_vector(60, 0);
|
||||
const float spacing_x = ImGui::GetStyle().ItemSpacing.y;
|
||||
const ImVec2 tall(
|
||||
ImGui::GetFrameHeight(),
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace overlay::windows {
|
||||
}
|
||||
|
||||
void GitadoraIOPanel::build_io_panel() {
|
||||
ImGui::Dummy(ImVec2(12, 0));
|
||||
ImGui::Dummy(overlay::apply_scaling_to_vector(12, 0));
|
||||
|
||||
ImGui::SameLine();
|
||||
this->draw_buttons(0);
|
||||
@@ -80,7 +80,7 @@ namespace overlay::windows {
|
||||
// draw p2 only if guitar freaks
|
||||
if (this->two_players) {
|
||||
ImGui::SameLine();
|
||||
ImGui::Dummy(ImVec2(12, 0));
|
||||
ImGui::Dummy(overlay::apply_scaling_to_vector(12, 0));
|
||||
ImGui::SameLine();
|
||||
this->draw_buttons(1);
|
||||
if (this->has_guitar_knobs) {
|
||||
@@ -146,7 +146,7 @@ namespace overlay::windows {
|
||||
games::gitadora::Analogs::GuitarP1Knob :
|
||||
games::gitadora::Analogs::GuitarP2Knob;
|
||||
|
||||
const ImVec2 slider_size(32, get_suggested_height());
|
||||
const ImVec2 slider_size(overlay::apply_scaling(32), get_suggested_height());
|
||||
|
||||
// get analog
|
||||
const auto analogs = games::get_analogs(eamuse_get_game());
|
||||
|
||||
@@ -19,15 +19,15 @@ namespace overlay::windows {
|
||||
case 0: {
|
||||
this->toggle_button = games::OverlayButtons::ToggleVirtualKeypadP1;
|
||||
this->init_pos = ImVec2(
|
||||
26,
|
||||
ImGui::GetIO().DisplaySize.y - 264);
|
||||
overlay::apply_scaling(26),
|
||||
ImGui::GetIO().DisplaySize.y - overlay::apply_scaling(264));
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
this->toggle_button = games::OverlayButtons::ToggleVirtualKeypadP2;
|
||||
this->init_pos = ImVec2(
|
||||
ImGui::GetIO().DisplaySize.x - 220,
|
||||
ImGui::GetIO().DisplaySize.y - 264);
|
||||
ImGui::GetIO().DisplaySize.x - overlay::apply_scaling(220),
|
||||
ImGui::GetIO().DisplaySize.y - overlay::apply_scaling(264));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -82,9 +82,17 @@ namespace overlay::windows {
|
||||
|
||||
// add selectable (fill last line)
|
||||
if (i == std::size(BUTTONS) - 1) {
|
||||
ImGui::Selectable(button.text, false, 0, ImVec2(112, 32));
|
||||
ImGui::Selectable(
|
||||
button.text,
|
||||
false,
|
||||
0,
|
||||
overlay::apply_scaling_to_vector(ImVec2(112, 32)));
|
||||
} else {
|
||||
ImGui::Selectable(button.text, false, 0, ImVec2(32, 32));
|
||||
ImGui::Selectable(
|
||||
button.text,
|
||||
false,
|
||||
0,
|
||||
overlay::apply_scaling_to_vector(ImVec2(32, 32)));
|
||||
}
|
||||
|
||||
// mouse down handler
|
||||
|
||||
Reference in New Issue
Block a user