mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-07-06 03:44:30 -04:00
work on controller config
This commit is contained in:
@@ -4,8 +4,10 @@
|
||||
|
||||
#include "ImGuiConsole.hpp"
|
||||
#include "ImGuiMenuGame.hpp"
|
||||
#include <imgui_internal.h>
|
||||
|
||||
#include "JSystem/JUtility/JUTGamePad.h"
|
||||
#include "m_Do/m_Do_controller_pad.h"
|
||||
#include "m_Do/m_Do_audio.h"
|
||||
|
||||
namespace dusk {
|
||||
@@ -65,23 +67,363 @@ namespace dusk {
|
||||
}
|
||||
}
|
||||
|
||||
// from https://github.com/ocornut/imgui/issues/1496#issuecomment-569892444
|
||||
void ImGuiBeginGroupPanel(const char* name, const ImVec2& size) {
|
||||
ImGui::BeginGroup();
|
||||
|
||||
auto cursorPos = ImGui::GetCursorScreenPos();
|
||||
auto itemSpacing = ImGui::GetStyle().ItemSpacing;
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
|
||||
|
||||
auto frameHeight = ImGui::GetFrameHeight();
|
||||
ImGui::BeginGroup();
|
||||
|
||||
ImVec2 effectiveSize = size;
|
||||
if (size.x < 0.0f)
|
||||
effectiveSize.x = ImGui::GetContentRegionAvail().x;
|
||||
else
|
||||
effectiveSize.x = size.x;
|
||||
ImGui::Dummy(ImVec2(effectiveSize.x, 0.0f));
|
||||
|
||||
ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f));
|
||||
ImGui::SameLine(0.0f, 0.0f);
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f));
|
||||
ImGui::SameLine(0.0f, 0.0f);
|
||||
ImGui::TextUnformatted(name);
|
||||
ImGui::SameLine(0.0f, 0.0f);
|
||||
ImGui::Dummy(ImVec2(0.0, frameHeight + itemSpacing.y));
|
||||
ImGui::BeginGroup();
|
||||
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
ImGui::GetCurrentWindow()->ContentRegionRect.Max.x -= frameHeight * 0.5f;
|
||||
ImGui::GetCurrentWindow()->WorkRect.Max.x -= frameHeight * 0.5f;
|
||||
ImGui::GetCurrentWindow()->Size.x -= frameHeight;
|
||||
|
||||
ImGui::PushItemWidth(effectiveSize.x - frameHeight);
|
||||
}
|
||||
|
||||
// from https://github.com/ocornut/imgui/issues/1496#issuecomment-569892444
|
||||
void ImGuiEndGroupPanel() {
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
auto itemSpacing = ImGui::GetStyle().ItemSpacing;
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
|
||||
|
||||
auto frameHeight = ImGui::GetFrameHeight();
|
||||
|
||||
// workaround for incorrect capture of columns/table width by placing
|
||||
// zero-sized dummy element in the same group, this ensure
|
||||
// max X cursor position is updated correctly
|
||||
ImGui::SameLine(0.0f, 0.0f);
|
||||
ImGui::Dummy(ImVec2(0.0f, 0.0f));
|
||||
|
||||
ImGui::EndGroup();
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::SameLine(0.0f, 0.0f);
|
||||
ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f));
|
||||
ImGui::Dummy(ImVec2(0.0, frameHeight - frameHeight * 0.5f - itemSpacing.y));
|
||||
|
||||
ImGui::EndGroup();
|
||||
|
||||
auto itemMin = ImGui::GetItemRectMin();
|
||||
auto itemMax = ImGui::GetItemRectMax();
|
||||
|
||||
ImVec2 halfFrame = ImVec2((frameHeight * 0.25f) * 0.5f, frameHeight * 0.5f);
|
||||
ImGui::GetWindowDrawList()->AddRect(
|
||||
ImVec2(itemMin.x + halfFrame.x, itemMin.y + halfFrame.y),
|
||||
ImVec2(itemMax.x - halfFrame.x, itemMax.y),
|
||||
ImColor(ImGui::GetStyleColorVec4(ImGuiCol_Border)),
|
||||
halfFrame.x);
|
||||
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
ImGui::GetCurrentWindow()->ContentRegionRect.Max.x += frameHeight * 0.5f;
|
||||
ImGui::GetCurrentWindow()->WorkRect.Max.x += frameHeight * 0.5f;
|
||||
ImGui::GetCurrentWindow()->Size.x += frameHeight;
|
||||
|
||||
ImGui::Dummy(ImVec2(0.0f, 0.0f));
|
||||
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
|
||||
static void drawVirtualStick(const char* id, const ImVec2& stick) {
|
||||
ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPos().x + 5, ImGui::GetCursorPos().y));
|
||||
|
||||
ImGui::BeginChild(id, ImVec2(80, 80));
|
||||
ImDrawList* dl = ImGui::GetWindowDrawList();
|
||||
ImVec2 p = ImGui::GetCursorScreenPos();
|
||||
|
||||
float radius = ImGui::GetCurrentContext()->CurrentDpiScale * 30.0f;
|
||||
ImVec2 pos = ImVec2(p.x + radius, p.y + radius);
|
||||
|
||||
constexpr ImU32 stickGray = IM_COL32(150, 150, 150, 255);
|
||||
constexpr ImU32 white = IM_COL32(255, 255, 255, 255);
|
||||
constexpr ImU32 red = IM_COL32(230, 0, 0, 255);
|
||||
|
||||
dl->AddCircleFilled(pos, radius, stickGray, 8);
|
||||
dl->AddCircleFilled(ImVec2(pos.x + stick.x * (radius), pos.y + -stick.y * (radius)), 3, red);
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
void ImGuiMenuGame::windowControllerConfig() {
|
||||
if (!m_showControllerConfig) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if pending for an input mapping, check to set new input
|
||||
if (m_controllerConfig.m_pendingMapping != nullptr) {
|
||||
s32 nativeButton = PADGetNativeButtonPressed(m_controllerConfig.m_pendingPort);
|
||||
if (nativeButton != -1) {
|
||||
m_controllerConfig.m_pendingMapping->nativeButton = nativeButton;
|
||||
m_controllerConfig.m_pendingMapping = nullptr;
|
||||
m_controllerConfig.m_pendingPort = -1;
|
||||
PADBlockInput(false);
|
||||
}
|
||||
}
|
||||
|
||||
ImGuiWindowFlags windowFlags =
|
||||
ImGuiWindowFlags_NoResize |
|
||||
ImGuiWindowFlags_AlwaysAutoResize;
|
||||
|
||||
ImGui::SetNextWindowBgAlpha(0.65f);
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(500, 200), ImVec2(1000, 200));
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(850, 400), ImVec2(850, 400));
|
||||
|
||||
if (!ImGui::Begin("Controller Config", nullptr, windowFlags)) {
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
// port tabs
|
||||
ImGui::BeginTabBar("##ControllerTabs");
|
||||
for (int i = PAD_1; i <= PAD_4; i++) {
|
||||
if (ImGui::BeginTabItem(fmt::format("Port {}", i + 1).c_str())) {
|
||||
m_controllerConfig.m_selectedPort = i;
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
}
|
||||
ImGui::EndTabBar();
|
||||
|
||||
// if tab is changed while waiting for input, cancel pending
|
||||
if (m_controllerConfig.m_pendingMapping != nullptr &&
|
||||
m_controllerConfig.m_pendingPort != m_controllerConfig.m_selectedPort)
|
||||
{
|
||||
m_controllerConfig.m_pendingMapping = nullptr;
|
||||
m_controllerConfig.m_pendingPort = -1;
|
||||
PADBlockInput(false);
|
||||
}
|
||||
|
||||
// get a list of all available controller's names
|
||||
std::vector<std::string> controllerList;
|
||||
controllerList.push_back("None");
|
||||
for (int i = 0; i < PADCount(); i++) {
|
||||
// attach index to name for unique name
|
||||
controllerList.push_back(fmt::format("{}-{}", PADGetNameForControllerIndex(i), i));
|
||||
}
|
||||
|
||||
// get current controller name
|
||||
const char* tmpName = PADGetName(m_controllerConfig.m_selectedPort);
|
||||
std::string currentName = "None";
|
||||
if (tmpName != nullptr) {
|
||||
currentName = fmt::format("{}-{}", tmpName, PADGetIndexForPort(m_controllerConfig.m_selectedPort));
|
||||
}
|
||||
|
||||
// controller selection combo box
|
||||
bool changedController = false;
|
||||
int changedControllerIndex = 0;
|
||||
if (ImGui::BeginCombo("##ControllerDeviceList", currentName.c_str())) {
|
||||
for (int i = 0; const auto& name : controllerList) {
|
||||
if (ImGui::Selectable(name.c_str(), currentName == name)) {
|
||||
changedControllerIndex = i;
|
||||
changedController = true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
// handle controller change
|
||||
if (changedController) {
|
||||
if (changedControllerIndex > 0) {
|
||||
PADSetPortForIndex(changedControllerIndex - 1, m_controllerConfig.m_selectedPort);
|
||||
}
|
||||
else if (changedControllerIndex == 0) {
|
||||
// if "None" selected
|
||||
PADClearPort(m_controllerConfig.m_selectedPort);
|
||||
}
|
||||
}
|
||||
|
||||
// save mappings button
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Save")) {
|
||||
PADSerializeMappings();
|
||||
}
|
||||
|
||||
// restore defaults button
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Default")) {
|
||||
PADRestoreDefaultMapping(m_controllerConfig.m_selectedPort);
|
||||
}
|
||||
|
||||
// buttons panel
|
||||
constexpr float buttonSize = 40;
|
||||
|
||||
ImGuiBeginGroupPanel("Buttons", ImVec2(150, 20));
|
||||
|
||||
u32 buttonCount;
|
||||
PADButtonMapping* mappingList = PADGetButtonMappings(m_controllerConfig.m_selectedPort, &buttonCount);
|
||||
if (mappingList != nullptr) {
|
||||
for (int i = 0; i < buttonCount; i++) {
|
||||
const char* btnName = PADGetButtonName(mappingList[i].padButton);
|
||||
ImVec2 len = ImGui::CalcTextSize(btnName);
|
||||
ImVec2 pos = ImGui::GetCursorPos();
|
||||
|
||||
ImGui::SetCursorPosY(pos.y + len.y / 4);
|
||||
ImGui::SetCursorPosX(pos.x + abs(len.x - buttonSize));
|
||||
ImGui::Text("%s", btnName);
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::SetCursorPosY(pos.y);
|
||||
|
||||
bool pressed = ImGui::Button(m_controllerConfig.m_isReading && m_controllerConfig.m_pendingMapping == &mappingList[i]
|
||||
? fmt::format("Press a Key...##{}", btnName).c_str()
|
||||
: fmt::format("{0}##-{1}", PADGetNativeButtonName(mappingList[i].nativeButton), i).c_str(),
|
||||
ImVec2(100.0f, 20.0f));
|
||||
|
||||
if (pressed) {
|
||||
m_controllerConfig.m_isReading = true;
|
||||
m_controllerConfig.m_pendingPort = m_controllerConfig.m_selectedPort;
|
||||
m_controllerConfig.m_pendingMapping = &mappingList[i];
|
||||
PADBlockInput(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGuiEndGroupPanel();
|
||||
ImGui::SameLine();
|
||||
|
||||
int port = m_controllerConfig.m_selectedPort;
|
||||
|
||||
const char* stickDirections[] = {
|
||||
"Up",
|
||||
"Down",
|
||||
"Left",
|
||||
"Right",
|
||||
};
|
||||
|
||||
// main stick panel
|
||||
ImGuiBeginGroupPanel("Control Stick", ImVec2(150, 20));
|
||||
|
||||
drawVirtualStick("##mainStick", ImVec2{ mDoCPd_c::getStickX(port), mDoCPd_c::getStickY(port) });
|
||||
|
||||
{
|
||||
for (int i = 0; i < 4; i++) {
|
||||
const char* label = stickDirections[i];
|
||||
ImVec2 len = ImGui::CalcTextSize(label);
|
||||
ImVec2 pos = ImGui::GetCursorPos();
|
||||
|
||||
ImGui::SetCursorPosY(pos.y + len.y / 4);
|
||||
ImGui::SetCursorPosX(pos.x + abs(len.x - buttonSize));
|
||||
ImGui::Text("%s", label);
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::SetCursorPosY(pos.y);
|
||||
|
||||
bool pressed = ImGui::Button(fmt::format("Temp##{}", label).c_str(), ImVec2(100.0f, 20.0f));
|
||||
}
|
||||
}
|
||||
|
||||
PADDeadZones* deadZones = PADGetDeadZones(port);
|
||||
|
||||
if (deadZones != nullptr) {
|
||||
ImGui::Text("Dead Zone");
|
||||
{
|
||||
float tmp = static_cast<float>(deadZones->stickDeadZone * 100.f) / 32767.f;
|
||||
if (ImGui::DragFloat("##mainDeadZone", &tmp, 0.5f, 0.f, 100.f, "%.3f%%")) {
|
||||
deadZones->stickDeadZone = static_cast<u16>((tmp / 100.f) * 32767);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGuiEndGroupPanel();
|
||||
ImGui::SameLine();
|
||||
|
||||
// sub stick panel
|
||||
ImGuiBeginGroupPanel("C Stick", ImVec2(150, 20));
|
||||
|
||||
drawVirtualStick("##subStick", ImVec2{ mDoCPd_c::getSubStickX(port), mDoCPd_c::getSubStickY(port) });
|
||||
|
||||
{
|
||||
for (int i = 0; i < 4; i++) {
|
||||
const char* label = stickDirections[i];
|
||||
ImVec2 len = ImGui::CalcTextSize(label);
|
||||
ImVec2 pos = ImGui::GetCursorPos();
|
||||
|
||||
ImGui::SetCursorPosY(pos.y + len.y / 4);
|
||||
ImGui::SetCursorPosX(pos.x + abs(len.x - buttonSize));
|
||||
ImGui::Text("%s", label);
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::SetCursorPosY(pos.y);
|
||||
|
||||
bool pressed = ImGui::Button(fmt::format("Temp##sub{}", label).c_str(), ImVec2(100.0f, 20.0f));
|
||||
}
|
||||
}
|
||||
|
||||
if (deadZones != nullptr) {
|
||||
ImGui::Text("Dead Zone");
|
||||
{
|
||||
float tmp = static_cast<float>(deadZones->substickDeadZone * 100.f) / 32767.f;
|
||||
if (ImGui::DragFloat("##subDeadZone", &tmp, 0.5f, 0.f, 100.f, "%.3f%%")) {
|
||||
deadZones->substickDeadZone = static_cast<u16>((tmp / 100.f) * 32767);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGuiEndGroupPanel();
|
||||
ImGui::SameLine();
|
||||
|
||||
// Triggers Panel
|
||||
ImGuiBeginGroupPanel("Triggers", ImVec2(150, 20));
|
||||
|
||||
if (deadZones != nullptr) {
|
||||
ImGui::Text("L Threshold");
|
||||
{
|
||||
float tmp = static_cast<float>(deadZones->leftTriggerActivationZone * 100.f) / 32767.f;
|
||||
if (ImGui::DragFloat("##LThreshold", &tmp, 0.5f, 0.f, 100.f, "%.3f%%")) {
|
||||
deadZones->leftTriggerActivationZone = static_cast<u16>((tmp / 100.f) * 32767);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (deadZones != nullptr) {
|
||||
ImGui::Text("R Threshold");
|
||||
{
|
||||
float tmp = static_cast<float>(deadZones->rightTriggerActivationZone * 100.f) / 32767.f;
|
||||
if (ImGui::DragFloat("##RThreshold", &tmp, 0.5f, 0.f, 100.f, "%.3f%%")) {
|
||||
deadZones->rightTriggerActivationZone = static_cast<u16>((tmp / 100.f) * 32767);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGuiEndGroupPanel();
|
||||
ImGui::SameLine();
|
||||
|
||||
// Options panel
|
||||
ImGuiBeginGroupPanel("Options", ImVec2(150, 20));
|
||||
|
||||
if (deadZones != nullptr) {
|
||||
ImGui::Checkbox("Enable Dead Zones", &deadZones->useDeadzones);
|
||||
ImGui::Checkbox("Emulate Triggers", &deadZones->emulateTriggers);
|
||||
}
|
||||
|
||||
ImGuiEndGroupPanel();
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
#define DUSK_IMGUI_MENUGAME_HPP
|
||||
|
||||
#include <aurora/aurora.h>
|
||||
#include <pad.h>
|
||||
#include <string>
|
||||
|
||||
#include "imgui.h"
|
||||
@@ -24,6 +25,13 @@ namespace dusk {
|
||||
float m_fanfareVolume = 1.0f;
|
||||
} m_audioSettings;
|
||||
|
||||
struct {
|
||||
int m_selectedPort = 0;
|
||||
bool m_isReading = false;
|
||||
PADButtonMapping* m_pendingMapping = nullptr;
|
||||
int m_pendingPort = -1;
|
||||
} m_controllerConfig;
|
||||
|
||||
bool m_showControllerConfig = false;
|
||||
|
||||
bool m_showInputViewer = false;
|
||||
|
||||
@@ -5,20 +5,33 @@
|
||||
#include "ImGuiConsole.hpp"
|
||||
#include "ImGuiMenuTools.hpp"
|
||||
|
||||
#include "m_Do/m_Do_main.h"
|
||||
|
||||
namespace dusk {
|
||||
ImGuiMenuTools::ImGuiMenuTools() {}
|
||||
|
||||
void ImGuiMenuTools::draw() {
|
||||
bool isToggleDevelopmentMode = false;
|
||||
|
||||
if (ImGui::BeginMenu("Tools")) {
|
||||
if (ImGui::Checkbox("Development Mode", &m_isDevelopmentMode)) {
|
||||
isToggleDevelopmentMode = true;
|
||||
}
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::MenuItem("Process Management", "F2", &m_showProcessManagement);
|
||||
ImGui::MenuItem("Debug Overlay", "F3", &m_showDebugOverlay);
|
||||
ImGui::MenuItem("Heaps", "F4", &m_showHeapOverlay);
|
||||
ImGui::MenuItem("Heap Viewer", "F4", &m_showHeapOverlay);
|
||||
ImGui::MenuItem("Stub Log", "F5", &m_showStubLog);
|
||||
ImGui::MenuItem("Camera", "F6", &m_showCameraOverlay);
|
||||
ImGui::MenuItem("Debug Camera", "F6", &m_showCameraOverlay);
|
||||
ImGui::MenuItem("Map Loader", nullptr, &m_showMapLoader);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (isToggleDevelopmentMode) {
|
||||
mDoMain::developmentMode = m_isDevelopmentMode ? 1 : -1;
|
||||
}
|
||||
|
||||
ShowDebugOverlay();
|
||||
ShowCameraOverlay();
|
||||
ShowProcessManager();
|
||||
|
||||
@@ -44,6 +44,8 @@ namespace dusk {
|
||||
int layer = -1;
|
||||
bool showInternalNames = false;
|
||||
} m_mapLoaderInfo;
|
||||
|
||||
bool m_isDevelopmentMode = false;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user