mirror of
https://github.com/izzy2lost/2ship2harkinian-Android.git
synced 2026-06-19 01:20:08 -07:00
* Start the framework. * Start header bar. * Header buttons now toggle. Sections show accordingly. Basic audio section done. Needs subdividing for sane widget widths. * Add fonts and multiple sizes. Add graphics settings to menu. * Finalized fonts, more sizes. * Modularized the menu structure. Has an errant EndChild somewhere. * Finished first step modularization. Parameterized menu height. * Some adaptive menu size. * Moved all enhancements over and organized. Tried to add button option for sidebar entries. * Finished Enhancements Menu. Sidebar window button still broken (can't reference window variables properly, not drawing in the right place). * Developer Tools header started. Menu now pops out with a checkbox in Developer Tools. Menu sizing works for smaller game sizes. Popout docking disabled. Port bool added for disallowing popout regardless of cvar. * Better auto-sizing. Columns collapse to 1 below 800 window width, and scroll. * Move inside of HudEditorWindow::DrawElement to DrawContents, and call DrawContents from DrawElement. * Menu resizability complete. Menu popout complete. Menu popout position/size is retained when popped in. Apply HUD editor changes, draw contents in menu if window is closed. All child sizes properly calculated. SidebarEntry drawing separated into its own custom element. * Split header entries into separate widget. Header now dynamically sized and shows scrollbar when necessary. * Modify EventLog to be drawable with the DrawContents setup. Prevent menu from covering other windows (always in back). * Add reset, close menu, and quit buttons to the header. * Fix reset and quit button placement. * Swap Actor Viewer, Collision Viewer, Save Editor to DrawContents concept. Change reset icon to FA_ICON_UNDO (single arrow) and quit icon to FA_ICON_POWER_OFF. Add button to close menu button tooltip, add parentheses to button for reset tooltip. * Custom InputEditorWindow to work with menu. Fix LUS references in Menu.cpp for Window backend changes. Implement gamepad navigation and forced cursor visibility checkboxes. Toggle cursor visibility according to menu status and forced visibility CVar. * clang-format * Swap std for fmt (runner build error). Ensure cursor visibility is restored if started in full screen with the menu open. * Oops, still had #include <format> * Swap to LUS GetMenu() functionality. Add option to hide "F1 to open enhancements menu" text at startup if menus aren't open. * Remove last vestiges of pre-LUS-menu functionality. * cleanup * Adapt to GuiElement, GuiWindow changes on the menu support PR. * LUS PR bump. Adapt to cursor visibility changes in LUS. Adapt to menu toggle changes in LUS. Fix input editor not hiding in menu when popped out. * Add new enhancements and cheats to Modern Menu from rebase. * clang * Apply Graphics Menu Lag Fix to Menu structure. * Remove unnecessary window children to simplify controller navigation. * clang * Add `UpdateWindowBackendObjects()` call to backend combobox. * Rebase to latest develop. Remove redundant window backend stuff that exists now in BenMenuBar. * Search Enhancement (#2) * 90% complete, Commit for review. * Updated remaining Menu Entries, Reverted Backends and other Window Buttons for now. Motion Blur copied to Search Menu. * Did I mention I dislike this clang thing? lol * Updating MotionBlur options and reverting soem things. * Integrates .disabled and .disabledTooltip to the constructors. Allows for multiple qualifications to be checked against for disabling widgets and for setting the tooltip accordingly. * Updated Disabled Reasoning * Better Disabled State registration system * Clean up from testing * Expand WidgetOptions to be able to handle string and float values. bool and uint32_t are handled through int32_t. Numerous renames. Added several data structures to allow for dynamic updating of CVars for DisableOptions, as well as dynamic evaluation of status with enumerated conditions (less than, greater than, equal to). Added menuThemeIndex variable to store state of menu theme selection instead of having all the individual calls to CVarGetInteger for it. Updated once per frame. * Changed color vector to map with enum as key and UIWidget::Colors as the value. More renames. Moved float slider values into case block. * Add Color_RGB8 and Color_RGBA8 to CVarVariant in preparation for adding color widgets to menu item system. Not happy it required comparison operator overrides, but it is what it is. * Changed disable conditions to lambdas. * Convert Stats and Collision Viewer to menu item system. Swap out DisableOption vector for activeDisables and a lambda function for evaluating disabled and hidden. Set the precedent to still use the DisableInfo system. * Add DisableOption for both camera settings being off. Put Debug Camera in Free Look column, disable common widgets for both cameras, hide widgets specific to either if off. * Moved more widgets to MenuItem system. Some need proper initialization routines because of Ship::Context references. * Convert menu items to nested vector setup. Remove MenuItem enum. Add menu item location display to search results. * Partial removal of SidebarEntryIndex enum. * Finish removing SidebarEntryIndex. Rework drawing code to handle the change back to direct vector access. Add tooltips to search. * Fix Graphics enhancements section title. * Copy added menu items to modern menu system. * clang * Add some documentation for the menu system components. * Revert change to std::map * `size_t` because GCC has to be happy * Fixed HUD Editor Widescreen mode not displaying the sliders properly. Changed all windows to full-section-width display. * Revert changes to MotionBlur.cpp * Add non-CVar variants of checkbox, combobox, and the sliders. Fix motion blur functionality with new non-CVar widgets. * Add non-CVar variants of checkbox, combobox, and the sliders. Fix motion blur functionality with those non-CVar widgets. Add size and labelPosition to widgetOptions, implemented on button and checkbox/combobox/sliders. Change window popout buttons to inline size type. * Rename SearchMenu.h to SearchableMenuItems.h and move to BenGui folder. * Forgot to change the include XD * Change `modifierFunc` to `preFunc`, updated documentation for that and including `postFunc`. * Modify code to require variable for non-CVar widget initialization when necessary. Check for `valuePointer` being nullptr, and preventing widget drawing with a debug assert and error log entry. Remove all `has_variant` calls and wrap entire widget type switch in `SearchMenuGetItem` with a try/catch on `std::bad_variant_access` with another error log and debug assert. * More review changes. * Implement `isPercentage`, `format`, and `showButtons` for sliders. Pull values of those over from menubar. Add documentation on `widgetOptions` for those and others added for previous review changes. Move Fast Magic Arrow and Instant Fin Recall to Gameplay section. * Modify header and sidebar "buttons" to match theming of regular buttons. * Add precision clamping to SliderFloat value. At least 1.0 seems to be consistent at "100%". Change IR slider to be percentage. * Mention weirdness with SDL and pad menu button in controller nav tooltip. * Move Menu files to 2s2h/BenGui. * Add Warp Points to Developer Tools. Make "Press F1" prompt show only when a menu isn't registered. * clang * Make search input take focus when search menu is open. * Forgot include. * Global search (#3) * Restore Sidebar search entry, but lock it behind a checkbox in Settings. Dynamically adds or removes the sidebar entry, and header search is toggled inversely. * Make menu toggle its visibility when using the button in the menu to close. Couldn't handle Alt+F4 without a hook I didn't want to add. Remove unneeded commented code. --------- Co-authored-by: Caladius <Caladius@users.noreply.github.com> Co-authored-by: Garrett Cox <garrettjcox@gmail.com>
1672 lines
76 KiB
C++
1672 lines
76 KiB
C++
#include "BenInputEditorWindow.h"
|
|
#include "Context.h"
|
|
#include "Gui.h"
|
|
#include "utils/StringHelper.h"
|
|
#include "public/bridge/consolevariablebridge.h"
|
|
#include "controller/controldevice/controller/mapping/sdl/SDLAxisDirectionToButtonMapping.h"
|
|
|
|
#define SCALE_IMGUI_SIZE(value) ((value / 13.0f) * ImGui::GetFontSize())
|
|
|
|
BenInputEditorWindow::~BenInputEditorWindow() {
|
|
SPDLOG_TRACE("destruct input editor window");
|
|
}
|
|
|
|
void BenInputEditorWindow::InitElement() {
|
|
mGameInputBlockTimer = INT32_MAX;
|
|
mMappingInputBlockTimer = INT32_MAX;
|
|
mRumbleTimer = INT32_MAX;
|
|
mRumbleMappingToTest = nullptr;
|
|
mInputEditorPopupOpen = false;
|
|
|
|
mButtonsBitmasks = { BTN_A, BTN_B, BTN_START, BTN_L, BTN_R, BTN_Z, BTN_CUP, BTN_CDOWN, BTN_CLEFT, BTN_CRIGHT };
|
|
mDpadBitmasks = { BTN_DUP, BTN_DDOWN, BTN_DLEFT, BTN_DRIGHT };
|
|
|
|
mDeviceIndexVisiblity.clear();
|
|
mDeviceIndexVisiblity[Ship::ShipDeviceIndex::Keyboard] = true;
|
|
mDeviceIndexVisiblity[Ship::ShipDeviceIndex::Blue] = true;
|
|
for (auto index = 1; index < Ship::ShipDeviceIndex::Max; index++) {
|
|
mDeviceIndexVisiblity[static_cast<Ship::ShipDeviceIndex>(index)] = false;
|
|
}
|
|
}
|
|
|
|
#define INPUT_EDITOR_WINDOW_GAME_INPUT_BLOCK_ID 95237929
|
|
void BenInputEditorWindow::UpdateElement() {
|
|
if (mRumbleTimer != INT32_MAX) {
|
|
mRumbleTimer--;
|
|
if (mRumbleMappingToTest != nullptr) {
|
|
mRumbleMappingToTest->StartRumble();
|
|
}
|
|
if (mRumbleTimer <= 0) {
|
|
if (mRumbleMappingToTest != nullptr) {
|
|
mRumbleMappingToTest->StopRumble();
|
|
}
|
|
mRumbleTimer = INT32_MAX;
|
|
mRumbleMappingToTest = nullptr;
|
|
}
|
|
}
|
|
|
|
if (mInputEditorPopupOpen && ImGui::IsPopupOpen("", ImGuiPopupFlags_AnyPopupId)) {
|
|
Ship::Context::GetInstance()->GetControlDeck()->BlockGameInput(INPUT_EDITOR_WINDOW_GAME_INPUT_BLOCK_ID);
|
|
|
|
// continue to block input for a third of a second after getting the mapping
|
|
mGameInputBlockTimer = ImGui::GetIO().Framerate / 3;
|
|
|
|
if (mMappingInputBlockTimer != INT32_MAX) {
|
|
mMappingInputBlockTimer--;
|
|
if (mMappingInputBlockTimer <= 0) {
|
|
mMappingInputBlockTimer = INT32_MAX;
|
|
}
|
|
}
|
|
|
|
Ship::Context::GetInstance()->GetWindow()->GetGui()->BlockImGuiGamepadNavigation();
|
|
} else {
|
|
if (mGameInputBlockTimer != INT32_MAX) {
|
|
mGameInputBlockTimer--;
|
|
if (mGameInputBlockTimer <= 0) {
|
|
Ship::Context::GetInstance()->GetControlDeck()->UnblockGameInput(
|
|
INPUT_EDITOR_WINDOW_GAME_INPUT_BLOCK_ID);
|
|
mGameInputBlockTimer = INT32_MAX;
|
|
}
|
|
}
|
|
|
|
if (Ship::Context::GetInstance()->GetWindow()->GetGui()->ImGuiGamepadNavigationEnabled()) {
|
|
mMappingInputBlockTimer = ImGui::GetIO().Framerate / 3;
|
|
} else {
|
|
mMappingInputBlockTimer = INT32_MAX;
|
|
}
|
|
|
|
Ship::Context::GetInstance()->GetWindow()->GetGui()->UnblockImGuiGamepadNavigation();
|
|
}
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawAnalogPreview(const char* label, ImVec2 stick, float deadzone, bool gyro) {
|
|
ImGui::BeginChild(label, ImVec2(gyro ? SCALE_IMGUI_SIZE(78) : SCALE_IMGUI_SIZE(96), SCALE_IMGUI_SIZE(85)), false);
|
|
ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPos().x + gyro ? SCALE_IMGUI_SIZE(10) : SCALE_IMGUI_SIZE(18),
|
|
ImGui::GetCursorPos().y + gyro ? SCALE_IMGUI_SIZE(10) : 0));
|
|
ImDrawList* drawList = ImGui::GetWindowDrawList();
|
|
|
|
const ImVec2 cursorScreenPosition = ImGui::GetCursorScreenPos();
|
|
|
|
// Draw the border box
|
|
float borderSquareLeft = cursorScreenPosition.x + SCALE_IMGUI_SIZE(2.0f);
|
|
float borderSquareTop = cursorScreenPosition.y + SCALE_IMGUI_SIZE(2.0f);
|
|
float borderSquareSize = SCALE_IMGUI_SIZE(65.0f);
|
|
drawList->AddRect(ImVec2(borderSquareLeft, borderSquareTop),
|
|
ImVec2(borderSquareLeft + borderSquareSize, borderSquareTop + borderSquareSize),
|
|
ImColor(100, 100, 100, 255), 0.0f, 0, 1.5f);
|
|
|
|
// Draw the gate background
|
|
float cardinalRadius = SCALE_IMGUI_SIZE(22.5f);
|
|
float diagonalRadius = SCALE_IMGUI_SIZE(22.5f * (69.0f / 85.0f));
|
|
|
|
ImVec2 joystickCenterpoint = ImVec2(cursorScreenPosition.x + cardinalRadius + SCALE_IMGUI_SIZE(12),
|
|
cursorScreenPosition.y + cardinalRadius + SCALE_IMGUI_SIZE(11));
|
|
drawList->AddQuadFilled(joystickCenterpoint,
|
|
ImVec2(joystickCenterpoint.x - diagonalRadius, joystickCenterpoint.y + diagonalRadius),
|
|
ImVec2(joystickCenterpoint.x, joystickCenterpoint.y + cardinalRadius),
|
|
ImVec2(joystickCenterpoint.x + diagonalRadius, joystickCenterpoint.y + diagonalRadius),
|
|
ImColor(130, 130, 130, 255));
|
|
drawList->AddQuadFilled(joystickCenterpoint,
|
|
ImVec2(joystickCenterpoint.x + diagonalRadius, joystickCenterpoint.y + diagonalRadius),
|
|
ImVec2(joystickCenterpoint.x + cardinalRadius, joystickCenterpoint.y),
|
|
ImVec2(joystickCenterpoint.x + diagonalRadius, joystickCenterpoint.y - diagonalRadius),
|
|
ImColor(130, 130, 130, 255));
|
|
drawList->AddQuadFilled(joystickCenterpoint,
|
|
ImVec2(joystickCenterpoint.x + diagonalRadius, joystickCenterpoint.y - diagonalRadius),
|
|
ImVec2(joystickCenterpoint.x, joystickCenterpoint.y - cardinalRadius),
|
|
ImVec2(joystickCenterpoint.x - diagonalRadius, joystickCenterpoint.y - diagonalRadius),
|
|
ImColor(130, 130, 130, 255));
|
|
drawList->AddQuadFilled(joystickCenterpoint,
|
|
ImVec2(joystickCenterpoint.x - diagonalRadius, joystickCenterpoint.y - diagonalRadius),
|
|
ImVec2(joystickCenterpoint.x - cardinalRadius, joystickCenterpoint.y),
|
|
ImVec2(joystickCenterpoint.x - diagonalRadius, joystickCenterpoint.y + diagonalRadius),
|
|
ImColor(130, 130, 130, 255));
|
|
|
|
// Draw the joystick position indicator
|
|
ImVec2 joystickIndicatorDistanceFromCenter = ImVec2(0, 0);
|
|
if ((stick.x * stick.x + stick.y * stick.y) > (deadzone * deadzone)) {
|
|
joystickIndicatorDistanceFromCenter =
|
|
ImVec2((stick.x * (cardinalRadius / 85.0f)), -(stick.y * (cardinalRadius / 85.0f)));
|
|
}
|
|
float indicatorRadius = SCALE_IMGUI_SIZE(5.0f);
|
|
drawList->AddCircleFilled(ImVec2(joystickCenterpoint.x + joystickIndicatorDistanceFromCenter.x,
|
|
joystickCenterpoint.y + joystickIndicatorDistanceFromCenter.y),
|
|
indicatorRadius, ImColor(34, 51, 76, 255), 7);
|
|
|
|
if (!gyro) {
|
|
ImGui::SetCursorPos(
|
|
ImVec2(ImGui::GetCursorPos().x - SCALE_IMGUI_SIZE(8), ImGui::GetCursorPos().y + SCALE_IMGUI_SIZE(72)));
|
|
ImGui::Text("X:%3d, Y:%3d", static_cast<int32_t>(stick.x), static_cast<int32_t>(stick.y));
|
|
}
|
|
ImGui::EndChild();
|
|
}
|
|
|
|
#define CHIP_COLOR_N64_GREY ImVec4(0.4f, 0.4f, 0.4f, 1.0f)
|
|
#define CHIP_COLOR_N64_BLUE ImVec4(0.176f, 0.176f, 0.5f, 1.0f)
|
|
#define CHIP_COLOR_N64_GREEN ImVec4(0.0f, 0.294f, 0.0f, 1.0f)
|
|
#define CHIP_COLOR_N64_YELLOW ImVec4(0.5f, 0.314f, 0.0f, 1.0f)
|
|
#define CHIP_COLOR_N64_RED ImVec4(0.392f, 0.0f, 0.0f, 1.0f)
|
|
|
|
#define BUTTON_COLOR_KEYBOARD_BEIGE ImVec4(0.651f, 0.482f, 0.357f, 0.5f)
|
|
#define BUTTON_COLOR_KEYBOARD_BEIGE_HOVERED ImVec4(0.651f, 0.482f, 0.357f, 1.0f)
|
|
|
|
#define BUTTON_COLOR_GAMEPAD_BLUE ImVec4(0.0f, 0.255f, 0.976f, 0.5f)
|
|
#define BUTTON_COLOR_GAMEPAD_BLUE_HOVERED ImVec4(0.0f, 0.255f, 0.976f, 1.0f)
|
|
|
|
#define BUTTON_COLOR_GAMEPAD_RED ImVec4(0.976f, 0.0f, 0.094f, 0.5f)
|
|
#define BUTTON_COLOR_GAMEPAD_RED_HOVERED ImVec4(0.976f, 0.0f, 0.094f, 1.0f)
|
|
|
|
#define BUTTON_COLOR_GAMEPAD_ORANGE ImVec4(0.976f, 0.376f, 0.0f, 0.5f)
|
|
#define BUTTON_COLOR_GAMEPAD_ORANGE_HOVERED ImVec4(0.976f, 0.376f, 0.0f, 1.0f)
|
|
|
|
#define BUTTON_COLOR_GAMEPAD_GREEN ImVec4(0.0f, 0.5f, 0.0f, 0.5f)
|
|
#define BUTTON_COLOR_GAMEPAD_GREEN_HOVERED ImVec4(0.0f, 0.5f, 0.0f, 1.0f)
|
|
|
|
#define BUTTON_COLOR_GAMEPAD_PURPLE ImVec4(0.431f, 0.369f, 0.706f, 0.5f)
|
|
#define BUTTON_COLOR_GAMEPAD_PURPLE_HOVERED ImVec4(0.431f, 0.369f, 0.706f, 1.0f)
|
|
|
|
void BenInputEditorWindow::GetButtonColorsForShipDeviceIndex(Ship::ShipDeviceIndex lusIndex, ImVec4& buttonColor,
|
|
ImVec4& buttonHoveredColor) {
|
|
switch (lusIndex) {
|
|
case Ship::ShipDeviceIndex::Keyboard:
|
|
buttonColor = BUTTON_COLOR_KEYBOARD_BEIGE;
|
|
buttonHoveredColor = BUTTON_COLOR_KEYBOARD_BEIGE_HOVERED;
|
|
break;
|
|
case Ship::ShipDeviceIndex::Blue:
|
|
buttonColor = BUTTON_COLOR_GAMEPAD_BLUE;
|
|
buttonHoveredColor = BUTTON_COLOR_GAMEPAD_BLUE_HOVERED;
|
|
break;
|
|
case Ship::ShipDeviceIndex::Red:
|
|
buttonColor = BUTTON_COLOR_GAMEPAD_RED;
|
|
buttonHoveredColor = BUTTON_COLOR_GAMEPAD_RED_HOVERED;
|
|
break;
|
|
case Ship::ShipDeviceIndex::Orange:
|
|
buttonColor = BUTTON_COLOR_GAMEPAD_ORANGE;
|
|
buttonHoveredColor = BUTTON_COLOR_GAMEPAD_ORANGE_HOVERED;
|
|
break;
|
|
case Ship::ShipDeviceIndex::Green:
|
|
buttonColor = BUTTON_COLOR_GAMEPAD_GREEN;
|
|
buttonHoveredColor = BUTTON_COLOR_GAMEPAD_GREEN_HOVERED;
|
|
break;
|
|
default:
|
|
buttonColor = BUTTON_COLOR_GAMEPAD_PURPLE;
|
|
buttonHoveredColor = BUTTON_COLOR_GAMEPAD_PURPLE_HOVERED;
|
|
}
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawInputChip(const char* buttonName, ImVec4 color = CHIP_COLOR_N64_GREY) {
|
|
ImGui::BeginDisabled();
|
|
ImGui::PushStyleColor(ImGuiCol_Button, color);
|
|
ImGui::Button(buttonName, ImVec2(SCALE_IMGUI_SIZE(50.0f), 0));
|
|
ImGui::PopStyleColor();
|
|
ImGui::EndDisabled();
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawButtonLineAddMappingButton(uint8_t port, CONTROLLERBUTTONS_T bitmask) {
|
|
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(1.0f, 0.5f));
|
|
auto popupId = StringHelper::Sprintf("addButtonMappingPopup##%d-%d", port, bitmask);
|
|
if (ImGui::Button(StringHelper::Sprintf("%s###addButtonMappingButton%d-%d", ICON_FA_PLUS, port, bitmask).c_str(),
|
|
ImVec2(SCALE_IMGUI_SIZE(20.0f), 0.0f))) {
|
|
ImGui::OpenPopup(popupId.c_str());
|
|
};
|
|
ImGui::PopStyleVar();
|
|
|
|
if (ImGui::BeginPopup(popupId.c_str())) {
|
|
mInputEditorPopupOpen = true;
|
|
ImGui::Text("Press any button,\nmove any axis,\nor press any key\nto add mapping");
|
|
if (ImGui::Button("Cancel")) {
|
|
mInputEditorPopupOpen = false;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
// todo: figure out why optional params (using id = "" in the definition) wasn't working
|
|
if (mMappingInputBlockTimer == INT32_MAX && Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetControllerByPort(port)
|
|
->GetButton(bitmask)
|
|
->AddOrEditButtonMappingFromRawPress(bitmask, "")) {
|
|
mInputEditorPopupOpen = false;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::EndPopup();
|
|
}
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawButtonLineEditMappingButton(uint8_t port, CONTROLLERBUTTONS_T bitmask, std::string id) {
|
|
auto mapping = Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetControllerByPort(port)
|
|
->GetButton(bitmask)
|
|
->GetButtonMappingById(id);
|
|
if (mapping == nullptr) {
|
|
return;
|
|
}
|
|
if (!mDeviceIndexVisiblity[mapping->GetShipDeviceIndex()]) {
|
|
return;
|
|
}
|
|
|
|
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.5f));
|
|
std::string icon = "";
|
|
switch (mapping->GetMappingType()) {
|
|
case MAPPING_TYPE_GAMEPAD:
|
|
icon = ICON_FA_GAMEPAD;
|
|
break;
|
|
case MAPPING_TYPE_KEYBOARD:
|
|
icon = ICON_FA_KEYBOARD_O;
|
|
break;
|
|
case MAPPING_TYPE_UNKNOWN:
|
|
icon = ICON_FA_BUG;
|
|
break;
|
|
}
|
|
auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
|
|
auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
|
|
auto physicalInputDisplayName =
|
|
StringHelper::Sprintf("%s %s", icon.c_str(), mapping->GetPhysicalInputName().c_str());
|
|
GetButtonColorsForShipDeviceIndex(mapping->GetShipDeviceIndex(), buttonColor, buttonHoveredColor);
|
|
ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
|
|
auto popupId = StringHelper::Sprintf("editButtonMappingPopup##%s", id.c_str());
|
|
if (ImGui::Button(
|
|
StringHelper::Sprintf("%s###editButtonMappingButton%s", physicalInputDisplayName.c_str(), id.c_str())
|
|
.c_str(),
|
|
ImVec2(ImGui::CalcTextSize(physicalInputDisplayName.c_str()).x + SCALE_IMGUI_SIZE(12.0f), 0.0f))) {
|
|
ImGui::OpenPopup(popupId.c_str());
|
|
}
|
|
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal | ImGuiHoveredFlags_NoSharedDelay)) {
|
|
ImGui::SetTooltip(mapping->GetPhysicalDeviceName().c_str());
|
|
}
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopStyleColor();
|
|
|
|
if (ImGui::BeginPopup(popupId.c_str())) {
|
|
mInputEditorPopupOpen = true;
|
|
ImGui::Text("Press any button,\nmove any axis,\nor press any key\nto edit mapping");
|
|
if (ImGui::Button("Cancel")) {
|
|
mInputEditorPopupOpen = false;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
if (mMappingInputBlockTimer == INT32_MAX && Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetControllerByPort(port)
|
|
->GetButton(bitmask)
|
|
->AddOrEditButtonMappingFromRawPress(bitmask, id)) {
|
|
mInputEditorPopupOpen = false;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::EndPopup();
|
|
}
|
|
|
|
ImGui::PopStyleVar();
|
|
ImGui::SameLine(0, 0);
|
|
|
|
auto sdlAxisDirectionToButtonMapping = std::dynamic_pointer_cast<Ship::SDLAxisDirectionToButtonMapping>(mapping);
|
|
auto indexMapping = Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetDeviceIndexMappingManager()
|
|
->GetDeviceIndexMappingFromShipDeviceIndex(mapping->GetShipDeviceIndex());
|
|
auto sdlIndexMapping = std::dynamic_pointer_cast<Ship::ShipDeviceIndexToSDLDeviceIndexMapping>(indexMapping);
|
|
|
|
if (sdlIndexMapping != nullptr && sdlAxisDirectionToButtonMapping != nullptr) {
|
|
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.5f));
|
|
auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
|
|
auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
|
|
GetButtonColorsForShipDeviceIndex(mapping->GetShipDeviceIndex(), buttonColor, buttonHoveredColor);
|
|
ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
|
|
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(1.0f, 0.5f));
|
|
auto popupId = StringHelper::Sprintf("editAxisThresholdPopup##%s", id.c_str());
|
|
if (ImGui::Button(StringHelper::Sprintf("%s###editAxisThresholdButton%s", ICON_FA_COG, id.c_str()).c_str(),
|
|
ImVec2(ImGui::CalcTextSize(ICON_FA_COG).x + SCALE_IMGUI_SIZE(10.0f), 0.0f))) {
|
|
ImGui::OpenPopup(popupId.c_str());
|
|
}
|
|
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal | ImGuiHoveredFlags_NoSharedDelay)) {
|
|
ImGui::SetTooltip("Edit axis threshold");
|
|
}
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopStyleVar();
|
|
|
|
if (ImGui::BeginPopup(popupId.c_str())) {
|
|
mInputEditorPopupOpen = true;
|
|
ImGui::Text("Axis Threshold\n\nThe extent to which the joystick\nmust be moved or the trigger\npressed to "
|
|
"initiate the assigned\nbutton action.\n\n");
|
|
|
|
if (sdlAxisDirectionToButtonMapping->AxisIsStick()) {
|
|
ImGui::Text("Stick axis threshold:");
|
|
|
|
int32_t stickAxisThreshold = sdlIndexMapping->GetStickAxisThresholdPercentage();
|
|
if (stickAxisThreshold == 0) {
|
|
ImGui::BeginDisabled();
|
|
}
|
|
ImGui::PushButtonRepeat(true);
|
|
if (ImGui::Button(StringHelper::Sprintf("-##Stick Axis Threshold%s", id.c_str()).c_str())) {
|
|
sdlIndexMapping->SetStickAxisThresholdPercentage(stickAxisThreshold - 1);
|
|
sdlIndexMapping->SaveToConfig();
|
|
}
|
|
ImGui::PopButtonRepeat();
|
|
if (stickAxisThreshold == 0) {
|
|
ImGui::EndDisabled();
|
|
}
|
|
ImGui::SameLine(0.0f, 0.0f);
|
|
ImGui::SetNextItemWidth(SCALE_IMGUI_SIZE(160.0f));
|
|
if (ImGui::SliderInt(StringHelper::Sprintf("##Stick Axis Threshold%s", id.c_str()).c_str(),
|
|
&stickAxisThreshold, 0, 100, "%d%%", ImGuiSliderFlags_AlwaysClamp)) {
|
|
sdlIndexMapping->SetStickAxisThresholdPercentage(stickAxisThreshold);
|
|
sdlIndexMapping->SaveToConfig();
|
|
}
|
|
ImGui::SameLine(0.0f, 0.0f);
|
|
if (stickAxisThreshold == 100) {
|
|
ImGui::BeginDisabled();
|
|
}
|
|
ImGui::PushButtonRepeat(true);
|
|
if (ImGui::Button(StringHelper::Sprintf("+##Stick Axis Threshold%s", id.c_str()).c_str())) {
|
|
sdlIndexMapping->SetStickAxisThresholdPercentage(stickAxisThreshold + 1);
|
|
sdlIndexMapping->SaveToConfig();
|
|
}
|
|
ImGui::PopButtonRepeat();
|
|
if (stickAxisThreshold == 100) {
|
|
ImGui::EndDisabled();
|
|
}
|
|
}
|
|
|
|
if (sdlAxisDirectionToButtonMapping->AxisIsTrigger()) {
|
|
ImGui::Text("Trigger axis threshold:");
|
|
|
|
int32_t triggerAxisThreshold = sdlIndexMapping->GetTriggerAxisThresholdPercentage();
|
|
if (triggerAxisThreshold == 0) {
|
|
ImGui::BeginDisabled();
|
|
}
|
|
ImGui::PushButtonRepeat(true);
|
|
if (ImGui::Button(StringHelper::Sprintf("-##Trigger Axis Threshold%s", id.c_str()).c_str())) {
|
|
sdlIndexMapping->SetTriggerAxisThresholdPercentage(triggerAxisThreshold - 1);
|
|
sdlIndexMapping->SaveToConfig();
|
|
}
|
|
ImGui::PopButtonRepeat();
|
|
if (triggerAxisThreshold == 0) {
|
|
ImGui::EndDisabled();
|
|
}
|
|
ImGui::SameLine(0.0f, 0.0f);
|
|
ImGui::SetNextItemWidth(SCALE_IMGUI_SIZE(160.0f));
|
|
if (ImGui::SliderInt(StringHelper::Sprintf("##Trigger Axis Threshold%s", id.c_str()).c_str(),
|
|
&triggerAxisThreshold, 0, 100, "%d%%", ImGuiSliderFlags_AlwaysClamp)) {
|
|
sdlIndexMapping->SetTriggerAxisThresholdPercentage(triggerAxisThreshold);
|
|
sdlIndexMapping->SaveToConfig();
|
|
}
|
|
ImGui::SameLine(0.0f, 0.0f);
|
|
if (triggerAxisThreshold == 100) {
|
|
ImGui::BeginDisabled();
|
|
}
|
|
ImGui::PushButtonRepeat(true);
|
|
if (ImGui::Button(StringHelper::Sprintf("+##Trigger Axis Threshold%s", id.c_str()).c_str())) {
|
|
sdlIndexMapping->SetTriggerAxisThresholdPercentage(triggerAxisThreshold + 1);
|
|
sdlIndexMapping->SaveToConfig();
|
|
}
|
|
ImGui::PopButtonRepeat();
|
|
if (triggerAxisThreshold == 100) {
|
|
ImGui::EndDisabled();
|
|
}
|
|
}
|
|
|
|
if (ImGui::Button("Close")) {
|
|
mInputEditorPopupOpen = false;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
|
|
ImGui::EndPopup();
|
|
}
|
|
|
|
ImGui::PopStyleVar();
|
|
ImGui::SameLine(0, 0);
|
|
}
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
|
|
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(1.0f, 0.5f));
|
|
if (ImGui::Button(StringHelper::Sprintf("%s###removeButtonMappingButton%s", ICON_FA_TIMES, id.c_str()).c_str(),
|
|
ImVec2(ImGui::CalcTextSize(ICON_FA_TIMES).x + SCALE_IMGUI_SIZE(10.0f), 0.0f))) {
|
|
Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetControllerByPort(port)
|
|
->GetButton(bitmask)
|
|
->ClearButtonMapping(id);
|
|
};
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopStyleVar();
|
|
|
|
ImGui::SameLine(0, SCALE_IMGUI_SIZE(4.0f));
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawButtonLine(const char* buttonName, uint8_t port, CONTROLLERBUTTONS_T bitmask,
|
|
ImVec4 color = CHIP_COLOR_N64_GREY) {
|
|
ImGui::NewLine();
|
|
ImGui::SameLine(SCALE_IMGUI_SIZE(32.0f));
|
|
DrawInputChip(buttonName, color);
|
|
ImGui::SameLine(SCALE_IMGUI_SIZE(86.0f));
|
|
for (auto id : mBitmaskToMappingIds[port][bitmask]) {
|
|
DrawButtonLineEditMappingButton(port, bitmask, id);
|
|
}
|
|
DrawButtonLineAddMappingButton(port, bitmask);
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawStickDirectionLineAddMappingButton(uint8_t port, uint8_t stick,
|
|
Ship::Direction direction) {
|
|
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(1.0f, 0.5f));
|
|
auto popupId = StringHelper::Sprintf("addStickDirectionMappingPopup##%d-%d-%d", port, stick, direction);
|
|
if (ImGui::Button(
|
|
StringHelper::Sprintf("%s###addStickDirectionMappingButton%d-%d-%d", ICON_FA_PLUS, port, stick, direction)
|
|
.c_str(),
|
|
ImVec2(SCALE_IMGUI_SIZE(20.0f), 0.0f))) {
|
|
ImGui::OpenPopup(popupId.c_str());
|
|
};
|
|
ImGui::PopStyleVar();
|
|
|
|
if (ImGui::BeginPopup(popupId.c_str())) {
|
|
mInputEditorPopupOpen = true;
|
|
ImGui::Text("Press any button,\nmove any axis,\nor press any key\nto add mapping");
|
|
if (ImGui::Button("Cancel")) {
|
|
mInputEditorPopupOpen = false;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
if (stick == Ship::LEFT) {
|
|
if (mMappingInputBlockTimer == INT32_MAX &&
|
|
Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetControllerByPort(port)
|
|
->GetLeftStick()
|
|
->AddOrEditAxisDirectionMappingFromRawPress(direction, "")) {
|
|
mInputEditorPopupOpen = false;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
} else {
|
|
if (mMappingInputBlockTimer == INT32_MAX &&
|
|
Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetControllerByPort(port)
|
|
->GetRightStick()
|
|
->AddOrEditAxisDirectionMappingFromRawPress(direction, "")) {
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
}
|
|
ImGui::EndPopup();
|
|
}
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawStickDirectionLineEditMappingButton(uint8_t port, uint8_t stick,
|
|
Ship::Direction direction, std::string id) {
|
|
std::shared_ptr<Ship::ControllerAxisDirectionMapping> mapping = nullptr;
|
|
if (stick == Ship::LEFT) {
|
|
mapping = Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetControllerByPort(port)
|
|
->GetLeftStick()
|
|
->GetAxisDirectionMappingById(direction, id);
|
|
} else {
|
|
mapping = Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetControllerByPort(port)
|
|
->GetRightStick()
|
|
->GetAxisDirectionMappingById(direction, id);
|
|
}
|
|
|
|
if (mapping == nullptr) {
|
|
return;
|
|
}
|
|
if (!mDeviceIndexVisiblity[mapping->GetShipDeviceIndex()]) {
|
|
return;
|
|
}
|
|
|
|
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.5f));
|
|
std::string icon = "";
|
|
switch (mapping->GetMappingType()) {
|
|
case MAPPING_TYPE_GAMEPAD:
|
|
icon = ICON_FA_GAMEPAD;
|
|
break;
|
|
case MAPPING_TYPE_KEYBOARD:
|
|
icon = ICON_FA_KEYBOARD_O;
|
|
break;
|
|
case MAPPING_TYPE_UNKNOWN:
|
|
icon = ICON_FA_BUG;
|
|
break;
|
|
}
|
|
auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
|
|
auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
|
|
auto physicalInputDisplayName =
|
|
StringHelper::Sprintf("%s %s", icon.c_str(), mapping->GetPhysicalInputName().c_str());
|
|
GetButtonColorsForShipDeviceIndex(mapping->GetShipDeviceIndex(), buttonColor, buttonHoveredColor);
|
|
ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
|
|
auto popupId = StringHelper::Sprintf("editStickDirectionMappingPopup##%s", id.c_str());
|
|
if (ImGui::Button(
|
|
StringHelper::Sprintf("%s###editStickDirectionMappingButton%s", physicalInputDisplayName.c_str(),
|
|
id.c_str())
|
|
.c_str(),
|
|
ImVec2(ImGui::CalcTextSize(physicalInputDisplayName.c_str()).x + SCALE_IMGUI_SIZE(12.0f), 0.0f))) {
|
|
ImGui::OpenPopup(popupId.c_str());
|
|
}
|
|
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal | ImGuiHoveredFlags_NoSharedDelay)) {
|
|
ImGui::SetTooltip(mapping->GetPhysicalDeviceName().c_str());
|
|
}
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopStyleColor();
|
|
|
|
if (ImGui::BeginPopup(popupId.c_str())) {
|
|
mInputEditorPopupOpen = true;
|
|
ImGui::Text("Press any button,\nmove any axis,\nor press any key\nto edit mapping");
|
|
if (ImGui::Button("Cancel")) {
|
|
mInputEditorPopupOpen = false;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
|
|
if (stick == Ship::LEFT) {
|
|
if (mMappingInputBlockTimer == INT32_MAX &&
|
|
Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetControllerByPort(port)
|
|
->GetLeftStick()
|
|
->AddOrEditAxisDirectionMappingFromRawPress(direction, id)) {
|
|
mInputEditorPopupOpen = false;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
} else {
|
|
if (mMappingInputBlockTimer == INT32_MAX &&
|
|
Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetControllerByPort(port)
|
|
->GetRightStick()
|
|
->AddOrEditAxisDirectionMappingFromRawPress(direction, id)) {
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
}
|
|
ImGui::EndPopup();
|
|
}
|
|
|
|
ImGui::PopStyleVar();
|
|
ImGui::SameLine(0, 0);
|
|
ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
|
|
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(1.0f, 0.5f));
|
|
if (ImGui::Button(
|
|
StringHelper::Sprintf("%s###removeStickDirectionMappingButton%s", ICON_FA_TIMES, id.c_str()).c_str(),
|
|
ImVec2(ImGui::CalcTextSize(ICON_FA_TIMES).x + SCALE_IMGUI_SIZE(10.0f), 0.0f))) {
|
|
if (stick == Ship::LEFT) {
|
|
Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetControllerByPort(port)
|
|
->GetLeftStick()
|
|
->ClearAxisDirectionMapping(direction, id);
|
|
} else {
|
|
Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetControllerByPort(port)
|
|
->GetRightStick()
|
|
->ClearAxisDirectionMapping(direction, id);
|
|
}
|
|
};
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopStyleVar();
|
|
ImGui::SameLine(0, SCALE_IMGUI_SIZE(4.0f));
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawStickDirectionLine(const char* axisDirectionName, uint8_t port, uint8_t stick,
|
|
Ship::Direction direction, ImVec4 color = CHIP_COLOR_N64_GREY) {
|
|
ImGui::NewLine();
|
|
ImGui::SameLine();
|
|
ImGui::BeginDisabled();
|
|
ImGui::PushStyleColor(ImGuiCol_Button, color);
|
|
ImGui::Button(axisDirectionName, ImVec2(SCALE_IMGUI_SIZE(26.0f), 0));
|
|
ImGui::PopStyleColor();
|
|
ImGui::EndDisabled();
|
|
ImGui::SameLine(0.0f, SCALE_IMGUI_SIZE(4.0f));
|
|
for (auto id : mStickDirectionToMappingIds[port][stick][direction]) {
|
|
DrawStickDirectionLineEditMappingButton(port, stick, direction, id);
|
|
}
|
|
DrawStickDirectionLineAddMappingButton(port, stick, direction);
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawStickSection(uint8_t port, uint8_t stick, int32_t id,
|
|
ImVec4 color = CHIP_COLOR_N64_GREY) {
|
|
static int8_t sX, sY;
|
|
std::shared_ptr<Ship::ControllerStick> controllerStick = nullptr;
|
|
if (stick == Ship::LEFT) {
|
|
controllerStick = Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetLeftStick();
|
|
} else {
|
|
controllerStick = Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetRightStick();
|
|
}
|
|
controllerStick->Process(sX, sY);
|
|
DrawAnalogPreview(StringHelper::Sprintf("##AnalogPreview%d", id).c_str(), ImVec2(sX, sY));
|
|
|
|
ImGui::SameLine();
|
|
ImGui::BeginGroup();
|
|
DrawStickDirectionLine(ICON_FA_ARROW_UP, port, stick, Ship::UP, color);
|
|
DrawStickDirectionLine(ICON_FA_ARROW_DOWN, port, stick, Ship::DOWN, color);
|
|
DrawStickDirectionLine(ICON_FA_ARROW_LEFT, port, stick, Ship::LEFT, color);
|
|
DrawStickDirectionLine(ICON_FA_ARROW_RIGHT, port, stick, Ship::RIGHT, color);
|
|
ImGui::EndGroup();
|
|
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
|
|
if (ImGui::TreeNode(StringHelper::Sprintf("Analog Stick Options##%d", id).c_str())) {
|
|
ImGui::Text("Sensitivity:");
|
|
|
|
int32_t sensitivityPercentage = controllerStick->GetSensitivityPercentage();
|
|
if (sensitivityPercentage == 0) {
|
|
ImGui::BeginDisabled();
|
|
}
|
|
ImGui::PushButtonRepeat(true);
|
|
if (ImGui::Button(StringHelper::Sprintf("-##Sensitivity%d", id).c_str())) {
|
|
controllerStick->SetSensitivity(sensitivityPercentage - 1);
|
|
}
|
|
ImGui::PopButtonRepeat();
|
|
if (sensitivityPercentage == 0) {
|
|
ImGui::EndDisabled();
|
|
}
|
|
ImGui::SameLine(0.0f, 0.0f);
|
|
ImGui::SetNextItemWidth(SCALE_IMGUI_SIZE(160.0f));
|
|
if (ImGui::SliderInt(StringHelper::Sprintf("##Sensitivity%d", id).c_str(), &sensitivityPercentage, 0, 200,
|
|
"%d%%", ImGuiSliderFlags_AlwaysClamp)) {
|
|
controllerStick->SetSensitivity(sensitivityPercentage);
|
|
}
|
|
ImGui::SameLine(0.0f, 0.0f);
|
|
if (sensitivityPercentage == 200) {
|
|
ImGui::BeginDisabled();
|
|
}
|
|
ImGui::PushButtonRepeat(true);
|
|
if (ImGui::Button(StringHelper::Sprintf("+##Sensitivity%d", id).c_str())) {
|
|
controllerStick->SetSensitivity(sensitivityPercentage + 1);
|
|
}
|
|
ImGui::PopButtonRepeat();
|
|
if (sensitivityPercentage == 200) {
|
|
ImGui::EndDisabled();
|
|
}
|
|
if (!controllerStick->SensitivityIsDefault()) {
|
|
ImGui::SameLine();
|
|
if (ImGui::Button(StringHelper::Sprintf("Reset to Default###resetStickSensitivity%d", id).c_str())) {
|
|
controllerStick->ResetSensitivityToDefault();
|
|
}
|
|
}
|
|
|
|
ImGui::Text("Deadzone:");
|
|
|
|
int32_t deadzonePercentage = controllerStick->GetDeadzonePercentage();
|
|
if (deadzonePercentage == 0) {
|
|
ImGui::BeginDisabled();
|
|
}
|
|
ImGui::PushButtonRepeat(true);
|
|
if (ImGui::Button(StringHelper::Sprintf("-##Deadzone%d", id).c_str())) {
|
|
controllerStick->SetDeadzone(deadzonePercentage - 1);
|
|
}
|
|
ImGui::PopButtonRepeat();
|
|
if (deadzonePercentage == 0) {
|
|
ImGui::EndDisabled();
|
|
}
|
|
ImGui::SameLine(0.0f, 0.0f);
|
|
ImGui::SetNextItemWidth(SCALE_IMGUI_SIZE(160.0f));
|
|
if (ImGui::SliderInt(StringHelper::Sprintf("##Deadzone%d", id).c_str(), &deadzonePercentage, 0, 100, "%d%%",
|
|
ImGuiSliderFlags_AlwaysClamp)) {
|
|
controllerStick->SetDeadzone(deadzonePercentage);
|
|
}
|
|
ImGui::SameLine(0.0f, 0.0f);
|
|
if (deadzonePercentage == 100) {
|
|
ImGui::BeginDisabled();
|
|
}
|
|
ImGui::PushButtonRepeat(true);
|
|
if (ImGui::Button(StringHelper::Sprintf("+##Deadzone%d", id).c_str())) {
|
|
controllerStick->SetDeadzone(deadzonePercentage + 1);
|
|
}
|
|
ImGui::PopButtonRepeat();
|
|
if (deadzonePercentage == 100) {
|
|
ImGui::EndDisabled();
|
|
}
|
|
if (!controllerStick->DeadzoneIsDefault()) {
|
|
ImGui::SameLine();
|
|
if (ImGui::Button(StringHelper::Sprintf("Reset to Default###resetStickDeadzone%d", id).c_str())) {
|
|
controllerStick->ResetDeadzoneToDefault();
|
|
}
|
|
}
|
|
|
|
ImGui::Text("Notch Snap Angle:");
|
|
int32_t notchSnapAngle = controllerStick->GetNotchSnapAngle();
|
|
if (notchSnapAngle == 0) {
|
|
ImGui::BeginDisabled();
|
|
}
|
|
ImGui::PushButtonRepeat(true);
|
|
if (ImGui::Button(StringHelper::Sprintf("-##NotchProximityThreshold%d", id).c_str())) {
|
|
controllerStick->SetNotchSnapAngle(notchSnapAngle - 1);
|
|
}
|
|
ImGui::PopButtonRepeat();
|
|
if (notchSnapAngle == 0) {
|
|
ImGui::EndDisabled();
|
|
}
|
|
ImGui::SameLine(0.0f, 0.0f);
|
|
ImGui::SetNextItemWidth(SCALE_IMGUI_SIZE(160.0f));
|
|
if (ImGui::SliderInt(StringHelper::Sprintf("##NotchProximityThreshold%d", id).c_str(), ¬chSnapAngle, 0, 45,
|
|
"%d°", ImGuiSliderFlags_AlwaysClamp)) {
|
|
controllerStick->SetNotchSnapAngle(notchSnapAngle);
|
|
}
|
|
ImGui::SameLine(0.0f, 0.0f);
|
|
if (notchSnapAngle == 45) {
|
|
ImGui::BeginDisabled();
|
|
}
|
|
ImGui::PushButtonRepeat(true);
|
|
if (ImGui::Button(StringHelper::Sprintf("+##NotchProximityThreshold%d", id).c_str())) {
|
|
controllerStick->SetNotchSnapAngle(notchSnapAngle + 1);
|
|
}
|
|
ImGui::PopButtonRepeat();
|
|
if (notchSnapAngle == 45) {
|
|
ImGui::EndDisabled();
|
|
}
|
|
if (!controllerStick->NotchSnapAngleIsDefault()) {
|
|
ImGui::SameLine();
|
|
if (ImGui::Button(StringHelper::Sprintf("Reset to Default###resetStickSnap%d", id).c_str())) {
|
|
controllerStick->ResetNotchSnapAngleToDefault();
|
|
}
|
|
}
|
|
|
|
ImGui::TreePop();
|
|
}
|
|
}
|
|
|
|
void BenInputEditorWindow::UpdateBitmaskToMappingIds(uint8_t port) {
|
|
// todo: do we need this now that ControllerButton exists?
|
|
|
|
for (auto [bitmask, button] :
|
|
Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetAllButtons()) {
|
|
for (auto [id, mapping] : button->GetAllButtonMappings()) {
|
|
// using a vector here instead of a set because i want newly added mappings
|
|
// to go to the end of the list instead of autosorting
|
|
if (std::find(mBitmaskToMappingIds[port][bitmask].begin(), mBitmaskToMappingIds[port][bitmask].end(), id) ==
|
|
mBitmaskToMappingIds[port][bitmask].end()) {
|
|
mBitmaskToMappingIds[port][bitmask].push_back(id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void BenInputEditorWindow::UpdateStickDirectionToMappingIds(uint8_t port) {
|
|
// todo: do we need this?
|
|
for (auto stick :
|
|
{ std::make_pair<uint8_t, std::shared_ptr<Ship::ControllerStick>>(
|
|
Ship::LEFT, Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetLeftStick()),
|
|
std::make_pair<uint8_t, std::shared_ptr<Ship::ControllerStick>>(
|
|
Ship::RIGHT,
|
|
Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetRightStick()) }) {
|
|
for (auto direction : { Ship::LEFT, Ship::RIGHT, Ship::UP, Ship::DOWN }) {
|
|
for (auto [id, mapping] : stick.second->GetAllAxisDirectionMappingByDirection(direction)) {
|
|
// using a vector here instead of a set because i want newly added mappings
|
|
// to go to the end of the list instead of autosorting
|
|
if (std::find(mStickDirectionToMappingIds[port][stick.first][direction].begin(),
|
|
mStickDirectionToMappingIds[port][stick.first][direction].end(),
|
|
id) == mStickDirectionToMappingIds[port][stick.first][direction].end()) {
|
|
mStickDirectionToMappingIds[port][stick.first][direction].push_back(id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawRemoveRumbleMappingButton(uint8_t port, std::string id) {
|
|
ImGui::SameLine();
|
|
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(1.0f, 0.5f));
|
|
if (ImGui::Button(StringHelper::Sprintf("%s###removeRumbleMapping%s", ICON_FA_TIMES, id.c_str()).c_str(),
|
|
ImVec2(SCALE_IMGUI_SIZE(20.0f), SCALE_IMGUI_SIZE(20.0f)))) {
|
|
Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetRumble()->ClearRumbleMapping(id);
|
|
}
|
|
ImGui::PopStyleVar();
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawAddRumbleMappingButton(uint8_t port) {
|
|
ImGui::SameLine();
|
|
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(1.0f, 0.5f));
|
|
auto popupId = StringHelper::Sprintf("addRumbleMappingPopup##%d", port);
|
|
if (ImGui::Button(StringHelper::Sprintf("%s###addRumbleMapping%d", ICON_FA_PLUS, port).c_str(),
|
|
ImVec2(SCALE_IMGUI_SIZE(20.0f), SCALE_IMGUI_SIZE(20.0f)))) {
|
|
ImGui::OpenPopup(popupId.c_str());
|
|
}
|
|
ImGui::PopStyleVar();
|
|
|
|
if (ImGui::BeginPopup(popupId.c_str())) {
|
|
mInputEditorPopupOpen = true;
|
|
ImGui::Text("Press any button\nor move any axis\nto add rumble device");
|
|
if (ImGui::Button("Cancel")) {
|
|
mInputEditorPopupOpen = false;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
|
|
if (mMappingInputBlockTimer == INT32_MAX && Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetControllerByPort(port)
|
|
->GetRumble()
|
|
->AddRumbleMappingFromRawPress()) {
|
|
mInputEditorPopupOpen = false;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::EndPopup();
|
|
}
|
|
}
|
|
|
|
bool BenInputEditorWindow::TestingRumble() {
|
|
return mRumbleTimer != INT32_MAX;
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawRumbleSection(uint8_t port) {
|
|
for (auto [id, mapping] : Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetControllerByPort(port)
|
|
->GetRumble()
|
|
->GetAllRumbleMappings()) {
|
|
ImGui::AlignTextToFramePadding();
|
|
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
|
|
auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
|
|
auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
|
|
GetButtonColorsForShipDeviceIndex(mapping->GetShipDeviceIndex(), buttonColor, buttonHoveredColor);
|
|
// begin hackaround https://github.com/ocornut/imgui/issues/282#issuecomment-123763192
|
|
// spaces to have background color for text in a tree node
|
|
std::string spaces = "";
|
|
for (size_t i = 0; i < mapping->GetPhysicalDeviceName().length(); i++) {
|
|
spaces += " ";
|
|
}
|
|
auto open = ImGui::TreeNode(StringHelper::Sprintf("%s###Rumble%s", spaces.c_str(), id.c_str()).c_str());
|
|
ImGui::SameLine();
|
|
ImGui::SetCursorPosX(SCALE_IMGUI_SIZE(30.0f));
|
|
// end hackaround
|
|
|
|
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
|
|
ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
|
|
ImGui::Button(mapping->GetPhysicalDeviceName().c_str());
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopItemFlag();
|
|
|
|
DrawRemoveRumbleMappingButton(port, id);
|
|
ImGui::SameLine();
|
|
if (ImGui::Button(
|
|
StringHelper::Sprintf("%s###rumbleTestButton%s", TestingRumble() ? "Stop" : "Test", id.c_str())
|
|
.c_str())) {
|
|
if (mRumbleTimer != INT32_MAX) {
|
|
mRumbleTimer = INT32_MAX;
|
|
mRumbleMappingToTest->StopRumble();
|
|
mRumbleMappingToTest = nullptr;
|
|
} else {
|
|
mRumbleTimer = ImGui::GetIO().Framerate;
|
|
mRumbleMappingToTest = mapping;
|
|
}
|
|
}
|
|
if (open) {
|
|
ImGui::Text("Small Motor Intensity:");
|
|
|
|
int32_t smallMotorIntensity = mapping->GetHighFrequencyIntensityPercentage();
|
|
if (smallMotorIntensity == 0) {
|
|
ImGui::BeginDisabled();
|
|
}
|
|
ImGui::PushButtonRepeat(true);
|
|
if (ImGui::Button(StringHelper::Sprintf("-##Small Motor Intensity%s", id.c_str()).c_str())) {
|
|
mapping->SetHighFrequencyIntensity(smallMotorIntensity - 1);
|
|
mapping->SaveToConfig();
|
|
}
|
|
ImGui::PopButtonRepeat();
|
|
if (smallMotorIntensity == 0) {
|
|
ImGui::EndDisabled();
|
|
}
|
|
ImGui::SameLine(0.0f, 0.0f);
|
|
ImGui::SetNextItemWidth(SCALE_IMGUI_SIZE(160.0f));
|
|
if (ImGui::SliderInt(StringHelper::Sprintf("##Small Motor Intensity%s", id.c_str()).c_str(),
|
|
&smallMotorIntensity, 0, 100, "%d%%", ImGuiSliderFlags_AlwaysClamp)) {
|
|
mapping->SetHighFrequencyIntensity(smallMotorIntensity);
|
|
mapping->SaveToConfig();
|
|
}
|
|
ImGui::SameLine(0.0f, 0.0f);
|
|
if (smallMotorIntensity == 100) {
|
|
ImGui::BeginDisabled();
|
|
}
|
|
ImGui::PushButtonRepeat(true);
|
|
if (ImGui::Button(StringHelper::Sprintf("+##Small Motor Intensity%s", id.c_str()).c_str())) {
|
|
mapping->SetHighFrequencyIntensity(smallMotorIntensity + 1);
|
|
mapping->SaveToConfig();
|
|
}
|
|
ImGui::PopButtonRepeat();
|
|
if (smallMotorIntensity == 100) {
|
|
ImGui::EndDisabled();
|
|
}
|
|
if (!mapping->HighFrequencyIntensityIsDefault()) {
|
|
ImGui::SameLine();
|
|
if (ImGui::Button(StringHelper::Sprintf("Reset to Default###resetHighFrequencyIntensity%s", id.c_str())
|
|
.c_str())) {
|
|
mapping->ResetHighFrequencyIntensityToDefault();
|
|
}
|
|
}
|
|
|
|
ImGui::Text("Large Motor Intensity:");
|
|
|
|
int32_t largeMotorIntensity = mapping->GetLowFrequencyIntensityPercentage();
|
|
if (largeMotorIntensity == 0) {
|
|
ImGui::BeginDisabled();
|
|
}
|
|
ImGui::PushButtonRepeat(true);
|
|
if (ImGui::Button(StringHelper::Sprintf("-##Large Motor Intensity%s", id.c_str()).c_str())) {
|
|
mapping->SetLowFrequencyIntensity(largeMotorIntensity - 1);
|
|
mapping->SaveToConfig();
|
|
}
|
|
ImGui::PopButtonRepeat();
|
|
if (largeMotorIntensity == 0) {
|
|
ImGui::EndDisabled();
|
|
}
|
|
ImGui::SameLine(0.0f, 0.0f);
|
|
ImGui::SetNextItemWidth(SCALE_IMGUI_SIZE(160.0f));
|
|
if (ImGui::SliderInt(StringHelper::Sprintf("##Large Motor Intensity%s", id.c_str()).c_str(),
|
|
&largeMotorIntensity, 0, 100, "%d%%", ImGuiSliderFlags_AlwaysClamp)) {
|
|
mapping->SetLowFrequencyIntensity(largeMotorIntensity);
|
|
mapping->SaveToConfig();
|
|
}
|
|
ImGui::SameLine(0.0f, 0.0f);
|
|
if (largeMotorIntensity == 100) {
|
|
ImGui::BeginDisabled();
|
|
}
|
|
ImGui::PushButtonRepeat(true);
|
|
if (ImGui::Button(StringHelper::Sprintf("+##Large Motor Intensity%s", id.c_str()).c_str())) {
|
|
mapping->SetLowFrequencyIntensity(largeMotorIntensity + 1);
|
|
mapping->SaveToConfig();
|
|
}
|
|
ImGui::PopButtonRepeat();
|
|
if (largeMotorIntensity == 100) {
|
|
ImGui::EndDisabled();
|
|
}
|
|
if (!mapping->LowFrequencyIntensityIsDefault()) {
|
|
ImGui::SameLine();
|
|
if (ImGui::Button(
|
|
StringHelper::Sprintf("Reset to Default###resetLowFrequencyIntensity%s", id.c_str()).c_str())) {
|
|
mapping->ResetLowFrequencyIntensityToDefault();
|
|
}
|
|
}
|
|
ImGui::Dummy(ImVec2(0, SCALE_IMGUI_SIZE(20)));
|
|
|
|
ImGui::TreePop();
|
|
}
|
|
}
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
ImGui::BulletText("Add rumble device");
|
|
DrawAddRumbleMappingButton(port);
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawRemoveLEDMappingButton(uint8_t port, std::string id) {
|
|
ImGui::SameLine();
|
|
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(1.0f, 0.5f));
|
|
if (ImGui::Button(StringHelper::Sprintf("%s###removeLEDMapping%s", ICON_FA_TIMES, id.c_str()).c_str(),
|
|
ImVec2(SCALE_IMGUI_SIZE(20.0f), SCALE_IMGUI_SIZE(20.0f)))) {
|
|
Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetLED()->ClearLEDMapping(id);
|
|
}
|
|
ImGui::PopStyleVar();
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawAddLEDMappingButton(uint8_t port) {
|
|
ImGui::SameLine();
|
|
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(1.0f, 0.5f));
|
|
auto popupId = StringHelper::Sprintf("addLEDMappingPopup##%d", port);
|
|
if (ImGui::Button(StringHelper::Sprintf("%s###addLEDMapping%d", ICON_FA_PLUS, port).c_str(),
|
|
ImVec2(SCALE_IMGUI_SIZE(20.0f), SCALE_IMGUI_SIZE(20.0f)))) {
|
|
ImGui::OpenPopup(popupId.c_str());
|
|
}
|
|
ImGui::PopStyleVar();
|
|
|
|
if (ImGui::BeginPopup(popupId.c_str())) {
|
|
mInputEditorPopupOpen = true;
|
|
ImGui::Text("Press any button\nor move any axis\nto add LED device");
|
|
if (ImGui::Button("Cancel")) {
|
|
mInputEditorPopupOpen = false;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
|
|
if (mMappingInputBlockTimer == INT32_MAX && Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetControllerByPort(port)
|
|
->GetLED()
|
|
->AddLEDMappingFromRawPress()) {
|
|
mInputEditorPopupOpen = false;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::EndPopup();
|
|
}
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawLEDSection(uint8_t port) {
|
|
for (auto [id, mapping] :
|
|
Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetLED()->GetAllLEDMappings()) {
|
|
ImGui::AlignTextToFramePadding();
|
|
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
|
|
auto open = ImGui::TreeNode(
|
|
StringHelper::Sprintf("%s##LED%s", mapping->GetPhysicalDeviceName().c_str(), id.c_str()).c_str());
|
|
DrawRemoveLEDMappingButton(port, id);
|
|
if (open) {
|
|
ImGui::AlignTextToFramePadding();
|
|
ImGui::Text("LED Color:");
|
|
ImGui::SameLine();
|
|
ImGui::SetNextItemWidth(SCALE_IMGUI_SIZE(80.0f));
|
|
int32_t colorSource = mapping->GetColorSource();
|
|
if (ImGui::Combo(StringHelper::Sprintf("###ledColorSource%s", mapping->GetLEDMappingId().c_str()).c_str(),
|
|
&colorSource, "Off\0Set\0Game\0\0")) {
|
|
mapping->SetColorSource(colorSource);
|
|
};
|
|
if (mapping->GetColorSource() == LED_COLOR_SOURCE_SET) {
|
|
ImGui::SameLine();
|
|
ImVec4 color = { mapping->GetSavedColor().r / 255.0f, mapping->GetSavedColor().g / 255.0f,
|
|
mapping->GetSavedColor().b / 255.0f, 1.0f };
|
|
if (ImGui::ColorEdit3(
|
|
StringHelper::Sprintf("###ledSavedColor%s", mapping->GetLEDMappingId().c_str()).c_str(),
|
|
(float*)&color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel)) {
|
|
mapping->SetSavedColor(
|
|
Color_RGB8({ static_cast<uint8_t>(color.x * 255.0), static_cast<uint8_t>(color.y * 255.0),
|
|
static_cast<uint8_t>(color.z * 255.0) }));
|
|
}
|
|
}
|
|
ImGui::TreePop();
|
|
}
|
|
}
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
ImGui::BulletText("Add LED device");
|
|
DrawAddLEDMappingButton(port);
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawRemoveGyroMappingButton(uint8_t port, std::string id) {
|
|
ImGui::SameLine();
|
|
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(1.0f, 0.5f));
|
|
if (ImGui::Button(StringHelper::Sprintf("%s###removeGyroMapping%s", ICON_FA_TIMES, id.c_str()).c_str(),
|
|
ImVec2(SCALE_IMGUI_SIZE(20.0f), SCALE_IMGUI_SIZE(20.0f)))) {
|
|
Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetGyro()->ClearGyroMapping();
|
|
}
|
|
ImGui::PopStyleVar();
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawAddGyroMappingButton(uint8_t port) {
|
|
ImGui::SameLine();
|
|
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(1.0f, 0.5f));
|
|
auto popupId = StringHelper::Sprintf("addGyroMappingPopup##%d", port);
|
|
if (ImGui::Button(StringHelper::Sprintf("%s###addGyroMapping%d", ICON_FA_PLUS, port).c_str(),
|
|
ImVec2(SCALE_IMGUI_SIZE(20.0f), SCALE_IMGUI_SIZE(20.0f)))) {
|
|
ImGui::OpenPopup(popupId.c_str());
|
|
}
|
|
ImGui::PopStyleVar();
|
|
|
|
if (ImGui::BeginPopup(popupId.c_str())) {
|
|
mInputEditorPopupOpen = true;
|
|
ImGui::Text("Press any button\nor move any axis\nto add gyro device");
|
|
if (ImGui::Button("Cancel")) {
|
|
mInputEditorPopupOpen = false;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
|
|
if (mMappingInputBlockTimer == INT32_MAX && Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetControllerByPort(port)
|
|
->GetGyro()
|
|
->SetGyroMappingFromRawPress()) {
|
|
mInputEditorPopupOpen = false;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::EndPopup();
|
|
}
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawGyroSection(uint8_t port) {
|
|
auto mapping =
|
|
Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetGyro()->GetGyroMapping();
|
|
if (mapping != nullptr) {
|
|
auto id = mapping->GetGyroMappingId();
|
|
ImGui::AlignTextToFramePadding();
|
|
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
|
|
ImGui::BulletText(mapping->GetPhysicalDeviceName().c_str());
|
|
DrawRemoveGyroMappingButton(port, id);
|
|
|
|
static float sPitch, sYaw = 0.0f;
|
|
mapping->UpdatePad(sPitch, sYaw);
|
|
|
|
ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPos().x, ImGui::GetCursorPos().y - SCALE_IMGUI_SIZE(8)));
|
|
// to find a reasonable scaling factor gyro values
|
|
// I tried to find the maximum value reported by shaking
|
|
// a PS5 controller as hard as I could without worrying about breaking it
|
|
// the max I found for both pitch and yaw was ~21
|
|
// the preview window expects values in an n64 analog stick range (-85 to 85)
|
|
// so I decided to multiply these by 85/21
|
|
DrawAnalogPreview(StringHelper::Sprintf("###GyroPreview%s", id.c_str()).c_str(),
|
|
ImVec2(sYaw * (85.0f / 21.0f), sPitch * (85.0f / 21.0f)), 0.0f, true);
|
|
ImGui::SameLine();
|
|
ImGui::SetCursorPos(
|
|
ImVec2(ImGui::GetCursorPos().x + SCALE_IMGUI_SIZE(8), ImGui::GetCursorPos().y + SCALE_IMGUI_SIZE(8)));
|
|
|
|
ImGui::BeginGroup();
|
|
ImGui::Text("Sensitivity:");
|
|
|
|
int32_t sensitivity = mapping->GetSensitivityPercent();
|
|
if (sensitivity == 0) {
|
|
ImGui::BeginDisabled();
|
|
}
|
|
ImGui::PushButtonRepeat(true);
|
|
if (ImGui::Button(StringHelper::Sprintf("-##GyroSensitivity%s", id.c_str()).c_str())) {
|
|
mapping->SetSensitivity(sensitivity - 1);
|
|
mapping->SaveToConfig();
|
|
}
|
|
ImGui::PopButtonRepeat();
|
|
if (sensitivity == 0) {
|
|
ImGui::EndDisabled();
|
|
}
|
|
ImGui::SameLine(0.0f, 0.0f);
|
|
ImGui::SetNextItemWidth(SCALE_IMGUI_SIZE(160.0f));
|
|
if (ImGui::SliderInt(StringHelper::Sprintf("##GyroSensitivity%s", id.c_str()).c_str(), &sensitivity, 0, 100,
|
|
"%d%%", ImGuiSliderFlags_AlwaysClamp)) {
|
|
mapping->SetSensitivity(sensitivity);
|
|
mapping->SaveToConfig();
|
|
}
|
|
ImGui::SameLine(0.0f, 0.0f);
|
|
if (sensitivity == 100) {
|
|
ImGui::BeginDisabled();
|
|
}
|
|
ImGui::PushButtonRepeat(true);
|
|
if (ImGui::Button(StringHelper::Sprintf("+##GyroSensitivity%s", id.c_str()).c_str())) {
|
|
mapping->SetSensitivity(sensitivity + 1);
|
|
mapping->SaveToConfig();
|
|
}
|
|
ImGui::PopButtonRepeat();
|
|
if (sensitivity == 100) {
|
|
ImGui::EndDisabled();
|
|
}
|
|
|
|
if (!mapping->SensitivityIsDefault()) {
|
|
ImGui::SameLine();
|
|
if (ImGui::Button(StringHelper::Sprintf("Reset to Default###resetGyroSensitivity%s", id.c_str()).c_str())) {
|
|
mapping->ResetSensitivityToDefault();
|
|
}
|
|
}
|
|
|
|
ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPos().x, ImGui::GetCursorPos().y + SCALE_IMGUI_SIZE(8)));
|
|
if (ImGui::Button("Recalibrate")) {
|
|
mapping->Recalibrate();
|
|
mapping->SaveToConfig();
|
|
}
|
|
ImGui::EndGroup();
|
|
ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPos().x, ImGui::GetCursorPos().y - SCALE_IMGUI_SIZE(8)));
|
|
} else {
|
|
ImGui::AlignTextToFramePadding();
|
|
ImGui::BulletText("Add gyro device");
|
|
DrawAddGyroMappingButton(port);
|
|
}
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawButtonDeviceIcons(uint8_t portIndex, std::set<CONTROLLERBUTTONS_T> bitmasks) {
|
|
std::set<Ship::ShipDeviceIndex> allLusDeviceIndices;
|
|
allLusDeviceIndices.insert(Ship::ShipDeviceIndex::Keyboard);
|
|
for (auto [lusIndex, mapping] : Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetDeviceIndexMappingManager()
|
|
->GetAllDeviceIndexMappingsFromConfig()) {
|
|
allLusDeviceIndices.insert(lusIndex);
|
|
}
|
|
|
|
std::vector<std::pair<Ship::ShipDeviceIndex, bool>> lusDeviceIndiciesWithMappings;
|
|
for (auto lusIndex : allLusDeviceIndices) {
|
|
for (auto [bitmask, button] :
|
|
Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->GetAllButtons()) {
|
|
if (!bitmasks.contains(bitmask)) {
|
|
continue;
|
|
}
|
|
|
|
if (button->HasMappingsForShipDeviceIndex(lusIndex)) {
|
|
for (auto [id, mapping] : button->GetAllButtonMappings()) {
|
|
if (mapping->GetShipDeviceIndex() == lusIndex) {
|
|
lusDeviceIndiciesWithMappings.push_back(
|
|
std::pair<Ship::ShipDeviceIndex, bool>(lusIndex, mapping->PhysicalDeviceIsConnected()));
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (auto [lusIndex, connected] : lusDeviceIndiciesWithMappings) {
|
|
auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
|
|
auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
|
|
GetButtonColorsForShipDeviceIndex(lusIndex, buttonColor, buttonHoveredColor);
|
|
ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
|
|
ImGui::SameLine();
|
|
if (lusIndex == Ship::ShipDeviceIndex::Keyboard) {
|
|
ImGui::SmallButton(ICON_FA_KEYBOARD_O);
|
|
} else {
|
|
ImGui::SmallButton(connected ? ICON_FA_GAMEPAD : ICON_FA_CHAIN_BROKEN);
|
|
}
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopStyleColor();
|
|
}
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawAnalogStickDeviceIcons(uint8_t portIndex, Ship::Stick stick) {
|
|
std::set<Ship::ShipDeviceIndex> allLusDeviceIndices;
|
|
allLusDeviceIndices.insert(Ship::ShipDeviceIndex::Keyboard);
|
|
for (auto [lusIndex, mapping] : Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetDeviceIndexMappingManager()
|
|
->GetAllDeviceIndexMappingsFromConfig()) {
|
|
allLusDeviceIndices.insert(lusIndex);
|
|
}
|
|
|
|
std::vector<std::pair<Ship::ShipDeviceIndex, bool>> lusDeviceIndiciesWithMappings;
|
|
for (auto lusIndex : allLusDeviceIndices) {
|
|
auto controllerStick =
|
|
stick == Ship::Stick::LEFT_STICK
|
|
? Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->GetLeftStick()
|
|
: Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->GetRightStick();
|
|
if (controllerStick->HasMappingsForShipDeviceIndex(lusIndex)) {
|
|
for (auto [direction, mappings] : controllerStick->GetAllAxisDirectionMappings()) {
|
|
bool foundMapping = false;
|
|
for (auto [id, mapping] : mappings) {
|
|
if (mapping->GetShipDeviceIndex() == lusIndex) {
|
|
foundMapping = true;
|
|
lusDeviceIndiciesWithMappings.push_back(
|
|
std::pair<Ship::ShipDeviceIndex, bool>(lusIndex, mapping->PhysicalDeviceIsConnected()));
|
|
break;
|
|
}
|
|
}
|
|
if (foundMapping) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (auto [lusIndex, connected] : lusDeviceIndiciesWithMappings) {
|
|
auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
|
|
auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
|
|
GetButtonColorsForShipDeviceIndex(lusIndex, buttonColor, buttonHoveredColor);
|
|
ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
|
|
ImGui::SameLine();
|
|
if (lusIndex == Ship::ShipDeviceIndex::Keyboard) {
|
|
ImGui::SmallButton(ICON_FA_KEYBOARD_O);
|
|
} else {
|
|
ImGui::SmallButton(connected ? ICON_FA_GAMEPAD : ICON_FA_CHAIN_BROKEN);
|
|
}
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopStyleColor();
|
|
}
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawRumbleDeviceIcons(uint8_t portIndex) {
|
|
std::set<Ship::ShipDeviceIndex> allLusDeviceIndices;
|
|
for (auto [lusIndex, mapping] : Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetDeviceIndexMappingManager()
|
|
->GetAllDeviceIndexMappingsFromConfig()) {
|
|
allLusDeviceIndices.insert(lusIndex);
|
|
}
|
|
|
|
std::vector<std::pair<Ship::ShipDeviceIndex, bool>> lusDeviceIndiciesWithMappings;
|
|
for (auto lusIndex : allLusDeviceIndices) {
|
|
if (Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetControllerByPort(portIndex)
|
|
->GetRumble()
|
|
->HasMappingsForShipDeviceIndex(lusIndex)) {
|
|
for (auto [id, mapping] : Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetControllerByPort(portIndex)
|
|
->GetRumble()
|
|
->GetAllRumbleMappings()) {
|
|
if (mapping->GetShipDeviceIndex() == lusIndex) {
|
|
lusDeviceIndiciesWithMappings.push_back(
|
|
std::pair<Ship::ShipDeviceIndex, bool>(lusIndex, mapping->PhysicalDeviceIsConnected()));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (auto [lusIndex, connected] : lusDeviceIndiciesWithMappings) {
|
|
auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
|
|
auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
|
|
GetButtonColorsForShipDeviceIndex(lusIndex, buttonColor, buttonHoveredColor);
|
|
ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
|
|
ImGui::SameLine();
|
|
ImGui::SmallButton(connected ? ICON_FA_GAMEPAD : ICON_FA_CHAIN_BROKEN);
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopStyleColor();
|
|
}
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawGyroDeviceIcons(uint8_t portIndex) {
|
|
auto mapping =
|
|
Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->GetGyro()->GetGyroMapping();
|
|
if (mapping == nullptr) {
|
|
return;
|
|
}
|
|
|
|
auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
|
|
auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
|
|
GetButtonColorsForShipDeviceIndex(mapping->GetShipDeviceIndex(), buttonColor, buttonHoveredColor);
|
|
ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
|
|
ImGui::SameLine();
|
|
ImGui::SmallButton(mapping->PhysicalDeviceIsConnected() ? ICON_FA_GAMEPAD : ICON_FA_CHAIN_BROKEN);
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopStyleColor();
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawLEDDeviceIcons(uint8_t portIndex) {
|
|
std::set<Ship::ShipDeviceIndex> allLusDeviceIndices;
|
|
for (auto [lusIndex, mapping] : Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetDeviceIndexMappingManager()
|
|
->GetAllDeviceIndexMappingsFromConfig()) {
|
|
allLusDeviceIndices.insert(lusIndex);
|
|
}
|
|
|
|
std::vector<std::pair<Ship::ShipDeviceIndex, bool>> lusDeviceIndiciesWithMappings;
|
|
for (auto lusIndex : allLusDeviceIndices) {
|
|
if (Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetControllerByPort(portIndex)
|
|
->GetRumble()
|
|
->HasMappingsForShipDeviceIndex(lusIndex)) {
|
|
for (auto [id, mapping] : Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetControllerByPort(portIndex)
|
|
->GetLED()
|
|
->GetAllLEDMappings()) {
|
|
if (mapping->GetShipDeviceIndex() == lusIndex) {
|
|
lusDeviceIndiciesWithMappings.push_back(
|
|
std::pair<Ship::ShipDeviceIndex, bool>(lusIndex, mapping->PhysicalDeviceIsConnected()));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (auto [lusIndex, connected] : lusDeviceIndiciesWithMappings) {
|
|
auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
|
|
auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
|
|
GetButtonColorsForShipDeviceIndex(lusIndex, buttonColor, buttonHoveredColor);
|
|
ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
|
|
ImGui::SameLine();
|
|
ImGui::SmallButton(connected ? ICON_FA_GAMEPAD : ICON_FA_CHAIN_BROKEN);
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopStyleColor();
|
|
}
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawDeviceVisibilityButtons() {
|
|
std::map<Ship::ShipDeviceIndex, std::pair<std::string, int32_t>> indexMappings;
|
|
for (auto [lusIndex, mapping] : Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetDeviceIndexMappingManager()
|
|
->GetAllDeviceIndexMappingsFromConfig()) {
|
|
auto sdlIndexMapping = std::static_pointer_cast<Ship::ShipDeviceIndexToSDLDeviceIndexMapping>(mapping);
|
|
if (sdlIndexMapping == nullptr) {
|
|
continue;
|
|
}
|
|
|
|
indexMappings[lusIndex] = { sdlIndexMapping->GetSDLControllerName(), -1 };
|
|
}
|
|
|
|
for (auto [lusIndex, mapping] :
|
|
Ship::Context::GetInstance()->GetControlDeck()->GetDeviceIndexMappingManager()->GetAllDeviceIndexMappings()) {
|
|
auto sdlIndexMapping = std::static_pointer_cast<Ship::ShipDeviceIndexToSDLDeviceIndexMapping>(mapping);
|
|
if (sdlIndexMapping == nullptr) {
|
|
continue;
|
|
}
|
|
|
|
indexMappings[lusIndex] = { sdlIndexMapping->GetSDLControllerName(), sdlIndexMapping->GetSDLDeviceIndex() };
|
|
}
|
|
|
|
auto keyboardButtonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
|
|
auto keyboardButtonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
|
|
GetButtonColorsForShipDeviceIndex(Ship::ShipDeviceIndex::Keyboard, keyboardButtonColor, keyboardButtonHoveredColor);
|
|
ImGui::PushStyleColor(ImGuiCol_Button, keyboardButtonColor);
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, keyboardButtonHoveredColor);
|
|
bool keyboardVisible = mDeviceIndexVisiblity[Ship::ShipDeviceIndex::Keyboard];
|
|
if (ImGui::Button(StringHelper::Sprintf("%s %s Keyboard", keyboardVisible ? ICON_FA_EYE : ICON_FA_EYE_SLASH,
|
|
ICON_FA_KEYBOARD_O)
|
|
.c_str())) {
|
|
mDeviceIndexVisiblity[Ship::ShipDeviceIndex::Keyboard] = !keyboardVisible;
|
|
}
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopStyleColor();
|
|
|
|
for (auto [lusIndex, info] : indexMappings) {
|
|
auto [name, sdlIndex] = info;
|
|
bool connected = sdlIndex != -1;
|
|
|
|
auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
|
|
auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
|
|
GetButtonColorsForShipDeviceIndex(lusIndex, buttonColor, buttonHoveredColor);
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
|
|
bool visible = mDeviceIndexVisiblity[lusIndex];
|
|
if (ImGui::Button(
|
|
StringHelper::Sprintf("%s %s %s (%s)", visible ? ICON_FA_EYE : ICON_FA_EYE_SLASH,
|
|
connected ? ICON_FA_GAMEPAD : ICON_FA_CHAIN_BROKEN, name.c_str(),
|
|
connected ? StringHelper::Sprintf("SDL %d", sdlIndex).c_str() : "Disconnected")
|
|
.c_str())) {
|
|
mDeviceIndexVisiblity[lusIndex] = !visible;
|
|
}
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopStyleColor();
|
|
}
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawClearAllButton(uint8_t portIndex) {
|
|
if (ImGui::Button("Clear All", ImGui::CalcTextSize("Clear All") * 2)) {
|
|
ImGui::OpenPopup("Clear All##clearAllPopup");
|
|
}
|
|
if (ImGui::BeginPopupModal("Clear All##clearAllPopup", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
|
|
ImGui::Text("This will clear all mappings for port %d.\n\nContinue?", portIndex + 1);
|
|
if (ImGui::Button("Cancel")) {
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
if (ImGui::Button("Clear All")) {
|
|
Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->ClearAllMappings();
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::EndPopup();
|
|
}
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawPortTab(uint8_t portIndex) {
|
|
if (ImGui::BeginTabItem(StringHelper::Sprintf("Port %d###port%d", portIndex + 1, portIndex).c_str())) {
|
|
DrawPortTabContents(portIndex);
|
|
ImGui::EndTabItem();
|
|
}
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawPortTabContents(uint8_t portIndex) {
|
|
DrawClearAllButton(portIndex);
|
|
DrawSetDefaultsButton(portIndex);
|
|
if (!Ship::Context::GetInstance()->GetControlDeck()->IsSinglePlayerMappingMode()) {
|
|
ImGui::SameLine();
|
|
if (ImGui::Button("Reorder controllers")) {
|
|
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Controller Reordering")->Show();
|
|
}
|
|
}
|
|
DrawDeviceVisibilityButtons();
|
|
|
|
UpdateBitmaskToMappingIds(portIndex);
|
|
UpdateStickDirectionToMappingIds(portIndex);
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.133f, 0.133f, 0.133f, 1.0f));
|
|
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
|
|
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
|
|
|
|
if (ImGui::CollapsingHeader("Buttons", NULL, ImGuiTreeNodeFlags_DefaultOpen)) {
|
|
DrawButtonDeviceIcons(portIndex, mButtonsBitmasks);
|
|
DrawButtonLine("A", portIndex, BTN_A, CHIP_COLOR_N64_BLUE);
|
|
DrawButtonLine("B", portIndex, BTN_B, CHIP_COLOR_N64_GREEN);
|
|
DrawButtonLine("Start", portIndex, BTN_START, CHIP_COLOR_N64_RED);
|
|
DrawButtonLine("L", portIndex, BTN_L);
|
|
DrawButtonLine("R", portIndex, BTN_R);
|
|
DrawButtonLine("Z", portIndex, BTN_Z);
|
|
DrawButtonLine(StringHelper::Sprintf("C %s", ICON_FA_ARROW_UP).c_str(), portIndex, BTN_CUP,
|
|
CHIP_COLOR_N64_YELLOW);
|
|
DrawButtonLine(StringHelper::Sprintf("C %s", ICON_FA_ARROW_DOWN).c_str(), portIndex, BTN_CDOWN,
|
|
CHIP_COLOR_N64_YELLOW);
|
|
DrawButtonLine(StringHelper::Sprintf("C %s", ICON_FA_ARROW_LEFT).c_str(), portIndex, BTN_CLEFT,
|
|
CHIP_COLOR_N64_YELLOW);
|
|
DrawButtonLine(StringHelper::Sprintf("C %s", ICON_FA_ARROW_RIGHT).c_str(), portIndex, BTN_CRIGHT,
|
|
CHIP_COLOR_N64_YELLOW);
|
|
} else {
|
|
DrawButtonDeviceIcons(portIndex, mButtonsBitmasks);
|
|
}
|
|
|
|
if (ImGui::CollapsingHeader("D-Pad", NULL, ImGuiTreeNodeFlags_DefaultOpen)) {
|
|
DrawButtonDeviceIcons(portIndex, mDpadBitmasks);
|
|
DrawButtonLine(StringHelper::Sprintf("%s", ICON_FA_ARROW_UP).c_str(), portIndex, BTN_DUP);
|
|
DrawButtonLine(StringHelper::Sprintf("%s", ICON_FA_ARROW_DOWN).c_str(), portIndex, BTN_DDOWN);
|
|
DrawButtonLine(StringHelper::Sprintf("%s", ICON_FA_ARROW_LEFT).c_str(), portIndex, BTN_DLEFT);
|
|
DrawButtonLine(StringHelper::Sprintf("%s", ICON_FA_ARROW_RIGHT).c_str(), portIndex, BTN_DRIGHT);
|
|
} else {
|
|
DrawButtonDeviceIcons(portIndex, mDpadBitmasks);
|
|
}
|
|
|
|
if (ImGui::CollapsingHeader("Analog Stick", NULL, ImGuiTreeNodeFlags_DefaultOpen)) {
|
|
DrawAnalogStickDeviceIcons(portIndex, Ship::LEFT_STICK);
|
|
DrawStickSection(portIndex, Ship::LEFT, 0);
|
|
} else {
|
|
DrawAnalogStickDeviceIcons(portIndex, Ship::LEFT_STICK);
|
|
}
|
|
|
|
if (ImGui::CollapsingHeader("Additional (\"Right\") Stick")) {
|
|
DrawAnalogStickDeviceIcons(portIndex, Ship::RIGHT_STICK);
|
|
DrawStickSection(portIndex, Ship::RIGHT, 1, CHIP_COLOR_N64_YELLOW);
|
|
} else {
|
|
DrawAnalogStickDeviceIcons(portIndex, Ship::RIGHT_STICK);
|
|
}
|
|
|
|
if (ImGui::CollapsingHeader("Rumble")) {
|
|
DrawRumbleDeviceIcons(portIndex);
|
|
DrawRumbleSection(portIndex);
|
|
} else {
|
|
DrawRumbleDeviceIcons(portIndex);
|
|
}
|
|
|
|
if (ImGui::CollapsingHeader("Gyro")) {
|
|
DrawGyroDeviceIcons(portIndex);
|
|
DrawGyroSection(portIndex);
|
|
} else {
|
|
DrawGyroDeviceIcons(portIndex);
|
|
}
|
|
|
|
if (ImGui::CollapsingHeader("LEDs")) {
|
|
DrawLEDDeviceIcons(portIndex);
|
|
DrawLEDSection(portIndex);
|
|
} else {
|
|
DrawLEDDeviceIcons(portIndex);
|
|
}
|
|
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopStyleColor();
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) {
|
|
ImGui::SameLine();
|
|
auto popupId = StringHelper::Sprintf("setDefaultsPopup##%d", portIndex);
|
|
if (ImGui::Button(StringHelper::Sprintf("Set Defaults##%d", portIndex).c_str(),
|
|
ImVec2(ImGui::CalcTextSize("Set Defaults") * 2))) {
|
|
ImGui::OpenPopup(popupId.c_str());
|
|
}
|
|
|
|
if (ImGui::BeginPopup(popupId.c_str())) {
|
|
std::map<Ship::ShipDeviceIndex, std::pair<std::string, int32_t>> indexMappings;
|
|
for (auto [lusIndex, mapping] : Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetDeviceIndexMappingManager()
|
|
->GetAllDeviceIndexMappings()) {
|
|
auto sdlIndexMapping = std::static_pointer_cast<Ship::ShipDeviceIndexToSDLDeviceIndexMapping>(mapping);
|
|
if (sdlIndexMapping == nullptr) {
|
|
continue;
|
|
}
|
|
|
|
indexMappings[lusIndex] = { sdlIndexMapping->GetSDLControllerName(), sdlIndexMapping->GetSDLDeviceIndex() };
|
|
}
|
|
|
|
bool shouldClose = false;
|
|
ImGui::PushStyleColor(ImGuiCol_Button, BUTTON_COLOR_KEYBOARD_BEIGE);
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, BUTTON_COLOR_KEYBOARD_BEIGE_HOVERED);
|
|
if (ImGui::Button(StringHelper::Sprintf("%s Keyboard", ICON_FA_KEYBOARD_O).c_str())) {
|
|
ImGui::OpenPopup("Set Defaults for Keyboard");
|
|
}
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopStyleColor();
|
|
if (ImGui::BeginPopupModal("Set Defaults for Keyboard", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
|
|
ImGui::Text("This will clear all existing mappings for\nKeyboard on port %d.\n\nContinue?", portIndex + 1);
|
|
if (ImGui::Button("Cancel")) {
|
|
shouldClose = true;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
if (ImGui::Button("Set defaults")) {
|
|
Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetControllerByPort(portIndex)
|
|
->ClearAllMappingsForDevice(Ship::ShipDeviceIndex::Keyboard);
|
|
Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->AddDefaultMappings(
|
|
Ship::ShipDeviceIndex::Keyboard);
|
|
shouldClose = true;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::EndPopup();
|
|
}
|
|
for (auto [lusIndex, info] : indexMappings) {
|
|
auto [name, sdlIndex] = info;
|
|
|
|
auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
|
|
auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
|
|
GetButtonColorsForShipDeviceIndex(lusIndex, buttonColor, buttonHoveredColor);
|
|
ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
|
|
if (ImGui::Button(StringHelper::Sprintf("%s %s (%s)", ICON_FA_GAMEPAD, name.c_str(),
|
|
StringHelper::Sprintf("SDL %d", sdlIndex).c_str())
|
|
.c_str())) {
|
|
ImGui::OpenPopup(StringHelper::Sprintf("Set Defaults for %s", name.c_str()).c_str());
|
|
}
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopStyleColor();
|
|
if (ImGui::BeginPopupModal(StringHelper::Sprintf("Set Defaults for %s", name.c_str()).c_str(), NULL,
|
|
ImGuiWindowFlags_AlwaysAutoResize)) {
|
|
ImGui::Text("This will clear all existing mappings for\n%s (SDL %d) on port %d.\n\nContinue?",
|
|
name.c_str(), sdlIndex, portIndex + 1);
|
|
if (ImGui::Button("Cancel")) {
|
|
shouldClose = true;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
if (ImGui::Button("Set defaults")) {
|
|
Ship::Context::GetInstance()
|
|
->GetControlDeck()
|
|
->GetControllerByPort(portIndex)
|
|
->ClearAllMappingsForDevice(lusIndex);
|
|
Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->AddDefaultMappings(
|
|
lusIndex);
|
|
shouldClose = true;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::EndPopup();
|
|
}
|
|
}
|
|
|
|
if (ImGui::Button("Cancel") || shouldClose) {
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
|
|
ImGui::EndPopup();
|
|
}
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawFullContents() {
|
|
ImGui::BeginTabBar("##ControllerConfigPortTabs");
|
|
for (uint8_t i = 0; i < 4; i++) {
|
|
DrawPortTab(i);
|
|
}
|
|
ImGui::EndTabBar();
|
|
}
|
|
|
|
void BenInputEditorWindow::DrawElement() {
|
|
DrawFullContents();
|
|
}
|