#include "debug_overlay.hpp" #include namespace coop { namespace { struct ButtonBit { std::uint16_t mask; const char* label; }; // XINPUT_GAMEPAD_* bit values (kept local so this file needn't include Xinput.h). constexpr ButtonBit kButtons[] = { {0x0001, "Up"}, {0x0002, "Down"}, {0x0004, "Left"}, {0x0008, "Right"}, {0x0010, "Start"}, {0x0020, "Back"}, {0x0040, "LS"}, {0x0080, "RS"}, {0x0100, "LB"}, {0x0200, "RB"}, {0x1000, "A"}, {0x2000, "B"}, {0x4000, "X"}, {0x8000, "Y"}, }; void draw_pad(int index, const PadInfo& pad) { ImGui::PushID(index); if (!pad.connected) { ImGui::TextDisabled("Slot %d: disconnected", index); ImGui::PopID(); return; } ImGui::Text("Slot %d [%s]", index, pad.source.c_str()); ImGui::Text("LT %3u RT %3u", pad.state.left_trigger, pad.state.right_trigger); ImGui::Text("L (%6d, %6d) R (%6d, %6d)", pad.state.thumb_lx, pad.state.thumb_ly, pad.state.thumb_rx, pad.state.thumb_ry); bool first = true; ImGui::TextUnformatted("Buttons: "); for (const ButtonBit& b : kButtons) { if ((pad.state.buttons & b.mask) != 0) { ImGui::SameLine(); ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f), "%s%s", first ? "" : ", ", b.label); first = false; } } if (first) { ImGui::SameLine(); ImGui::TextDisabled("(none)"); } ImGui::Separator(); ImGui::PopID(); } } // namespace void draw_debug_overlay(const InputSource& input) { ImGui::SetNextWindowPos(ImVec2(24, 24), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(420, 0), ImGuiCond_FirstUseEver); ImGui::Begin("CoopAllTheThings - Phase 0 spike"); ImGui::Text("Input backend: %s", input.name()); ImGui::Text("%.1f FPS (%.2f ms)", ImGui::GetIO().Framerate, 1000.0f / ImGui::GetIO().Framerate); ImGui::TextDisabled("This window is what Remote Play Together captures."); ImGui::TextDisabled("Press Esc to quit."); ImGui::Separator(); const auto& pads = input.pads(); for (int i = 0; i < static_cast(pads.size()); ++i) { draw_pad(i, pads[i]); } ImGui::End(); } } // namespace coop