mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5065a92d55 | |||
| 5483e8e2c0 | |||
| e8949a2612 | |||
| db71a0b24d | |||
| d3d5422768 | |||
| 5185f753e5 |
@@ -21,6 +21,8 @@ static const char *CLASS_NAME = "ConfiguratorWindow";
|
||||
static std::string WINDOW_TITLE;
|
||||
static int WINDOW_SIZE_X = 800;
|
||||
static int WINDOW_SIZE_Y = 600;
|
||||
static const int WINDOW_MIN_SIZE_X = 540;
|
||||
static const int WINDOW_MIN_SIZE_Y = 300;
|
||||
static HICON WINDOW_ICON = LoadIcon(GetModuleHandle(nullptr), MAKEINTRESOURCE(MAINICON));
|
||||
|
||||
static const UINT_PTR RENDER_TIMER_ID = 1;
|
||||
@@ -85,6 +87,23 @@ static cfg::ConfiguratorWindow *get_state(HWND hWnd) {
|
||||
GetWindowLongPtrW(hWnd, GWLP_USERDATA));
|
||||
}
|
||||
|
||||
// computes the top-left position that centers a window of the given size on
|
||||
// the primary monitor's work area (the desktop minus the taskbar); falls back
|
||||
// to (0, 0) if the monitor info can't be queried.
|
||||
static POINT center_on_primary_monitor(int width, int height) {
|
||||
POINT pos = { 0, 0 };
|
||||
HMONITOR mon = MonitorFromPoint(pos, MONITOR_DEFAULTTOPRIMARY);
|
||||
MONITORINFO mi {};
|
||||
mi.cbSize = sizeof(mi);
|
||||
if (GetMonitorInfo(mon, &mi)) {
|
||||
const int work_w = mi.rcWork.right - mi.rcWork.left;
|
||||
const int work_h = mi.rcWork.bottom - mi.rcWork.top;
|
||||
pos.x = mi.rcWork.left + (work_w - width) / 2;
|
||||
pos.y = mi.rcWork.top + (work_h - height) / 2;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
// Returns the refresh rate (Hz) of the monitor the window currently lives on,
|
||||
// clamped to a sane range. Falls back to 60 if detection fails or the value
|
||||
// looks invalid (DEVMODE may report 0 or 1 to mean "use hardware default").
|
||||
@@ -243,8 +262,10 @@ cfg::ConfiguratorWindow::~ConfiguratorWindow() {
|
||||
|
||||
void cfg::ConfiguratorWindow::run() {
|
||||
|
||||
const POINT pos = center_on_primary_monitor(WINDOW_SIZE_X, WINDOW_SIZE_Y);
|
||||
SetWindowPos(this->hWnd, HWND_TOP, pos.x, pos.y, WINDOW_SIZE_X, WINDOW_SIZE_Y, 0);
|
||||
|
||||
// show window
|
||||
SetWindowPos(this->hWnd, HWND_TOP, 0, 0, WINDOW_SIZE_X, WINDOW_SIZE_Y, 0);
|
||||
ShowWindow(this->hWnd, SW_SHOWNORMAL);
|
||||
UpdateWindow(this->hWnd);
|
||||
|
||||
@@ -290,6 +311,22 @@ LRESULT CALLBACK cfg::ConfiguratorWindow::window_proc(HWND hWnd, UINT uMsg, WPAR
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_GETMINMAXINFO: {
|
||||
|
||||
// enforce a minimum window size so the UI can't be shrunk to a
|
||||
// point where the tabs/controls become unusable. The minimum is
|
||||
// expressed in client-area pixels and converted to a full window
|
||||
// size that accounts for the current frame/title-bar style.
|
||||
RECT rc = { 0, 0, WINDOW_MIN_SIZE_X, WINDOW_MIN_SIZE_Y };
|
||||
DWORD style = static_cast<DWORD>(GetWindowLongPtrW(hWnd, GWL_STYLE));
|
||||
DWORD ex_style = static_cast<DWORD>(GetWindowLongPtrW(hWnd, GWL_EXSTYLE));
|
||||
if (AdjustWindowRectEx(&rc, style, FALSE, ex_style)) {
|
||||
auto *mmi = reinterpret_cast<MINMAXINFO *>(lParam);
|
||||
mmi->ptMinTrackSize.x = rc.right - rc.left;
|
||||
mmi->ptMinTrackSize.y = rc.bottom - rc.top;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_CREATE: {
|
||||
|
||||
// set user data of window to class pointer
|
||||
|
||||
@@ -1273,9 +1273,11 @@ static void graphics_d3d9_ldj_on_present(IDirect3DDevice9 *wrapped_device) {
|
||||
wintouchemu::update();
|
||||
|
||||
// newer versions of exceed gear needs SUBSCREEN_FORCE_REDRAW
|
||||
// (when enabled on older versions of EG, you end up with graphical glitches on the subscreen
|
||||
// early versions of popn HC needs this as well, otherwise the subscreen doesn't update at all
|
||||
if (GRAPHICS_WINDOWED || SUBSCREEN_FORCE_REDRAW || games::popn::is_pikapika_model()) {
|
||||
// (when enabled on older versions of EG, you end up with graphical glitches on the subscreen)
|
||||
//
|
||||
// early versions of popn HC needs this as well, but not on by default as it can cause
|
||||
// graphical glitches on some GPUs
|
||||
if (GRAPHICS_WINDOWED || SUBSCREEN_FORCE_REDRAW) {
|
||||
SUB_SWAP_CHAIN->Present(nullptr, nullptr, nullptr, nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -643,6 +643,9 @@ int main_implementation(int argc, char *argv[]) {
|
||||
if (options[launcher::Options::PopnNativeTouch].value_bool()) {
|
||||
games::popn::NATIVE_TOUCH = true;
|
||||
}
|
||||
if (options[launcher::Options::PopnSubRedraw].value_bool()) {
|
||||
SUBSCREEN_FORCE_REDRAW = true;
|
||||
}
|
||||
if (options[launcher::Options::LoadMetalGearArcadeModule].value_bool()) {
|
||||
attach_mga = true;
|
||||
}
|
||||
@@ -1546,8 +1549,19 @@ int main_implementation(int argc, char *argv[]) {
|
||||
|
||||
// print out conflicts
|
||||
size_t conflicts = 0;
|
||||
for (const auto &option : options) {
|
||||
if (option.conflicting && option.get_definition().type != OptionType::Bool) {
|
||||
for (size_t i = 0; i < options.size(); i++) {
|
||||
// InjectHook / EarlyInjectHook accept multiple values, so command line and
|
||||
// spicecfg entries are merged rather than conflicting; don't warn about them
|
||||
if (i == (size_t) launcher::Options::InjectHook ||
|
||||
i == (size_t) launcher::Options::EarlyInjectHook) {
|
||||
continue;
|
||||
}
|
||||
const auto &option = options[i];
|
||||
// ignore Boolean values
|
||||
if (option.get_definition().type == OptionType::Bool) {
|
||||
continue;
|
||||
}
|
||||
if (option.conflicting) {
|
||||
conflicts += 1;
|
||||
const auto& value = option.get_definition().sensitive ? "*****" : option.value;
|
||||
if (launcher::USE_CMD_OVERRIDE) {
|
||||
|
||||
@@ -1138,6 +1138,17 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.game_name = "Pop'n Music",
|
||||
.category = "Advanced Game Options",
|
||||
},
|
||||
{
|
||||
// PopnSubRedraw
|
||||
.title = "Pop'n Music PikaPika Subscreen Force Redraw",
|
||||
.name = "popnsubredraw",
|
||||
.desc = "Check if submonitor in fullscreen mode appears stuck; "
|
||||
"this option forces subscreen to redraw every frame.",
|
||||
.type = OptionType::Bool,
|
||||
.game_name = "Pop'n Music",
|
||||
.category = "Advanced Game Options",
|
||||
.quick_setting_category = "Game",
|
||||
},
|
||||
{
|
||||
.title = "Force Load HELLO! Pop'n Music Module",
|
||||
.name = "hpm",
|
||||
|
||||
@@ -108,6 +108,7 @@ namespace launcher {
|
||||
PopnNoSub,
|
||||
PopnSubMonitorOverride,
|
||||
PopnNativeTouch,
|
||||
PopnSubRedraw,
|
||||
LoadHelloPopnMusicModule,
|
||||
LoadGitaDoraModule,
|
||||
GitaDoraTwoChannelAudio,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <cmath>
|
||||
|
||||
#include "external/imgui/imgui.h"
|
||||
#include "external/imgui/imgui_internal.h"
|
||||
#include "overlay/overlay.h"
|
||||
|
||||
|
||||
@@ -209,17 +210,17 @@ namespace ImGui {
|
||||
return open;
|
||||
}
|
||||
|
||||
void InvisibleTableRowSelectable() {
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
ImGui::PushStyleColor(ImGuiCol_Header, 0);
|
||||
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, 0);
|
||||
ImGui::PushStyleColor(ImGuiCol_HeaderActive, 0);
|
||||
ImGui::PushTabStop(false); // prevent tab navigation
|
||||
ImGui::Selectable("##row", false,
|
||||
ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap);
|
||||
ImGui::PopTabStop();
|
||||
ImGui::PopStyleColor(3);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
void HighlightTableRowOnHover() {
|
||||
// hit-test the row rect directly so the row layout and height are untouched
|
||||
ImGuiTable *table = ImGui::GetCurrentTable();
|
||||
if (table == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (ImGui::IsWindowHovered() &&
|
||||
ImGui::IsMouseHoveringRect(
|
||||
ImVec2(table->WorkRect.Min.x, table->RowPosY1),
|
||||
ImVec2(table->WorkRect.Max.x, table->RowPosY2),
|
||||
false)) {
|
||||
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg1, IM_COL32(200, 200, 200, 24));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace ImGui {
|
||||
void TextTruncated(const std::string& p_text, float p_truncated_width);
|
||||
bool DeleteButton(const std::string& tooltip);
|
||||
bool ClearButton(const std::string& tooltip);
|
||||
void InvisibleTableRowSelectable();
|
||||
void HighlightTableRowOnHover();
|
||||
|
||||
// Config tab bar with extra label padding and uniform, centered tab widths.
|
||||
// Wrap items in BeginPaddedTabItem between BeginPaddedTabBar/EndTabBar.
|
||||
|
||||
@@ -928,18 +928,14 @@ namespace overlay::windows {
|
||||
|
||||
// primary
|
||||
build_button(name, primary_button, &primary_button, button_it, button_it_max, 0);
|
||||
ImGui::PushID(&primary_button);
|
||||
ImGui::InvisibleTableRowSelectable();
|
||||
ImGui::PopID();
|
||||
ImGui::HighlightTableRowOnHover();
|
||||
|
||||
// alternatives
|
||||
int alt_index = 1; // 0 is primary
|
||||
for (auto &alt : primary_button.getAlternatives()) {
|
||||
if (alt.isValid()) {
|
||||
build_button(name, primary_button, &alt, button_it, button_it_max, alt_index);
|
||||
ImGui::PushID(&alt);
|
||||
ImGui::InvisibleTableRowSelectable();
|
||||
ImGui::PopID();
|
||||
ImGui::HighlightTableRowOnHover();
|
||||
}
|
||||
alt_index++;
|
||||
}
|
||||
@@ -2519,8 +2515,7 @@ namespace overlay::windows {
|
||||
|
||||
edit_analog_popup(analog, title);
|
||||
|
||||
// row hover detection (invisible selectable that spans entire row)
|
||||
ImGui::InvisibleTableRowSelectable();
|
||||
ImGui::HighlightTableRowOnHover();
|
||||
|
||||
// clean up
|
||||
ImGui::PopID();
|
||||
@@ -3174,16 +3169,12 @@ namespace overlay::windows {
|
||||
}
|
||||
|
||||
build_light(light, &light, i, 0);
|
||||
ImGui::PushID(&light);
|
||||
ImGui::InvisibleTableRowSelectable();
|
||||
ImGui::PopID();
|
||||
ImGui::HighlightTableRowOnHover();
|
||||
int alt_index = 1;
|
||||
for (auto &alt : light.getAlternatives()) {
|
||||
if (alt.isValid()) {
|
||||
build_light(light, &alt, i, alt_index);
|
||||
ImGui::PushID(&alt);
|
||||
ImGui::InvisibleTableRowSelectable();
|
||||
ImGui::PopID();
|
||||
ImGui::HighlightTableRowOnHover();
|
||||
}
|
||||
alt_index++;
|
||||
}
|
||||
@@ -4209,8 +4200,10 @@ namespace overlay::windows {
|
||||
|
||||
ImGui::TextColored(ImVec4(1, 0.7f, 0, 1), "Card overrides");
|
||||
ImGui::Spacing();
|
||||
ImGui::TextUnformatted(
|
||||
"Specify hardcoded card numbers here. This will always take priority when Insert Card is pressed.");
|
||||
ImGui::TextWrapped(
|
||||
"%s",
|
||||
"Specify hardcoded card numbers here.\n\n"
|
||||
"Overrides will always take priority when Insert Card is pressed.");
|
||||
ImGui::Spacing();
|
||||
|
||||
// read in values from options
|
||||
@@ -4387,7 +4380,8 @@ namespace overlay::windows {
|
||||
ImGui::Spacing();
|
||||
ImGui::TextColored(ImVec4(1, 0.7f, 0, 1), "Card from text files");
|
||||
ImGui::Spacing();
|
||||
ImGui::TextUnformatted(
|
||||
ImGui::TextWrapped(
|
||||
"%s",
|
||||
"Use text files on disk; its content will be read when Insert Card is pressed.");
|
||||
ImGui::Spacing();
|
||||
|
||||
@@ -5293,8 +5287,7 @@ namespace overlay::windows {
|
||||
}
|
||||
}
|
||||
|
||||
// row hover detection (invisible selectable that spans entire row)
|
||||
ImGui::InvisibleTableRowSelectable();
|
||||
ImGui::HighlightTableRowOnHover();
|
||||
|
||||
// next item
|
||||
ImGui::PopID();
|
||||
@@ -5787,23 +5780,28 @@ namespace overlay::windows {
|
||||
|
||||
// name
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::TextTruncated(
|
||||
t.name, ImGui::GetContentRegionAvail().x - overlay::apply_scaling(20));
|
||||
|
||||
// type
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::TextUnformatted(t.is_builtin ? "Built-in" : "User");
|
||||
|
||||
// buttons
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("%d", (int)t.buttons.size());
|
||||
|
||||
// analogs
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("%d", (int)t.analogs.size());
|
||||
|
||||
// lights
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("%d", (int)t.lights.size());
|
||||
|
||||
// actions
|
||||
@@ -5831,7 +5829,7 @@ namespace overlay::windows {
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::InvisibleTableRowSelectable();
|
||||
ImGui::HighlightTableRowOnHover();
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
|
||||
@@ -876,8 +876,7 @@ namespace overlay::windows {
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
// row hover detection (invisible selectable that spans entire row)
|
||||
ImGui::InvisibleTableRowSelectable();
|
||||
ImGui::HighlightTableRowOnHover();
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user