mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-07-09 17:25:37 -06:00
Handle accept invite dialog with gamepad (#4681)
* invitation dlg with gamepad * fixup * classic
This commit is contained in:
parent
eabd04d35d
commit
474fbe741d
@ -14,6 +14,7 @@
|
||||
#include "core/libraries/np/np_handler.h"
|
||||
#include "imgui/imgui_layer.h"
|
||||
#include "imgui/invitation_prompt_layer.h"
|
||||
#include "imgui/renderer/imgui_core.h"
|
||||
#include "imgui/shadnet_notifications_layer.h"
|
||||
|
||||
namespace ImGui::InvitationPrompt {
|
||||
@ -34,10 +35,15 @@ struct Prompt {
|
||||
};
|
||||
|
||||
constexpr std::size_t kMaxPrompts = 4; // oldest dropped beyond this
|
||||
constexpr float kFocusHoldSeconds = 0.6f; // hold Share/Back this long to focus the prompt
|
||||
|
||||
std::mutex g_mutex;
|
||||
std::deque<Prompt> g_prompts;
|
||||
|
||||
bool g_focused = false;
|
||||
bool g_capture_held = false;
|
||||
float g_back_held_secs = 0.0f;
|
||||
|
||||
class InvitationPromptUI final : public ImGui::Layer {
|
||||
public:
|
||||
void Draw() override;
|
||||
@ -92,6 +98,20 @@ void RunDecline(Prompt prompt) {
|
||||
}).detach();
|
||||
}
|
||||
|
||||
void SetFocused(bool focused) {
|
||||
if (g_focused == focused) {
|
||||
return;
|
||||
}
|
||||
g_focused = focused;
|
||||
if (focused && !g_capture_held) {
|
||||
ImGui::Core::AcquireGamepadInputCapture();
|
||||
g_capture_held = true;
|
||||
} else if (!focused && g_capture_held) {
|
||||
ImGui::Core::ReleaseGamepadInputCapture();
|
||||
g_capture_held = false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Push(s32 user_id, std::string invitation_id, std::string session_id, std::string from_npid) {
|
||||
@ -117,6 +137,7 @@ void Register() {
|
||||
}
|
||||
|
||||
void Unregister() {
|
||||
SetFocused(false);
|
||||
ImGui::Layer::RemoveLayer(&g_layer);
|
||||
}
|
||||
|
||||
@ -124,28 +145,49 @@ void InvitationPromptUI::Draw() {
|
||||
std::vector<Prompt> snapshot;
|
||||
{
|
||||
std::lock_guard lock(g_mutex);
|
||||
if (g_prompts.empty()) {
|
||||
snapshot.assign(g_prompts.begin(), g_prompts.end());
|
||||
}
|
||||
|
||||
if (snapshot.empty()) {
|
||||
SetFocused(false);
|
||||
return;
|
||||
}
|
||||
snapshot.assign(g_prompts.begin(), g_prompts.end());
|
||||
|
||||
if (!g_focused) {
|
||||
if (ImGui::IsKeyDown(ImGuiKey_GamepadBack)) {
|
||||
g_back_held_secs += ImGui::GetIO().DeltaTime;
|
||||
if (g_back_held_secs >= kFocusHoldSeconds) {
|
||||
g_back_held_secs = 0.0f;
|
||||
SetFocused(true);
|
||||
}
|
||||
} else {
|
||||
g_back_held_secs = 0.0f;
|
||||
}
|
||||
} else {
|
||||
// Stage 2 -> 1: Circle (nav cancel) or Escape returns control to the game.
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_GamepadFaceRight, false) ||
|
||||
ImGui::IsKeyPressed(ImGuiKey_Escape, false)) {
|
||||
SetFocused(false);
|
||||
}
|
||||
}
|
||||
|
||||
auto& io = ImGui::GetIO();
|
||||
const float scale = io.DisplaySize.x / 1920.0f;
|
||||
const float width = 420.0f * scale;
|
||||
const float width = 440.0f * scale;
|
||||
const float margin = 20.0f * scale;
|
||||
|
||||
// Top-center, below the top edge,the transient shadNet toasts live top-right so the two
|
||||
// don't collide. Mouse-interactive but NoNav so gamepad navigation stays with the game.
|
||||
ImGui::SetNextWindowPos(ImVec2(io.DisplaySize.x / 2.0f, margin), ImGuiCond_Always,
|
||||
ImVec2(0.5f, 0.0f));
|
||||
ImGui::SetNextWindowSize(ImVec2(width, 0.0f), ImGuiCond_Always);
|
||||
ImGui::SetNextWindowBgAlpha(0.92f);
|
||||
ImGui::SetNextWindowBgAlpha(g_focused ? 0.97f : 0.85f);
|
||||
|
||||
const ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoNav |
|
||||
ImGuiWindowFlags_NoFocusOnAppearing |
|
||||
ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoMove |
|
||||
ImGuiWindowFlags_AlwaysAutoResize;
|
||||
ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings |
|
||||
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize;
|
||||
if (g_focused) {
|
||||
ImGui::SetNextWindowFocus();
|
||||
} else {
|
||||
flags |= ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoFocusOnAppearing;
|
||||
}
|
||||
|
||||
if (ImGui::Begin("##invitation_prompts", nullptr, flags)) {
|
||||
bool first = true;
|
||||
@ -167,6 +209,9 @@ void InvitationPromptUI::Draw() {
|
||||
if (ImGui::Button(busy ? "Joining..." : "Accept", ImVec2(120.0f * scale, 0.0f))) {
|
||||
RunAccept(p);
|
||||
}
|
||||
if (g_focused && &p == snapshot.data()) {
|
||||
ImGui::SetItemDefaultFocus(); // nav lands on Accept of the newest-focused prompt
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Decline", ImVec2(120.0f * scale, 0.0f))) {
|
||||
RunDecline(p);
|
||||
@ -174,6 +219,10 @@ void InvitationPromptUI::Draw() {
|
||||
ImGui::PopID();
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
ImGui::Spacing();
|
||||
ImGui::TextDisabled(g_focused ? "D-Pad: select Cross: confirm Circle/Esc: back to game"
|
||||
: "Hold Share/Back to respond, or click");
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user