mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-02 06:40: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 std::string WINDOW_TITLE;
|
||||||
static int WINDOW_SIZE_X = 800;
|
static int WINDOW_SIZE_X = 800;
|
||||||
static int WINDOW_SIZE_Y = 600;
|
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 HICON WINDOW_ICON = LoadIcon(GetModuleHandle(nullptr), MAKEINTRESOURCE(MAINICON));
|
||||||
|
|
||||||
static const UINT_PTR RENDER_TIMER_ID = 1;
|
static const UINT_PTR RENDER_TIMER_ID = 1;
|
||||||
@@ -85,6 +87,23 @@ static cfg::ConfiguratorWindow *get_state(HWND hWnd) {
|
|||||||
GetWindowLongPtrW(hWnd, GWLP_USERDATA));
|
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,
|
// 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
|
// 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").
|
// looks invalid (DEVMODE may report 0 or 1 to mean "use hardware default").
|
||||||
@@ -243,8 +262,10 @@ cfg::ConfiguratorWindow::~ConfiguratorWindow() {
|
|||||||
|
|
||||||
void cfg::ConfiguratorWindow::run() {
|
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
|
// show window
|
||||||
SetWindowPos(this->hWnd, HWND_TOP, 0, 0, WINDOW_SIZE_X, WINDOW_SIZE_Y, 0);
|
|
||||||
ShowWindow(this->hWnd, SW_SHOWNORMAL);
|
ShowWindow(this->hWnd, SW_SHOWNORMAL);
|
||||||
UpdateWindow(this->hWnd);
|
UpdateWindow(this->hWnd);
|
||||||
|
|
||||||
@@ -290,6 +311,22 @@ LRESULT CALLBACK cfg::ConfiguratorWindow::window_proc(HWND hWnd, UINT uMsg, WPAR
|
|||||||
}
|
}
|
||||||
break;
|
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: {
|
case WM_CREATE: {
|
||||||
|
|
||||||
// set user data of window to class pointer
|
// set user data of window to class pointer
|
||||||
|
|||||||
@@ -1273,9 +1273,11 @@ static void graphics_d3d9_ldj_on_present(IDirect3DDevice9 *wrapped_device) {
|
|||||||
wintouchemu::update();
|
wintouchemu::update();
|
||||||
|
|
||||||
// newer versions of exceed gear needs SUBSCREEN_FORCE_REDRAW
|
// 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
|
// (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()) {
|
// 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);
|
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()) {
|
if (options[launcher::Options::PopnNativeTouch].value_bool()) {
|
||||||
games::popn::NATIVE_TOUCH = true;
|
games::popn::NATIVE_TOUCH = true;
|
||||||
}
|
}
|
||||||
|
if (options[launcher::Options::PopnSubRedraw].value_bool()) {
|
||||||
|
SUBSCREEN_FORCE_REDRAW = true;
|
||||||
|
}
|
||||||
if (options[launcher::Options::LoadMetalGearArcadeModule].value_bool()) {
|
if (options[launcher::Options::LoadMetalGearArcadeModule].value_bool()) {
|
||||||
attach_mga = true;
|
attach_mga = true;
|
||||||
}
|
}
|
||||||
@@ -1546,8 +1549,19 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
|
|
||||||
// print out conflicts
|
// print out conflicts
|
||||||
size_t conflicts = 0;
|
size_t conflicts = 0;
|
||||||
for (const auto &option : options) {
|
for (size_t i = 0; i < options.size(); i++) {
|
||||||
if (option.conflicting && option.get_definition().type != OptionType::Bool) {
|
// 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;
|
conflicts += 1;
|
||||||
const auto& value = option.get_definition().sensitive ? "*****" : option.value;
|
const auto& value = option.get_definition().sensitive ? "*****" : option.value;
|
||||||
if (launcher::USE_CMD_OVERRIDE) {
|
if (launcher::USE_CMD_OVERRIDE) {
|
||||||
|
|||||||
@@ -1138,6 +1138,17 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.game_name = "Pop'n Music",
|
.game_name = "Pop'n Music",
|
||||||
.category = "Advanced Game Options",
|
.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",
|
.title = "Force Load HELLO! Pop'n Music Module",
|
||||||
.name = "hpm",
|
.name = "hpm",
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ namespace launcher {
|
|||||||
PopnNoSub,
|
PopnNoSub,
|
||||||
PopnSubMonitorOverride,
|
PopnSubMonitorOverride,
|
||||||
PopnNativeTouch,
|
PopnNativeTouch,
|
||||||
|
PopnSubRedraw,
|
||||||
LoadHelloPopnMusicModule,
|
LoadHelloPopnMusicModule,
|
||||||
LoadGitaDoraModule,
|
LoadGitaDoraModule,
|
||||||
GitaDoraTwoChannelAudio,
|
GitaDoraTwoChannelAudio,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include "external/imgui/imgui.h"
|
#include "external/imgui/imgui.h"
|
||||||
|
#include "external/imgui/imgui_internal.h"
|
||||||
#include "overlay/overlay.h"
|
#include "overlay/overlay.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -209,17 +210,17 @@ namespace ImGui {
|
|||||||
return open;
|
return open;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InvisibleTableRowSelectable() {
|
void HighlightTableRowOnHover() {
|
||||||
ImGui::TableSetColumnIndex(0);
|
// hit-test the row rect directly so the row layout and height are untouched
|
||||||
ImGui::PushStyleColor(ImGuiCol_Header, 0);
|
ImGuiTable *table = ImGui::GetCurrentTable();
|
||||||
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, 0);
|
if (table == nullptr) {
|
||||||
ImGui::PushStyleColor(ImGuiCol_HeaderActive, 0);
|
return;
|
||||||
ImGui::PushTabStop(false); // prevent tab navigation
|
}
|
||||||
ImGui::Selectable("##row", false,
|
if (ImGui::IsWindowHovered() &&
|
||||||
ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap);
|
ImGui::IsMouseHoveringRect(
|
||||||
ImGui::PopTabStop();
|
ImVec2(table->WorkRect.Min.x, table->RowPosY1),
|
||||||
ImGui::PopStyleColor(3);
|
ImVec2(table->WorkRect.Max.x, table->RowPosY2),
|
||||||
if (ImGui::IsItemHovered()) {
|
false)) {
|
||||||
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg1, IM_COL32(200, 200, 200, 24));
|
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);
|
void TextTruncated(const std::string& p_text, float p_truncated_width);
|
||||||
bool DeleteButton(const std::string& tooltip);
|
bool DeleteButton(const std::string& tooltip);
|
||||||
bool ClearButton(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.
|
// Config tab bar with extra label padding and uniform, centered tab widths.
|
||||||
// Wrap items in BeginPaddedTabItem between BeginPaddedTabBar/EndTabBar.
|
// Wrap items in BeginPaddedTabItem between BeginPaddedTabBar/EndTabBar.
|
||||||
|
|||||||
@@ -928,18 +928,14 @@ namespace overlay::windows {
|
|||||||
|
|
||||||
// primary
|
// primary
|
||||||
build_button(name, primary_button, &primary_button, button_it, button_it_max, 0);
|
build_button(name, primary_button, &primary_button, button_it, button_it_max, 0);
|
||||||
ImGui::PushID(&primary_button);
|
ImGui::HighlightTableRowOnHover();
|
||||||
ImGui::InvisibleTableRowSelectable();
|
|
||||||
ImGui::PopID();
|
|
||||||
|
|
||||||
// alternatives
|
// alternatives
|
||||||
int alt_index = 1; // 0 is primary
|
int alt_index = 1; // 0 is primary
|
||||||
for (auto &alt : primary_button.getAlternatives()) {
|
for (auto &alt : primary_button.getAlternatives()) {
|
||||||
if (alt.isValid()) {
|
if (alt.isValid()) {
|
||||||
build_button(name, primary_button, &alt, button_it, button_it_max, alt_index);
|
build_button(name, primary_button, &alt, button_it, button_it_max, alt_index);
|
||||||
ImGui::PushID(&alt);
|
ImGui::HighlightTableRowOnHover();
|
||||||
ImGui::InvisibleTableRowSelectable();
|
|
||||||
ImGui::PopID();
|
|
||||||
}
|
}
|
||||||
alt_index++;
|
alt_index++;
|
||||||
}
|
}
|
||||||
@@ -2519,8 +2515,7 @@ namespace overlay::windows {
|
|||||||
|
|
||||||
edit_analog_popup(analog, title);
|
edit_analog_popup(analog, title);
|
||||||
|
|
||||||
// row hover detection (invisible selectable that spans entire row)
|
ImGui::HighlightTableRowOnHover();
|
||||||
ImGui::InvisibleTableRowSelectable();
|
|
||||||
|
|
||||||
// clean up
|
// clean up
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
@@ -3174,16 +3169,12 @@ namespace overlay::windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
build_light(light, &light, i, 0);
|
build_light(light, &light, i, 0);
|
||||||
ImGui::PushID(&light);
|
ImGui::HighlightTableRowOnHover();
|
||||||
ImGui::InvisibleTableRowSelectable();
|
|
||||||
ImGui::PopID();
|
|
||||||
int alt_index = 1;
|
int alt_index = 1;
|
||||||
for (auto &alt : light.getAlternatives()) {
|
for (auto &alt : light.getAlternatives()) {
|
||||||
if (alt.isValid()) {
|
if (alt.isValid()) {
|
||||||
build_light(light, &alt, i, alt_index);
|
build_light(light, &alt, i, alt_index);
|
||||||
ImGui::PushID(&alt);
|
ImGui::HighlightTableRowOnHover();
|
||||||
ImGui::InvisibleTableRowSelectable();
|
|
||||||
ImGui::PopID();
|
|
||||||
}
|
}
|
||||||
alt_index++;
|
alt_index++;
|
||||||
}
|
}
|
||||||
@@ -4209,8 +4200,10 @@ namespace overlay::windows {
|
|||||||
|
|
||||||
ImGui::TextColored(ImVec4(1, 0.7f, 0, 1), "Card overrides");
|
ImGui::TextColored(ImVec4(1, 0.7f, 0, 1), "Card overrides");
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
ImGui::TextUnformatted(
|
ImGui::TextWrapped(
|
||||||
"Specify hardcoded card numbers here. This will always take priority when Insert Card is pressed.");
|
"%s",
|
||||||
|
"Specify hardcoded card numbers here.\n\n"
|
||||||
|
"Overrides will always take priority when Insert Card is pressed.");
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
|
|
||||||
// read in values from options
|
// read in values from options
|
||||||
@@ -4387,7 +4380,8 @@ namespace overlay::windows {
|
|||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
ImGui::TextColored(ImVec4(1, 0.7f, 0, 1), "Card from text files");
|
ImGui::TextColored(ImVec4(1, 0.7f, 0, 1), "Card from text files");
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
ImGui::TextUnformatted(
|
ImGui::TextWrapped(
|
||||||
|
"%s",
|
||||||
"Use text files on disk; its content will be read when Insert Card is pressed.");
|
"Use text files on disk; its content will be read when Insert Card is pressed.");
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
|
|
||||||
@@ -5293,8 +5287,7 @@ namespace overlay::windows {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// row hover detection (invisible selectable that spans entire row)
|
ImGui::HighlightTableRowOnHover();
|
||||||
ImGui::InvisibleTableRowSelectable();
|
|
||||||
|
|
||||||
// next item
|
// next item
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
@@ -5787,23 +5780,28 @@ namespace overlay::windows {
|
|||||||
|
|
||||||
// name
|
// name
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::TextTruncated(
|
ImGui::TextTruncated(
|
||||||
t.name, ImGui::GetContentRegionAvail().x - overlay::apply_scaling(20));
|
t.name, ImGui::GetContentRegionAvail().x - overlay::apply_scaling(20));
|
||||||
|
|
||||||
// type
|
// type
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::TextUnformatted(t.is_builtin ? "Built-in" : "User");
|
ImGui::TextUnformatted(t.is_builtin ? "Built-in" : "User");
|
||||||
|
|
||||||
// buttons
|
// buttons
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::Text("%d", (int)t.buttons.size());
|
ImGui::Text("%d", (int)t.buttons.size());
|
||||||
|
|
||||||
// analogs
|
// analogs
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::Text("%d", (int)t.analogs.size());
|
ImGui::Text("%d", (int)t.analogs.size());
|
||||||
|
|
||||||
// lights
|
// lights
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::Text("%d", (int)t.lights.size());
|
ImGui::Text("%d", (int)t.lights.size());
|
||||||
|
|
||||||
// actions
|
// actions
|
||||||
@@ -5831,7 +5829,7 @@ namespace overlay::windows {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::InvisibleTableRowSelectable();
|
ImGui::HighlightTableRowOnHover();
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -876,8 +876,7 @@ namespace overlay::windows {
|
|||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
// row hover detection (invisible selectable that spans entire row)
|
ImGui::HighlightTableRowOnHover();
|
||||||
ImGui::InvisibleTableRowSelectable();
|
|
||||||
|
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user