mirror of https://github.com/PCSX2/pcsx2.git
Pad: Jogcon and Negcon emulation
This commit is contained in:
parent
ed9b82097d
commit
129be9dfe4
|
@ -112,6 +112,14 @@ void ControllerBindingWidget::onTypeChanged()
|
|||
{
|
||||
m_bindings_widget = ControllerBindingWidget_Guitar::createInstance(this);
|
||||
}
|
||||
else if (cinfo->type == Pad::ControllerType::Jogcon)
|
||||
{
|
||||
m_bindings_widget = ControllerBindingWidget_Jogcon::createInstance(this);
|
||||
}
|
||||
else if (cinfo->type == Pad::ControllerType::Negcon)
|
||||
{
|
||||
m_bindings_widget = ControllerBindingWidget_Negcon::createInstance(this);
|
||||
}
|
||||
else if (cinfo->type == Pad::ControllerType::Popn)
|
||||
{
|
||||
m_bindings_widget = ControllerBindingWidget_Popn::createInstance(this);
|
||||
|
@ -907,6 +915,48 @@ ControllerBindingWidget_Base* ControllerBindingWidget_Guitar::createInstance(Con
|
|||
return new ControllerBindingWidget_Guitar(parent);
|
||||
}
|
||||
|
||||
ControllerBindingWidget_Jogcon::ControllerBindingWidget_Jogcon(ControllerBindingWidget* parent)
|
||||
: ControllerBindingWidget_Base(parent)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
initBindingWidgets();
|
||||
}
|
||||
|
||||
ControllerBindingWidget_Jogcon::~ControllerBindingWidget_Jogcon()
|
||||
{
|
||||
}
|
||||
|
||||
QIcon ControllerBindingWidget_Jogcon::getIcon() const
|
||||
{
|
||||
return QIcon::fromTheme("controller-line");
|
||||
}
|
||||
|
||||
ControllerBindingWidget_Base* ControllerBindingWidget_Jogcon::createInstance(ControllerBindingWidget* parent)
|
||||
{
|
||||
return new ControllerBindingWidget_Jogcon(parent);
|
||||
}
|
||||
|
||||
ControllerBindingWidget_Negcon::ControllerBindingWidget_Negcon(ControllerBindingWidget* parent)
|
||||
: ControllerBindingWidget_Base(parent)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
initBindingWidgets();
|
||||
}
|
||||
|
||||
ControllerBindingWidget_Negcon::~ControllerBindingWidget_Negcon()
|
||||
{
|
||||
}
|
||||
|
||||
QIcon ControllerBindingWidget_Negcon::getIcon() const
|
||||
{
|
||||
return QIcon::fromTheme("controller-line");
|
||||
}
|
||||
|
||||
ControllerBindingWidget_Base* ControllerBindingWidget_Negcon::createInstance(ControllerBindingWidget* parent)
|
||||
{
|
||||
return new ControllerBindingWidget_Negcon(parent);
|
||||
}
|
||||
|
||||
ControllerBindingWidget_Popn::ControllerBindingWidget_Popn(ControllerBindingWidget* parent)
|
||||
: ControllerBindingWidget_Base(parent)
|
||||
{
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include "ui_ControllerBindingWidget.h"
|
||||
#include "ui_ControllerBindingWidget_DualShock2.h"
|
||||
#include "ui_ControllerBindingWidget_Guitar.h"
|
||||
#include "ui_ControllerBindingWidget_Jogcon.h"
|
||||
#include "ui_ControllerBindingWidget_Negcon.h"
|
||||
#include "ui_ControllerBindingWidget_Popn.h"
|
||||
#include "ui_ControllerMacroWidget.h"
|
||||
#include "ui_ControllerMacroEditWidget.h"
|
||||
|
@ -200,6 +202,38 @@ private:
|
|||
Ui::ControllerBindingWidget_Guitar m_ui;
|
||||
};
|
||||
|
||||
class ControllerBindingWidget_Jogcon final : public ControllerBindingWidget_Base
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ControllerBindingWidget_Jogcon(ControllerBindingWidget* parent);
|
||||
~ControllerBindingWidget_Jogcon();
|
||||
|
||||
QIcon getIcon() const override;
|
||||
|
||||
static ControllerBindingWidget_Base* createInstance(ControllerBindingWidget* parent);
|
||||
|
||||
private:
|
||||
Ui::ControllerBindingWidget_Jogcon m_ui;
|
||||
};
|
||||
|
||||
class ControllerBindingWidget_Negcon final : public ControllerBindingWidget_Base
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ControllerBindingWidget_Negcon(ControllerBindingWidget* parent);
|
||||
~ControllerBindingWidget_Negcon();
|
||||
|
||||
QIcon getIcon() const override;
|
||||
|
||||
static ControllerBindingWidget_Base* createInstance(ControllerBindingWidget* parent);
|
||||
|
||||
private:
|
||||
Ui::ControllerBindingWidget_Negcon m_ui;
|
||||
};
|
||||
|
||||
class ControllerBindingWidget_Popn final : public ControllerBindingWidget_Base
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
|
@ -0,0 +1,832 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ControllerBindingWidget_Jogcon</class>
|
||||
<widget class="QWidget" name="ControllerBindingWidget_Jogcon">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1232</width>
|
||||
<height>644</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>1100</width>
|
||||
<height>500</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_0">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0" rowspan="3">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_0">
|
||||
<property name="title">
|
||||
<string>D-Pad</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_1">
|
||||
<item row="3" column="1" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_1">
|
||||
<property name="title">
|
||||
<string>Down</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Down">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Left</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Left">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Up</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Up">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="title">
|
||||
<string>Right</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Right">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_29">
|
||||
<property name="title">
|
||||
<string>Large Motor</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_30">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputVibrationBindingWidget" name="LargeMotor">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<property name="title">
|
||||
<string>L2</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_7">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="L2">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QGroupBox" name="groupBox_6">
|
||||
<property name="title">
|
||||
<string>R2</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_8">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="R2">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_7">
|
||||
<property name="title">
|
||||
<string>L1</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_9">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="L1">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QGroupBox" name="groupBox_8">
|
||||
<property name="title">
|
||||
<string>R1</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_10">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="R1">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QGroupBox" name="groupBox_9">
|
||||
<property name="title">
|
||||
<string>Start</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_11">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Start">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QGroupBox" name="groupBox_10">
|
||||
<property name="title">
|
||||
<string>Select</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_12">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Select">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="2" rowspan="3">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_11">
|
||||
<property name="title">
|
||||
<string>Face Buttons</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_13">
|
||||
<item row="3" column="1" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_12">
|
||||
<property name="title">
|
||||
<string>Cross</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_14">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Cross">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_13">
|
||||
<property name="title">
|
||||
<string>Square</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_15">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Square">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_14">
|
||||
<property name="title">
|
||||
<string>Triangle</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_16">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Triangle">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_15">
|
||||
<property name="title">
|
||||
<string>Circle</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_17">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Circle">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_32">
|
||||
<property name="title">
|
||||
<string>Small Motor</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_31">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputVibrationBindingWidget" name="SmallMotor">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>266</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../resources/resources.qrc">:/images/Jogcon.svg</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<layout class="QGridLayout" name="gridLayout_18">
|
||||
<item row="0" column="1">
|
||||
<widget class="QGroupBox" name="groupBox_16">
|
||||
<property name="title">
|
||||
<string>Dial Left</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_19">
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="DialLeft">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QGroupBox" name="groupBox_17">
|
||||
<property name="title">
|
||||
<string>Dial Right</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_20">
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="DialRight">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="4">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>InputBindingWidget</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>Settings/InputBindingWidget.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>InputVibrationBindingWidget</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>Settings/InputBindingWidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../resources/resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -0,0 +1,730 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ControllerBindingWidget_Negcon</class>
|
||||
<widget class="QWidget" name="ControllerBindingWidget_Negcon">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1232</width>
|
||||
<height>644</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>1100</width>
|
||||
<height>500</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_35">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0" rowspan="3">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_1">
|
||||
<property name="title">
|
||||
<string>D-Pad</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="3" column="1" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<property name="title">
|
||||
<string>Down</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Down">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Left</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Left">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Up</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_1">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Up">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="title">
|
||||
<string>Right</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Right">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_29">
|
||||
<property name="title">
|
||||
<string>Large Motor</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_30">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputVibrationBindingWidget" name="LargeMotor">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QGridLayout" name="gridLayout_27">
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_22">
|
||||
<property name="title">
|
||||
<string>L</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_22">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="L">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QGroupBox" name="groupBox_26">
|
||||
<property name="title">
|
||||
<string>Start</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_26">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Start">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QGroupBox" name="groupBox_24">
|
||||
<property name="title">
|
||||
<string>R</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_24">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="R">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="2" rowspan="3">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_16">
|
||||
<property name="title">
|
||||
<string>Face Buttons</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_16">
|
||||
<item row="3" column="1" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_17">
|
||||
<property name="title">
|
||||
<string>I</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_17">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="I">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_18">
|
||||
<property name="title">
|
||||
<string>II</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_18">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="II">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_19">
|
||||
<property name="title">
|
||||
<string>B</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_19">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="B">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_20">
|
||||
<property name="title">
|
||||
<string>A</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_20">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="A">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_32">
|
||||
<property name="title">
|
||||
<string>Small Motor</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_31">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputVibrationBindingWidget" name="SmallMotor">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>266</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../resources/resources.qrc">:/images/Negcon.svg</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<layout class="QGridLayout" name="gridLayout_32">
|
||||
<item row="0" column="1">
|
||||
<widget class="QGroupBox" name="groupBox_31">
|
||||
<property name="title">
|
||||
<string>Twist Left</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_33">
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="TwistLeft">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QGroupBox" name="groupBox_6">
|
||||
<property name="title">
|
||||
<string>Twist Right</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="TwistRight">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="4">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>InputBindingWidget</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>Settings/InputBindingWidget.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>InputVibrationBindingWidget</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>Settings/InputBindingWidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../resources/resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -200,6 +200,8 @@
|
|||
<file>images/DualShock_2.svg</file>
|
||||
<file>images/GT_Force.svg</file>
|
||||
<file>images/Guitar.svg</file>
|
||||
<file>images/Jogcon.svg</file>
|
||||
<file>images/Negcon.svg</file>
|
||||
<file>images/Popn.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -436,6 +436,8 @@ set(pcsx2PADSources
|
|||
SIO/Pad/PadBase.cpp
|
||||
SIO/Pad/PadDualshock2.cpp
|
||||
SIO/Pad/PadGuitar.cpp
|
||||
SIO/Pad/PadJogcon.cpp
|
||||
SIO/Pad/PadNegcon.cpp
|
||||
SIO/Pad/PadPopn.cpp
|
||||
SIO/Pad/PadNotConnected.cpp
|
||||
)
|
||||
|
@ -444,6 +446,8 @@ set(pcsx2PADHeaders
|
|||
SIO/Pad/PadBase.h
|
||||
SIO/Pad/PadDualshock2.h
|
||||
SIO/Pad/PadGuitar.h
|
||||
SIO/Pad/PadJogcon.h
|
||||
SIO/Pad/PadNegcon.h
|
||||
SIO/Pad/PadPopn.h
|
||||
SIO/Pad/PadNotConnected.h
|
||||
SIO/Pad/PadTypes.h
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include "SIO/Pad/Pad.h"
|
||||
#include "SIO/Pad/PadDualshock2.h"
|
||||
#include "SIO/Pad/PadGuitar.h"
|
||||
#include "SIO/Pad/PadJogcon.h"
|
||||
#include "SIO/Pad/PadNegcon.h"
|
||||
#include "SIO/Pad/PadPopn.h"
|
||||
#include "SIO/Pad/PadNotConnected.h"
|
||||
#include "SIO/Sio.h"
|
||||
|
@ -255,6 +257,8 @@ static const Pad::ControllerInfo* s_controller_info[] = {
|
|||
&PadNotConnected::ControllerInfo,
|
||||
&PadDualshock2::ControllerInfo,
|
||||
&PadGuitar::ControllerInfo,
|
||||
&PadJogcon::ControllerInfo,
|
||||
&PadNegcon::ControllerInfo,
|
||||
&PadPopn::ControllerInfo,
|
||||
};
|
||||
|
||||
|
@ -495,6 +499,12 @@ PadBase* Pad::CreatePad(u8 unifiedSlot, ControllerType controllerType, size_t ej
|
|||
case ControllerType::Guitar:
|
||||
s_controllers[unifiedSlot] = std::make_unique<PadGuitar>(unifiedSlot, ejectTicks);
|
||||
break;
|
||||
case ControllerType::Jogcon:
|
||||
s_controllers[unifiedSlot] = std::make_unique<PadJogcon>(unifiedSlot, ejectTicks);
|
||||
break;
|
||||
case ControllerType::Negcon:
|
||||
s_controllers[unifiedSlot] = std::make_unique<PadNegcon>(unifiedSlot, ejectTicks);
|
||||
break;
|
||||
case ControllerType::Popn:
|
||||
s_controllers[unifiedSlot] = std::make_unique<PadPopn>(unifiedSlot, ejectTicks);
|
||||
break;
|
||||
|
|
|
@ -0,0 +1,531 @@
|
|||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "SIO/Pad/PadJogcon.h"
|
||||
#include "SIO/Pad/Pad.h"
|
||||
#include "SIO/Sio.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "Input/InputManager.h"
|
||||
#include "Host.h"
|
||||
|
||||
#include "IconsPromptFont.h"
|
||||
|
||||
static const InputBindingInfo s_bindings[] = {
|
||||
// clang-format off
|
||||
{"Up", TRANSLATE_NOOP("Pad", "D-Pad Up"), ICON_PF_DPAD_UP, InputBindingInfo::Type::Button, PadJogcon::Inputs::PAD_UP, GenericInputBinding::DPadUp},
|
||||
{"Right", TRANSLATE_NOOP("Pad", "D-Pad Right"), ICON_PF_DPAD_RIGHT, InputBindingInfo::Type::Button, PadJogcon::Inputs::PAD_RIGHT, GenericInputBinding::DPadRight},
|
||||
{"Down", TRANSLATE_NOOP("Pad", "D-Pad Down"), ICON_PF_DPAD_DOWN, InputBindingInfo::Type::Button, PadJogcon::Inputs::PAD_DOWN, GenericInputBinding::DPadDown},
|
||||
{"Left", TRANSLATE_NOOP("Pad", "D-Pad Left"), ICON_PF_DPAD_LEFT, InputBindingInfo::Type::Button, PadJogcon::Inputs::PAD_LEFT, GenericInputBinding::DPadLeft},
|
||||
{"Triangle", TRANSLATE_NOOP("Pad", "Triangle"), ICON_PF_BUTTON_TRIANGLE, InputBindingInfo::Type::Button, PadJogcon::Inputs::PAD_TRIANGLE, GenericInputBinding::Triangle},
|
||||
{"Circle", TRANSLATE_NOOP("Pad", "Circle"), ICON_PF_BUTTON_CIRCLE, InputBindingInfo::Type::Button, PadJogcon::Inputs::PAD_CIRCLE, GenericInputBinding::Circle},
|
||||
{"Cross", TRANSLATE_NOOP("Pad", "Cross"), ICON_PF_BUTTON_CROSS, InputBindingInfo::Type::Button, PadJogcon::Inputs::PAD_CROSS, GenericInputBinding::Cross},
|
||||
{"Square", TRANSLATE_NOOP("Pad", "Square"), ICON_PF_BUTTON_SQUARE, InputBindingInfo::Type::Button, PadJogcon::Inputs::PAD_SQUARE, GenericInputBinding::Square},
|
||||
{"Select", TRANSLATE_NOOP("Pad", "Select"), ICON_PF_SELECT_SHARE, InputBindingInfo::Type::Button, PadJogcon::Inputs::PAD_SELECT, GenericInputBinding::Select},
|
||||
{"Start", TRANSLATE_NOOP("Pad", "Start"), ICON_PF_START, InputBindingInfo::Type::Button, PadJogcon::Inputs::PAD_START, GenericInputBinding::Start},
|
||||
{"L1", TRANSLATE_NOOP("Pad", "L1 (Left Bumper)"), ICON_PF_LEFT_SHOULDER_L1, InputBindingInfo::Type::Button, PadJogcon::Inputs::PAD_L1, GenericInputBinding::L1},
|
||||
{"L2", TRANSLATE_NOOP("Pad", "L2 (Left Trigger)"), ICON_PF_LEFT_TRIGGER_L2, InputBindingInfo::Type::Button, PadJogcon::Inputs::PAD_L2, GenericInputBinding::L2},
|
||||
{"R1", TRANSLATE_NOOP("Pad", "R1 (Right Bumper)"), ICON_PF_RIGHT_SHOULDER_R1, InputBindingInfo::Type::Button, PadJogcon::Inputs::PAD_R1, GenericInputBinding::R1},
|
||||
{"R2", TRANSLATE_NOOP("Pad", "R2 (Right Trigger)"), ICON_PF_RIGHT_TRIGGER_R2, InputBindingInfo::Type::Button, PadJogcon::Inputs::PAD_R2, GenericInputBinding::R2},
|
||||
{}, {}, {}, {},
|
||||
{"DialLeft", TRANSLATE_NOOP("Pad", "Dial (Left)"), nullptr, InputBindingInfo::Type::HalfAxis, PadJogcon::Inputs::PAD_DIAL_LEFT, GenericInputBinding::LeftStickLeft},
|
||||
{"DialRight", TRANSLATE_NOOP("Pad", "Dial (Right)"), nullptr, InputBindingInfo::Type::HalfAxis, PadJogcon::Inputs::PAD_DIAL_RIGHT, GenericInputBinding::LeftStickRight},
|
||||
{"LargeMotor", TRANSLATE_NOOP("Pad", "Large (Low Frequency) Motor"), nullptr, InputBindingInfo::Type::Motor, 0, GenericInputBinding::LargeMotor},
|
||||
{"SmallMotor", TRANSLATE_NOOP("Pad", "Small (High Frequency) Motor"), nullptr, InputBindingInfo::Type::Motor, 0, GenericInputBinding::SmallMotor},
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
static const SettingInfo s_settings[] = {
|
||||
{SettingInfo::Type::Float, "Deadzone", TRANSLATE_NOOP("Pad", "Dial Deadzone"),
|
||||
TRANSLATE_NOOP("Pad", "Sets the dial deadzone. Inputs below this value will not be sent to the PS2."),
|
||||
"0.00", "0.00", "1.00", "0.01", TRANSLATE_NOOP("Pad", "%.0f%%"), nullptr, nullptr, 100.0f},
|
||||
{SettingInfo::Type::Float, "AxisScale", TRANSLATE_NOOP("Pad", "Dial Sensitivity"),
|
||||
TRANSLATE_NOOP("Pad", "Sets the dial scaling factor."),
|
||||
"1.0", "0.01", "2.00", "0.01", TRANSLATE_NOOP("Pad", "%.0f%%"), nullptr, nullptr, 100.0f},
|
||||
};
|
||||
|
||||
const Pad::ControllerInfo PadJogcon::ControllerInfo = {Pad::ControllerType::Jogcon, "Jogcon",
|
||||
TRANSLATE_NOOP("Pad", "Jogcon"), ICON_PF_GAMEPAD_ALT, s_bindings, s_settings, Pad::VibrationCapabilities::LargeSmallMotors};
|
||||
|
||||
void PadJogcon::ConfigLog()
|
||||
{
|
||||
const auto [port, slot] = sioConvertPadToPortAndSlot(unifiedSlot);
|
||||
|
||||
// AL: Analog Light (is it turned on right now)
|
||||
// AB: Analog Button (is it useable or is it locked in its current state)
|
||||
Console.WriteLn(fmt::format("[Pad] Jogcon Config Finished - P{0}/S{1} - AL: {2} - AB: {3}",
|
||||
port + 1,
|
||||
slot + 1,
|
||||
(this->analogLight ? "On" : "Off"),
|
||||
(this->analogLocked ? "Locked" : "Usable")));
|
||||
}
|
||||
|
||||
u8 PadJogcon::Mystery(u8 commandByte)
|
||||
{
|
||||
switch (this->commandBytesReceived)
|
||||
{
|
||||
case 5:
|
||||
return 0x02;
|
||||
case 8:
|
||||
return 0x5a;
|
||||
default:
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
u8 PadJogcon::ButtonQuery(u8 commandByte)
|
||||
{
|
||||
switch (this->commandBytesReceived)
|
||||
{
|
||||
case 3:
|
||||
case 4:
|
||||
return 0xff;
|
||||
case 5:
|
||||
return 0x03;
|
||||
case 8:
|
||||
return 0x5a;
|
||||
default:
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
u8 PadJogcon::Poll(u8 commandByte)
|
||||
{
|
||||
const u32 buttons = GetButtons();
|
||||
u8 largeMotor = 0x00;
|
||||
u8 smallMotor = 0x00;
|
||||
|
||||
switch (this->commandBytesReceived)
|
||||
{
|
||||
case 3:
|
||||
this->vibrationMotors[0] = commandByte;
|
||||
return (buttons >> 8) & 0xff;
|
||||
case 4:
|
||||
this->vibrationMotors[1] = commandByte;
|
||||
|
||||
// Apply the vibration mapping to the motors
|
||||
switch (this->largeMotorLastConfig)
|
||||
{
|
||||
case 0x00:
|
||||
largeMotor = this->vibrationMotors[0];
|
||||
break;
|
||||
case 0x01:
|
||||
largeMotor = this->vibrationMotors[1];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Small motor on the controller is only controlled by the LSB.
|
||||
// Any value can be sent by the software, but only odd numbers
|
||||
// (LSB set) will turn on the motor.
|
||||
switch (this->smallMotorLastConfig)
|
||||
{
|
||||
case 0x00:
|
||||
smallMotor = this->vibrationMotors[0] & 0x01;
|
||||
break;
|
||||
case 0x01:
|
||||
smallMotor = this->vibrationMotors[1] & 0x01;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Order is reversed here - SetPadVibrationIntensity takes large motor first, then small. PS2 orders small motor first, large motor second.
|
||||
InputManager::SetPadVibrationIntensity(this->unifiedSlot,
|
||||
std::min(static_cast<float>(largeMotor) * GetVibrationScale(1) * (1.0f / 255.0f), 1.0f),
|
||||
// Small motor on the PS2 is either on full power or zero power, it has no variable speed. If the game supplies any value here at all,
|
||||
// the pad in turn supplies full power to the motor, or no power at all if zero.
|
||||
std::min(static_cast<float>((smallMotor ? 0xff : 0)) * GetVibrationScale(0) * (1.0f / 255.0f), 1.0f));
|
||||
|
||||
return buttons & 0xff;
|
||||
case 5:
|
||||
return dial & 0xff;
|
||||
case 6:
|
||||
return (dial >> 8) & 0xff;
|
||||
case 7:
|
||||
{
|
||||
const u8 b7 = this->dial > this->lastdial ? 1 : this->dial < this->lastdial ? 2 : 0;
|
||||
this->lastdial = this->dial;
|
||||
return b7;
|
||||
}
|
||||
case 8:
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
Console.Warning("%s(%02X) Did not reach a valid return path! Returning zero as a failsafe!", __FUNCTION__, commandByte);
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
u8 PadJogcon::Config(u8 commandByte)
|
||||
{
|
||||
if (this->commandBytesReceived == 3)
|
||||
{
|
||||
if (commandByte)
|
||||
{
|
||||
if (!this->isInConfig)
|
||||
{
|
||||
this->isInConfig = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Warning("%s(%02X) Unexpected enter while already in config mode", __FUNCTION__, commandByte);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->isInConfig)
|
||||
{
|
||||
this->isInConfig = false;
|
||||
this->ConfigLog();
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Warning("%s(%02X) Unexpected exit while not in config mode", __FUNCTION__, commandByte);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
// Changes the mode of the controller between digital and analog, and adjusts the analog LED accordingly.
|
||||
u8 PadJogcon::ModeSwitch(u8 commandByte)
|
||||
{
|
||||
switch (this->commandBytesReceived)
|
||||
{
|
||||
case 3:
|
||||
this->analogLight = commandByte;
|
||||
|
||||
if (this->analogLight)
|
||||
{
|
||||
this->currentMode = Pad::Mode::ANALOG;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->currentMode = Pad::Mode::DIGITAL;
|
||||
}
|
||||
|
||||
break;
|
||||
case 4:
|
||||
this->analogLocked = (commandByte == 0x03);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
u8 PadJogcon::StatusInfo(u8 commandByte)
|
||||
{
|
||||
switch (this->commandBytesReceived)
|
||||
{
|
||||
case 3:
|
||||
return static_cast<u8>(Pad::PhysicalType::STANDARD);
|
||||
case 4:
|
||||
return 0x02;
|
||||
case 5:
|
||||
return this->analogLight;
|
||||
case 6:
|
||||
return 0x02;
|
||||
case 7:
|
||||
return 0x01;
|
||||
default:
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
u8 PadJogcon::Constant1(u8 commandByte)
|
||||
{
|
||||
switch (this->commandBytesReceived)
|
||||
{
|
||||
case 3:
|
||||
commandStage = (commandByte != 0);
|
||||
return 0x00;
|
||||
case 5:
|
||||
return 0x01;
|
||||
case 6:
|
||||
return (!commandStage ? 0x02 : 0x01);
|
||||
case 7:
|
||||
return (!commandStage ? 0x00 : 0x01);
|
||||
case 8:
|
||||
return (commandStage ? 0x0a : 0x14);
|
||||
default:
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
u8 PadJogcon::Constant2(u8 commandByte)
|
||||
{
|
||||
switch (this->commandBytesReceived)
|
||||
{
|
||||
case 5:
|
||||
return 0x02;
|
||||
case 7:
|
||||
return 0x01;
|
||||
default:
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
u8 PadJogcon::Constant3(u8 commandByte)
|
||||
{
|
||||
switch (this->commandBytesReceived)
|
||||
{
|
||||
case 3:
|
||||
commandStage = (commandByte != 0);
|
||||
return 0x00;
|
||||
case 6:
|
||||
return (!commandStage ? 0x04 : 0x07);
|
||||
default:
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
u8 PadJogcon::VibrationMap(u8 commandByte)
|
||||
{
|
||||
u8 ret = 0xff;
|
||||
|
||||
switch (commandBytesReceived)
|
||||
{
|
||||
case 3:
|
||||
ret = this->smallMotorLastConfig;
|
||||
this->smallMotorLastConfig = commandByte;
|
||||
return ret;
|
||||
case 4:
|
||||
ret = this->largeMotorLastConfig;
|
||||
this->largeMotorLastConfig = commandByte;
|
||||
return ret;
|
||||
case 8:
|
||||
return 0xff;
|
||||
default:
|
||||
return 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
PadJogcon::PadJogcon(u8 unifiedSlot, size_t ejectTicks)
|
||||
: PadBase(unifiedSlot, ejectTicks)
|
||||
{
|
||||
currentMode = Pad::Mode::PS1_JOGCON;
|
||||
}
|
||||
|
||||
PadJogcon::~PadJogcon() = default;
|
||||
|
||||
Pad::ControllerType PadJogcon::GetType() const
|
||||
{
|
||||
return Pad::ControllerType::Jogcon;
|
||||
}
|
||||
|
||||
const Pad::ControllerInfo& PadJogcon::GetInfo() const
|
||||
{
|
||||
return ControllerInfo;
|
||||
}
|
||||
|
||||
void PadJogcon::Set(u32 index, float value)
|
||||
{
|
||||
if (index > Inputs::LENGTH)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsAnalogKey(index))
|
||||
{
|
||||
const float dz_value = (this->dialDeadzone > 0.0f && value < this->dialDeadzone) ? 0.0f : value;
|
||||
this->rawInputs[index] = static_cast<u8>(std::clamp(dz_value * this->dialScale * 255.0f, 0.0f, 255.0f));
|
||||
|
||||
this->dial = this->rawInputs[Inputs::PAD_DIAL_RIGHT] != 0
|
||||
? this->rawInputs[Inputs::PAD_DIAL_RIGHT]
|
||||
: -this->rawInputs[Inputs::PAD_DIAL_LEFT];
|
||||
return;
|
||||
}
|
||||
|
||||
this->rawInputs[index] = static_cast<u8>(std::clamp(value * 255.0f, 0.0f, 255.0f));
|
||||
if (this->rawInputs[index] > 0.0f)
|
||||
{
|
||||
this->buttons &= ~(1u << bitmaskMapping[index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->buttons |= (1u << bitmaskMapping[index]);
|
||||
}
|
||||
}
|
||||
|
||||
void PadJogcon::SetRawAnalogs(const std::tuple<u8, u8> left, const std::tuple<u8, u8> right)
|
||||
{
|
||||
this->dial = (std::get<0>(left) << 8) | std::get<1>(left);
|
||||
}
|
||||
|
||||
void PadJogcon::SetRawPressureButton(u32 index, const std::tuple<bool, u8> value)
|
||||
{
|
||||
this->rawInputs[index] = std::get<1>(value);
|
||||
|
||||
if (std::get<0>(value))
|
||||
{
|
||||
this->buttons &= ~(1u << bitmaskMapping[index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->buttons |= (1u << bitmaskMapping[index]);
|
||||
}
|
||||
}
|
||||
|
||||
void PadJogcon::SetAxisScale(float deadzone, float scale)
|
||||
{
|
||||
this->dialDeadzone = deadzone;
|
||||
this->dialScale = scale;
|
||||
}
|
||||
|
||||
float PadJogcon::GetVibrationScale(u32 motor) const
|
||||
{
|
||||
return this->vibrationScale[motor];
|
||||
}
|
||||
|
||||
void PadJogcon::SetVibrationScale(u32 motor, float scale)
|
||||
{
|
||||
this->vibrationScale[motor] = scale;
|
||||
}
|
||||
|
||||
float PadJogcon::GetPressureModifier() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PadJogcon::SetPressureModifier(float mod)
|
||||
{
|
||||
}
|
||||
|
||||
void PadJogcon::SetButtonDeadzone(float deadzone)
|
||||
{
|
||||
}
|
||||
|
||||
void PadJogcon::SetAnalogInvertL(bool x, bool y)
|
||||
{
|
||||
}
|
||||
|
||||
void PadJogcon::SetAnalogInvertR(bool x, bool y)
|
||||
{
|
||||
}
|
||||
|
||||
float PadJogcon::GetEffectiveInput(u32 index) const
|
||||
{
|
||||
if (!IsAnalogKey(index))
|
||||
return GetRawInput(index);
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case Inputs::PAD_DIAL_LEFT:
|
||||
return (dial < 0) ? -(dial / 255.0f) : 0;
|
||||
|
||||
case Inputs::PAD_DIAL_RIGHT:
|
||||
return (dial > 0) ? (dial / 255.0f) : 0;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
u8 PadJogcon::GetRawInput(u32 index) const
|
||||
{
|
||||
return rawInputs[index];
|
||||
}
|
||||
|
||||
std::tuple<u8, u8> PadJogcon::GetRawLeftAnalog() const
|
||||
{
|
||||
return std::tuple<u8, u8>{(dial >> 8) & 0xff, dial & 0xff};
|
||||
}
|
||||
|
||||
std::tuple<u8, u8> PadJogcon::GetRawRightAnalog() const
|
||||
{
|
||||
return std::tuple<u8, u8>{0x7f, 0x7f};
|
||||
}
|
||||
|
||||
u32 PadJogcon::GetButtons() const
|
||||
{
|
||||
return buttons;
|
||||
}
|
||||
|
||||
u8 PadJogcon::GetPressure(u32 index) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool PadJogcon::Freeze(StateWrapper& sw)
|
||||
{
|
||||
if (!PadBase::Freeze(sw) || !sw.DoMarker("PadJogcon"))
|
||||
return false;
|
||||
|
||||
// Private PadJogcon members
|
||||
sw.Do(&analogLight);
|
||||
sw.Do(&analogLocked);
|
||||
sw.Do(&commandStage);
|
||||
sw.Do(&vibrationMotors);
|
||||
sw.Do(&smallMotorLastConfig);
|
||||
sw.Do(&largeMotorLastConfig);
|
||||
return !sw.HasError();
|
||||
}
|
||||
|
||||
u8 PadJogcon::SendCommandByte(u8 commandByte)
|
||||
{
|
||||
u8 ret = 0;
|
||||
|
||||
switch (this->commandBytesReceived)
|
||||
{
|
||||
case 0:
|
||||
ret = 0x00;
|
||||
break;
|
||||
case 1:
|
||||
this->currentCommand = static_cast<Pad::Command>(commandByte);
|
||||
|
||||
if (this->currentCommand != Pad::Command::POLL && this->currentCommand != Pad::Command::CONFIG && !this->isInConfig)
|
||||
{
|
||||
Console.Warning("%s(%02X) Config-only command was sent to a pad outside of config mode!", __FUNCTION__, commandByte);
|
||||
}
|
||||
|
||||
ret = this->isInConfig ? static_cast<u8>(Pad::Mode::CONFIG) : static_cast<u8>(this->currentMode);
|
||||
break;
|
||||
case 2:
|
||||
ret = 0x5a;
|
||||
break;
|
||||
default:
|
||||
switch (this->currentCommand)
|
||||
{
|
||||
case Pad::Command::MYSTERY:
|
||||
ret = Mystery(commandByte);
|
||||
break;
|
||||
case Pad::Command::BUTTON_QUERY:
|
||||
ret = ButtonQuery(commandByte);
|
||||
break;
|
||||
case Pad::Command::POLL:
|
||||
ret = Poll(commandByte);
|
||||
break;
|
||||
case Pad::Command::CONFIG:
|
||||
ret = Config(commandByte);
|
||||
break;
|
||||
case Pad::Command::MODE_SWITCH:
|
||||
ret = ModeSwitch(commandByte);
|
||||
break;
|
||||
case Pad::Command::STATUS_INFO:
|
||||
ret = StatusInfo(commandByte);
|
||||
break;
|
||||
case Pad::Command::CONST_1:
|
||||
ret = Constant1(commandByte);
|
||||
break;
|
||||
case Pad::Command::CONST_2:
|
||||
ret = Constant2(commandByte);
|
||||
break;
|
||||
case Pad::Command::CONST_3:
|
||||
ret = Constant3(commandByte);
|
||||
break;
|
||||
case Pad::Command::VIBRATION_MAP:
|
||||
ret = VibrationMap(commandByte);
|
||||
break;
|
||||
default:
|
||||
ret = 0x00;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this->commandBytesReceived++;
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "SIO/Pad/PadBase.h"
|
||||
|
||||
class PadJogcon final : public PadBase
|
||||
{
|
||||
public:
|
||||
enum Inputs
|
||||
{
|
||||
PAD_UP, // Directional pad up
|
||||
PAD_RIGHT, // Directional pad right
|
||||
PAD_DOWN, // Directional pad down
|
||||
PAD_LEFT, // Directional pad left
|
||||
PAD_TRIANGLE, // Triangle button
|
||||
PAD_CIRCLE, // Circle button
|
||||
PAD_CROSS, // Cross button
|
||||
PAD_SQUARE, // Square button
|
||||
PAD_SELECT, // Select button
|
||||
PAD_START, // Start button
|
||||
PAD_L1, // L1 button
|
||||
PAD_L2, // L2 button
|
||||
PAD_R1, // R1 button
|
||||
PAD_R2, // R2 button
|
||||
|
||||
// This workaround is necessary because InputRecorder doesn't support custom Pads beside DS2:
|
||||
// https://github.com/PCSX2/pcsx2/blob/ded55635c105c547756f5369b998297f602ada2f/pcsx2/Recording/PadData.cpp#L42-L61
|
||||
// We need to consider and avoid the DS2's indexes that aren't saved in InputRecorder
|
||||
// and we also have to use DS2's analog indexes for our analog axes.
|
||||
PADDING1, PADDING2, PADDING3, PADDING4,
|
||||
|
||||
PAD_DIAL_LEFT, // Dial (Left)
|
||||
PAD_DIAL_RIGHT, // Dial (Right)
|
||||
LENGTH,
|
||||
};
|
||||
|
||||
static constexpr u8 VIBRATION_MOTORS = 2;
|
||||
|
||||
private:
|
||||
u32 buttons = 0xffffffffu;
|
||||
s16 dial = 0x0000;
|
||||
s16 lastdial = 0x0000;
|
||||
|
||||
bool analogLight = false;
|
||||
bool analogLocked = false;
|
||||
bool commandStage = false;
|
||||
std::array<u8, VIBRATION_MOTORS> vibrationMotors = {};
|
||||
std::array<float, 2> vibrationScale = {1.0f, 1.0f};
|
||||
float dialDeadzone = 0.0f;
|
||||
float dialScale = 1.0f;
|
||||
// Used to store the last vibration mapping request the PS2 made for the small motor.
|
||||
u8 smallMotorLastConfig = 0xff;
|
||||
// Used to store the last vibration mapping request the PS2 made for the large motor.
|
||||
u8 largeMotorLastConfig = 0xff;
|
||||
|
||||
// Since we reordered the buttons for better UI, we need to remap them here.
|
||||
static constexpr std::array<u8, Inputs::LENGTH> bitmaskMapping = {{
|
||||
12, // PAD_UP
|
||||
13, // PAD_RIGHT
|
||||
14, // PAD_DOWN
|
||||
15, // PAD_LEFT
|
||||
4, // PAD_TRIANGLE
|
||||
5, // PAD_CIRCLE
|
||||
6, // PAD_CROSS
|
||||
7, // PAD_SQUARE
|
||||
8, // PAD_SELECT
|
||||
11, // PAD_START
|
||||
2, // PAD_L1
|
||||
0, // PAD_L2
|
||||
3, // PAD_R1
|
||||
1, // PAD_R2
|
||||
}};
|
||||
|
||||
void ConfigLog();
|
||||
|
||||
u8 Mystery(u8 commandByte);
|
||||
u8 ButtonQuery(u8 commandByte);
|
||||
u8 Poll(u8 commandByte);
|
||||
u8 Config(u8 commandByte);
|
||||
u8 ModeSwitch(u8 commandByte);
|
||||
u8 StatusInfo(u8 commandByte);
|
||||
u8 Constant1(u8 commandByte);
|
||||
u8 Constant2(u8 commandByte);
|
||||
u8 Constant3(u8 commandByte);
|
||||
u8 VibrationMap(u8 commandByte);
|
||||
|
||||
public:
|
||||
PadJogcon(u8 unifiedSlot, size_t ejectTicks);
|
||||
~PadJogcon() override;
|
||||
|
||||
static inline bool IsAnalogKey(int index)
|
||||
{
|
||||
return index == Inputs::PAD_DIAL_LEFT || index == Inputs::PAD_DIAL_RIGHT;
|
||||
}
|
||||
|
||||
Pad::ControllerType GetType() const override;
|
||||
const Pad::ControllerInfo& GetInfo() const override;
|
||||
void Set(u32 index, float value) override;
|
||||
void SetRawAnalogs(const std::tuple<u8, u8> left, const std::tuple<u8, u8> right) override;
|
||||
void SetRawPressureButton(u32 index, const std::tuple<bool, u8> value) override;
|
||||
void SetAxisScale(float deadzone, float scale) override;
|
||||
float GetVibrationScale(u32 motor) const override;
|
||||
void SetVibrationScale(u32 motor, float scale) override;
|
||||
float GetPressureModifier() const override;
|
||||
void SetPressureModifier(float mod) override;
|
||||
void SetButtonDeadzone(float deadzone) override;
|
||||
void SetAnalogInvertL(bool x, bool y) override;
|
||||
void SetAnalogInvertR(bool x, bool y) override;
|
||||
float GetEffectiveInput(u32 index) const override;
|
||||
u8 GetRawInput(u32 index) const override;
|
||||
std::tuple<u8, u8> GetRawLeftAnalog() const override;
|
||||
std::tuple<u8, u8> GetRawRightAnalog() const override;
|
||||
u32 GetButtons() const override;
|
||||
u8 GetPressure(u32 index) const override;
|
||||
|
||||
bool Freeze(StateWrapper& sw) override;
|
||||
|
||||
u8 SendCommandByte(u8 commandByte) override;
|
||||
|
||||
static const Pad::ControllerInfo ControllerInfo;
|
||||
};
|
|
@ -0,0 +1,549 @@
|
|||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "SIO/Pad/PadNegcon.h"
|
||||
#include "SIO/Pad/Pad.h"
|
||||
#include "SIO/Sio.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "Input/InputManager.h"
|
||||
#include "Host.h"
|
||||
|
||||
#include "IconsPromptFont.h"
|
||||
|
||||
static const InputBindingInfo s_bindings[] = {
|
||||
// clang-format off
|
||||
{"Up", TRANSLATE_NOOP("Pad", "D-Pad Up"), ICON_PF_DPAD_UP, InputBindingInfo::Type::Button, PadNegcon::Inputs::PAD_UP, GenericInputBinding::DPadUp},
|
||||
{"Right", TRANSLATE_NOOP("Pad", "D-Pad Right"), ICON_PF_DPAD_RIGHT, InputBindingInfo::Type::Button, PadNegcon::Inputs::PAD_RIGHT, GenericInputBinding::DPadRight},
|
||||
{"Down", TRANSLATE_NOOP("Pad", "D-Pad Down"), ICON_PF_DPAD_DOWN, InputBindingInfo::Type::Button, PadNegcon::Inputs::PAD_DOWN, GenericInputBinding::DPadDown},
|
||||
{"Left", TRANSLATE_NOOP("Pad", "D-Pad Left"), ICON_PF_DPAD_LEFT, InputBindingInfo::Type::Button, PadNegcon::Inputs::PAD_LEFT, GenericInputBinding::DPadLeft},
|
||||
{"B", TRANSLATE_NOOP("Pad", "B Button"), ICON_PF_BUTTON_B, InputBindingInfo::Type::Button, PadNegcon::Inputs::PAD_B, GenericInputBinding::Triangle},
|
||||
{"A", TRANSLATE_NOOP("Pad", "A Button"), ICON_PF_BUTTON_A, InputBindingInfo::Type::Button, PadNegcon::Inputs::PAD_A, GenericInputBinding::Circle},
|
||||
{"I", TRANSLATE_NOOP("Pad", "I Button"), nullptr, InputBindingInfo::Type::Button, PadNegcon::Inputs::PAD_I, GenericInputBinding::Cross},
|
||||
{"II", TRANSLATE_NOOP("Pad", "II Button"), nullptr, InputBindingInfo::Type::Button, PadNegcon::Inputs::PAD_II, GenericInputBinding::Square},
|
||||
{},
|
||||
{"Start", TRANSLATE_NOOP("Pad", "Start"), ICON_PF_START, InputBindingInfo::Type::Button, PadNegcon::Inputs::PAD_START, GenericInputBinding::Start},
|
||||
{"L", TRANSLATE_NOOP("Pad", "L (Left Bumper)"), ICON_PF_LEFT_SHOULDER_L1, InputBindingInfo::Type::Button, PadNegcon::Inputs::PAD_L, GenericInputBinding::L2},
|
||||
{"R", TRANSLATE_NOOP("Pad", "R (Right Bumper)"), ICON_PF_RIGHT_SHOULDER_R1, InputBindingInfo::Type::Button, PadNegcon::Inputs::PAD_R, GenericInputBinding::R2},
|
||||
{"TwistLeft", TRANSLATE_NOOP("Pad", "Twist (Left)"), nullptr, InputBindingInfo::Type::HalfAxis, PadNegcon::Inputs::PAD_TWIST_LEFT, GenericInputBinding::LeftStickLeft},
|
||||
{"TwistRight", TRANSLATE_NOOP("Pad", "Twist (Right)"), nullptr, InputBindingInfo::Type::HalfAxis, PadNegcon::Inputs::PAD_TWIST_RIGHT, GenericInputBinding::LeftStickRight},
|
||||
{"LargeMotor", TRANSLATE_NOOP("Pad", "Large (Low Frequency) Motor"), nullptr, InputBindingInfo::Type::Motor, 0, GenericInputBinding::LargeMotor},
|
||||
{"SmallMotor", TRANSLATE_NOOP("Pad", "Small (High Frequency) Motor"), nullptr, InputBindingInfo::Type::Motor, 0, GenericInputBinding::SmallMotor},
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
static const SettingInfo s_settings[] = {
|
||||
{SettingInfo::Type::Float, "Deadzone", TRANSLATE_NOOP("Pad", "Twist Deadzone"),
|
||||
TRANSLATE_NOOP("Pad", "Sets the twist deadzone. Inputs below this value will not be sent to the PS2."),
|
||||
"0.00", "0.00", "1.00", "0.01", "%.0f%%", nullptr, nullptr, 100.0f},
|
||||
{SettingInfo::Type::Float, "AxisScale", TRANSLATE_NOOP("Pad", "Twist Sensitivity"),
|
||||
TRANSLATE_NOOP("Pad", "Sets the twist scaling factor."),
|
||||
"1.0", "0.01", "2.00", "0.01", "%.0f%%", nullptr, nullptr, 100.0f},
|
||||
};
|
||||
|
||||
const Pad::ControllerInfo PadNegcon::ControllerInfo = {Pad::ControllerType::Negcon, "Negcon",
|
||||
TRANSLATE_NOOP("Pad", "Negcon"), ICON_PF_GAMEPAD_ALT, s_bindings, s_settings, Pad::VibrationCapabilities::LargeSmallMotors};
|
||||
|
||||
void PadNegcon::ConfigLog()
|
||||
{
|
||||
const auto [port, slot] = sioConvertPadToPortAndSlot(unifiedSlot);
|
||||
|
||||
// AL: Analog Light (is it turned on right now)
|
||||
// AB: Analog Button (is it useable or is it locked in its current state)
|
||||
Console.WriteLn(fmt::format("[Pad] Negcon Config Finished - P{0}/S{1} - AL: {2} - AB: {3}",
|
||||
port + 1,
|
||||
slot + 1,
|
||||
(this->analogLight ? "On" : "Off"),
|
||||
(this->analogLocked ? "Locked" : "Usable")));
|
||||
}
|
||||
|
||||
u8 PadNegcon::Mystery(u8 commandByte)
|
||||
{
|
||||
switch (this->commandBytesReceived)
|
||||
{
|
||||
case 5:
|
||||
return 0x02;
|
||||
case 8:
|
||||
return 0x5a;
|
||||
default:
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
u8 PadNegcon::ButtonQuery(u8 commandByte)
|
||||
{
|
||||
switch (this->commandBytesReceived)
|
||||
{
|
||||
case 3:
|
||||
case 4:
|
||||
return 0xff;
|
||||
case 5:
|
||||
return 0x03;
|
||||
case 8:
|
||||
return 0x5a;
|
||||
default:
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
u8 PadNegcon::Poll(u8 commandByte)
|
||||
{
|
||||
const u32 buttons = GetButtons();
|
||||
u8 largeMotor = 0x00;
|
||||
u8 smallMotor = 0x00;
|
||||
|
||||
switch (this->commandBytesReceived)
|
||||
{
|
||||
case 3:
|
||||
this->vibrationMotors[0] = commandByte;
|
||||
return (buttons >> 8) & 0xff;
|
||||
case 4:
|
||||
this->vibrationMotors[1] = commandByte;
|
||||
|
||||
// Apply the vibration mapping to the motors
|
||||
switch (this->largeMotorLastConfig)
|
||||
{
|
||||
case 0x00:
|
||||
largeMotor = this->vibrationMotors[0];
|
||||
break;
|
||||
case 0x01:
|
||||
largeMotor = this->vibrationMotors[1];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Small motor on the controller is only controlled by the LSB.
|
||||
// Any value can be sent by the software, but only odd numbers
|
||||
// (LSB set) will turn on the motor.
|
||||
switch (this->smallMotorLastConfig)
|
||||
{
|
||||
case 0x00:
|
||||
smallMotor = this->vibrationMotors[0] & 0x01;
|
||||
break;
|
||||
case 0x01:
|
||||
smallMotor = this->vibrationMotors[1] & 0x01;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Order is reversed here - SetPadVibrationIntensity takes large motor first, then small. PS2 orders small motor first, large motor second.
|
||||
InputManager::SetPadVibrationIntensity(this->unifiedSlot,
|
||||
std::min(static_cast<float>(largeMotor) * GetVibrationScale(1) * (1.0f / 255.0f), 1.0f),
|
||||
// Small motor on the PS2 is either on full power or zero power, it has no variable speed. If the game supplies any value here at all,
|
||||
// the pad in turn supplies full power to the motor, or no power at all if zero.
|
||||
std::min(static_cast<float>((smallMotor ? 0xff : 0)) * GetVibrationScale(0) * (1.0f / 255.0f), 1.0f));
|
||||
|
||||
return buttons & 0xff;
|
||||
case 5:
|
||||
return this->analogs.twist;
|
||||
case 6:
|
||||
return this->analogs.i;
|
||||
case 7:
|
||||
return this->analogs.ii;
|
||||
case 8:
|
||||
return this->analogs.l;
|
||||
}
|
||||
|
||||
Console.Warning("%s(%02X) Did not reach a valid return path! Returning zero as a failsafe!", __FUNCTION__, commandByte);
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
u8 PadNegcon::Config(u8 commandByte)
|
||||
{
|
||||
if (this->commandBytesReceived == 3)
|
||||
{
|
||||
if (commandByte)
|
||||
{
|
||||
if (!this->isInConfig)
|
||||
{
|
||||
this->isInConfig = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Warning("%s(%02X) Unexpected enter while already in config mode", __FUNCTION__, commandByte);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->isInConfig)
|
||||
{
|
||||
this->isInConfig = false;
|
||||
this->ConfigLog();
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Warning("%s(%02X) Unexpected exit while not in config mode", __FUNCTION__, commandByte);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
// Changes the mode of the controller between digital and analog, and adjusts the analog LED accordingly.
|
||||
u8 PadNegcon::ModeSwitch(u8 commandByte)
|
||||
{
|
||||
switch (this->commandBytesReceived)
|
||||
{
|
||||
case 3:
|
||||
this->analogLight = commandByte;
|
||||
|
||||
if (this->analogLight)
|
||||
{
|
||||
this->currentMode = Pad::Mode::ANALOG;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->currentMode = Pad::Mode::DIGITAL;
|
||||
}
|
||||
|
||||
break;
|
||||
case 4:
|
||||
this->analogLocked = (commandByte == 0x03);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
u8 PadNegcon::StatusInfo(u8 commandByte)
|
||||
{
|
||||
switch (this->commandBytesReceived)
|
||||
{
|
||||
case 3:
|
||||
return static_cast<u8>(Pad::PhysicalType::STANDARD);
|
||||
case 4:
|
||||
return 0x02;
|
||||
case 5:
|
||||
return this->analogLight;
|
||||
case 6:
|
||||
return 0x02;
|
||||
case 7:
|
||||
return 0x01;
|
||||
default:
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
u8 PadNegcon::Constant1(u8 commandByte)
|
||||
{
|
||||
switch (this->commandBytesReceived)
|
||||
{
|
||||
case 3:
|
||||
commandStage = (commandByte != 0);
|
||||
return 0x00;
|
||||
case 5:
|
||||
return 0x01;
|
||||
case 6:
|
||||
return (!commandStage ? 0x02 : 0x01);
|
||||
case 7:
|
||||
return (!commandStage ? 0x00 : 0x01);
|
||||
case 8:
|
||||
return (commandStage ? 0x0a : 0x14);
|
||||
default:
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
u8 PadNegcon::Constant2(u8 commandByte)
|
||||
{
|
||||
switch (this->commandBytesReceived)
|
||||
{
|
||||
case 5:
|
||||
return 0x02;
|
||||
case 7:
|
||||
return 0x01;
|
||||
default:
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
u8 PadNegcon::Constant3(u8 commandByte)
|
||||
{
|
||||
switch (this->commandBytesReceived)
|
||||
{
|
||||
case 3:
|
||||
commandStage = (commandByte != 0);
|
||||
return 0x00;
|
||||
case 6:
|
||||
return (!commandStage ? 0x04 : 0x07);
|
||||
default:
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
u8 PadNegcon::VibrationMap(u8 commandByte)
|
||||
{
|
||||
u8 ret = 0xff;
|
||||
|
||||
switch (commandBytesReceived)
|
||||
{
|
||||
case 3:
|
||||
ret = this->smallMotorLastConfig;
|
||||
this->smallMotorLastConfig = commandByte;
|
||||
return ret;
|
||||
case 4:
|
||||
ret = this->largeMotorLastConfig;
|
||||
this->largeMotorLastConfig = commandByte;
|
||||
return ret;
|
||||
case 8:
|
||||
return 0xff;
|
||||
default:
|
||||
return 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
PadNegcon::PadNegcon(u8 unifiedSlot, size_t ejectTicks)
|
||||
: PadBase(unifiedSlot, ejectTicks)
|
||||
{
|
||||
currentMode = Pad::Mode::NEGCON;
|
||||
}
|
||||
|
||||
PadNegcon::~PadNegcon() = default;
|
||||
|
||||
Pad::ControllerType PadNegcon::GetType() const
|
||||
{
|
||||
return Pad::ControllerType::Negcon;
|
||||
}
|
||||
|
||||
const Pad::ControllerInfo& PadNegcon::GetInfo() const
|
||||
{
|
||||
return ControllerInfo;
|
||||
}
|
||||
|
||||
void PadNegcon::Set(u32 index, float value)
|
||||
{
|
||||
if (index > Inputs::LENGTH)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsTwistKey(index))
|
||||
{
|
||||
const float dz_value = (this->twistDeadzone > 0.0f && value < this->twistDeadzone) ? 0.0f : value;
|
||||
this->rawInputs[index] = static_cast<u8>(std::clamp(dz_value * this->twistScale * 255.0f, 0.0f, 255.0f));
|
||||
|
||||
this->analogs.twist = this->rawInputs[Inputs::PAD_TWIST_RIGHT] != 0 ? 127u + (this->rawInputs[Inputs::PAD_TWIST_RIGHT] + 1u) / 2u : 127u - (this->rawInputs[Inputs::PAD_TWIST_LEFT] - 1u) / 2;
|
||||
return;
|
||||
}
|
||||
|
||||
this->rawInputs[index] = static_cast<u8>(std::clamp(value * 255.0f, 0.0f, 255.0f));
|
||||
if (IsAnalogKey(index))
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case PAD_I:
|
||||
this->analogs.i = this->rawInputs[index];
|
||||
break;
|
||||
case PAD_II:
|
||||
this->analogs.ii = this->rawInputs[index];
|
||||
break;
|
||||
case PAD_L:
|
||||
this->analogs.l = this->rawInputs[index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->rawInputs[index] > 0.0f)
|
||||
{
|
||||
this->buttons &= ~(1u << bitmaskMapping[index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->buttons |= (1u << bitmaskMapping[index]);
|
||||
}
|
||||
}
|
||||
|
||||
void PadNegcon::SetRawAnalogs(const std::tuple<u8, u8> left, const std::tuple<u8, u8> right)
|
||||
{
|
||||
this->analogs.i = std::get<0>(left);
|
||||
this->analogs.ii = std::get<1>(left);
|
||||
this->analogs.l = std::get<0>(right);
|
||||
this->analogs.twist = std::get<1>(right);
|
||||
}
|
||||
|
||||
void PadNegcon::SetRawPressureButton(u32 index, const std::tuple<bool, u8> value)
|
||||
{
|
||||
this->rawInputs[index] = std::get<1>(value);
|
||||
if (std::get<0>(value))
|
||||
{
|
||||
this->buttons &= ~(1u << bitmaskMapping[index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->buttons |= (1u << bitmaskMapping[index]);
|
||||
}
|
||||
}
|
||||
|
||||
void PadNegcon::SetAxisScale(float deadzone, float scale)
|
||||
{
|
||||
this->twistDeadzone = deadzone;
|
||||
this->twistScale = scale;
|
||||
}
|
||||
|
||||
float PadNegcon::GetVibrationScale(u32 motor) const
|
||||
{
|
||||
return this->vibrationScale[motor];
|
||||
}
|
||||
|
||||
void PadNegcon::SetVibrationScale(u32 motor, float scale)
|
||||
{
|
||||
this->vibrationScale[motor] = scale;
|
||||
}
|
||||
|
||||
float PadNegcon::GetPressureModifier() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PadNegcon::SetPressureModifier(float mod)
|
||||
{
|
||||
}
|
||||
|
||||
void PadNegcon::SetButtonDeadzone(float deadzone)
|
||||
{
|
||||
}
|
||||
|
||||
void PadNegcon::SetAnalogInvertL(bool x, bool y)
|
||||
{
|
||||
}
|
||||
|
||||
void PadNegcon::SetAnalogInvertR(bool x, bool y)
|
||||
{
|
||||
}
|
||||
|
||||
float PadNegcon::GetEffectiveInput(u32 index) const
|
||||
{
|
||||
if (!IsAnalogKey(index))
|
||||
return GetRawInput(index);
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case Inputs::PAD_I:
|
||||
return analogs.i;
|
||||
|
||||
case Inputs::PAD_II:
|
||||
return analogs.ii;
|
||||
|
||||
case Inputs::PAD_L:
|
||||
return analogs.l;
|
||||
|
||||
case Inputs::PAD_TWIST_LEFT:
|
||||
return (analogs.twist < 127) ? ((127 - analogs.twist) / 127.0f) : 0;
|
||||
|
||||
case Inputs::PAD_TWIST_RIGHT:
|
||||
return (analogs.twist > 128) ? ((analogs.twist - 128) / 127.0f) : 0;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
u8 PadNegcon::GetRawInput(u32 index) const
|
||||
{
|
||||
return rawInputs[index];
|
||||
}
|
||||
|
||||
std::tuple<u8, u8> PadNegcon::GetRawLeftAnalog() const
|
||||
{
|
||||
return std::tuple<u8, u8>{analogs.i, analogs.ii};
|
||||
}
|
||||
|
||||
std::tuple<u8, u8> PadNegcon::GetRawRightAnalog() const
|
||||
{
|
||||
return std::tuple<u8, u8>{analogs.l, analogs.twist};
|
||||
}
|
||||
|
||||
u32 PadNegcon::GetButtons() const
|
||||
{
|
||||
return buttons;
|
||||
}
|
||||
|
||||
u8 PadNegcon::GetPressure(u32 index) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool PadNegcon::Freeze(StateWrapper& sw)
|
||||
{
|
||||
if (!PadBase::Freeze(sw) || !sw.DoMarker("PadNegcon"))
|
||||
return false;
|
||||
|
||||
// Private PadNegcon members
|
||||
sw.Do(&analogLight);
|
||||
sw.Do(&analogLocked);
|
||||
sw.Do(&commandStage);
|
||||
sw.Do(&vibrationMotors);
|
||||
sw.Do(&smallMotorLastConfig);
|
||||
sw.Do(&largeMotorLastConfig);
|
||||
return !sw.HasError();
|
||||
}
|
||||
|
||||
u8 PadNegcon::SendCommandByte(u8 commandByte)
|
||||
{
|
||||
u8 ret = 0;
|
||||
|
||||
switch (this->commandBytesReceived)
|
||||
{
|
||||
case 0:
|
||||
ret = 0x00;
|
||||
break;
|
||||
case 1:
|
||||
this->currentCommand = static_cast<Pad::Command>(commandByte);
|
||||
|
||||
if (this->currentCommand != Pad::Command::POLL && this->currentCommand != Pad::Command::CONFIG && !this->isInConfig)
|
||||
{
|
||||
Console.Warning("%s(%02X) Config-only command was sent to a pad outside of config mode!", __FUNCTION__, commandByte);
|
||||
}
|
||||
|
||||
ret = this->isInConfig ? static_cast<u8>(Pad::Mode::CONFIG) : static_cast<u8>(this->currentMode);
|
||||
break;
|
||||
case 2:
|
||||
ret = 0x5a;
|
||||
break;
|
||||
default:
|
||||
switch (this->currentCommand)
|
||||
{
|
||||
case Pad::Command::MYSTERY:
|
||||
ret = Mystery(commandByte);
|
||||
break;
|
||||
case Pad::Command::BUTTON_QUERY:
|
||||
ret = ButtonQuery(commandByte);
|
||||
break;
|
||||
case Pad::Command::POLL:
|
||||
ret = Poll(commandByte);
|
||||
break;
|
||||
case Pad::Command::CONFIG:
|
||||
ret = Config(commandByte);
|
||||
break;
|
||||
case Pad::Command::MODE_SWITCH:
|
||||
ret = ModeSwitch(commandByte);
|
||||
break;
|
||||
case Pad::Command::STATUS_INFO:
|
||||
ret = StatusInfo(commandByte);
|
||||
break;
|
||||
case Pad::Command::CONST_1:
|
||||
ret = Constant1(commandByte);
|
||||
break;
|
||||
case Pad::Command::CONST_2:
|
||||
ret = Constant2(commandByte);
|
||||
break;
|
||||
case Pad::Command::CONST_3:
|
||||
ret = Constant3(commandByte);
|
||||
break;
|
||||
case Pad::Command::VIBRATION_MAP:
|
||||
ret = VibrationMap(commandByte);
|
||||
break;
|
||||
default:
|
||||
ret = 0x00;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this->commandBytesReceived++;
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "SIO/Pad/PadBase.h"
|
||||
|
||||
class PadNegcon final : public PadBase
|
||||
{
|
||||
public:
|
||||
enum Inputs
|
||||
{
|
||||
PAD_UP, // Directional pad up
|
||||
PAD_RIGHT, // Directional pad right
|
||||
PAD_DOWN, // Directional pad down
|
||||
PAD_LEFT, // Directional pad left
|
||||
PAD_B, // B button
|
||||
PAD_A, // A button
|
||||
PAD_I, // I button
|
||||
PAD_II, // II button
|
||||
|
||||
// This workaround is necessary because InputRecorder doesn't support custom Pads beside DS2:
|
||||
// https://github.com/PCSX2/pcsx2/blob/ded55635c105c547756f5369b998297f602ada2f/pcsx2/Recording/PadData.cpp#L42-L61
|
||||
// We need to consider and avoid the DS2's indexes that aren't saved in InputRecorder
|
||||
// and we also have to use DS2's analog indexes for our analog axes.
|
||||
PAD_PADDING1,
|
||||
|
||||
PAD_START, // Start button
|
||||
PAD_L, // L button
|
||||
PAD_R, // R button
|
||||
PAD_TWIST_LEFT, // Twist (Left)
|
||||
PAD_TWIST_RIGHT, // Twist (Right)
|
||||
LENGTH,
|
||||
};
|
||||
|
||||
static constexpr u8 VIBRATION_MOTORS = 2;
|
||||
|
||||
private:
|
||||
struct Analogs
|
||||
{
|
||||
u8 i = 0x00;
|
||||
u8 ii = 0x00;
|
||||
u8 l = 0x00;
|
||||
u8 twist = 0x80;
|
||||
};
|
||||
|
||||
u32 buttons = 0xffffffffu;
|
||||
Analogs analogs;
|
||||
|
||||
bool analogLight = false;
|
||||
bool analogLocked = false;
|
||||
bool commandStage = false;
|
||||
std::array<u8, VIBRATION_MOTORS> vibrationMotors = {};
|
||||
std::array<float, 2> vibrationScale = {1.0f, 1.0f};
|
||||
float twistDeadzone = 0.0f;
|
||||
float twistScale = 1.0f;
|
||||
// Used to store the last vibration mapping request the PS2 made for the small motor.
|
||||
u8 smallMotorLastConfig = 0xff;
|
||||
// Used to store the last vibration mapping request the PS2 made for the large motor.
|
||||
u8 largeMotorLastConfig = 0xff;
|
||||
|
||||
// Since we reordered the buttons for better UI, we need to remap them here.
|
||||
static constexpr std::array<u8, Inputs::LENGTH> bitmaskMapping = {{
|
||||
12, // PAD_UP
|
||||
13, // PAD_RIGHT
|
||||
14, // PAD_DOWN
|
||||
15, // PAD_LEFT
|
||||
4, // PAD_B
|
||||
5, // PAD_A
|
||||
6, // PAD_I
|
||||
7, // PAD_II
|
||||
0,
|
||||
11, // PAD_START
|
||||
2, // PAD_L
|
||||
3, // PAD_R
|
||||
}};
|
||||
|
||||
void ConfigLog();
|
||||
|
||||
u8 Mystery(u8 commandByte);
|
||||
u8 ButtonQuery(u8 commandByte);
|
||||
u8 Poll(u8 commandByte);
|
||||
u8 Config(u8 commandByte);
|
||||
u8 ModeSwitch(u8 commandByte);
|
||||
u8 StatusInfo(u8 commandByte);
|
||||
u8 Constant1(u8 commandByte);
|
||||
u8 Constant2(u8 commandByte);
|
||||
u8 Constant3(u8 commandByte);
|
||||
u8 VibrationMap(u8 commandByte);
|
||||
|
||||
public:
|
||||
PadNegcon(u8 unifiedSlot, size_t ejectTicks);
|
||||
~PadNegcon() override;
|
||||
|
||||
static inline bool IsAnalogKey(int index)
|
||||
{
|
||||
return index == Inputs::PAD_I
|
||||
|| index == Inputs::PAD_II
|
||||
|| index == Inputs::PAD_L
|
||||
|| index == Inputs::PAD_TWIST_LEFT
|
||||
|| index == Inputs::PAD_TWIST_RIGHT;
|
||||
}
|
||||
|
||||
static inline bool IsTwistKey(int index)
|
||||
{
|
||||
return index == Inputs::PAD_TWIST_LEFT
|
||||
|| index == Inputs::PAD_TWIST_RIGHT;
|
||||
}
|
||||
|
||||
Pad::ControllerType GetType() const override;
|
||||
const Pad::ControllerInfo& GetInfo() const override;
|
||||
void Set(u32 index, float value) override;
|
||||
void SetRawAnalogs(const std::tuple<u8, u8> left, const std::tuple<u8, u8> right) override;
|
||||
void SetRawPressureButton(u32 index, const std::tuple<bool, u8> value) override;
|
||||
void SetAxisScale(float deadzone, float scale) override;
|
||||
float GetVibrationScale(u32 motor) const override;
|
||||
void SetVibrationScale(u32 motor, float scale) override;
|
||||
float GetPressureModifier() const override;
|
||||
void SetPressureModifier(float mod) override;
|
||||
void SetButtonDeadzone(float deadzone) override;
|
||||
void SetAnalogInvertL(bool x, bool y) override;
|
||||
void SetAnalogInvertR(bool x, bool y) override;
|
||||
float GetEffectiveInput(u32 index) const override;
|
||||
u8 GetRawInput(u32 index) const override;
|
||||
std::tuple<u8, u8> GetRawLeftAnalog() const override;
|
||||
std::tuple<u8, u8> GetRawRightAnalog() const override;
|
||||
u32 GetButtons() const override;
|
||||
u8 GetPressure(u32 index) const override;
|
||||
|
||||
bool Freeze(StateWrapper& sw) override;
|
||||
|
||||
u8 SendCommandByte(u8 commandByte) override;
|
||||
|
||||
static const Pad::ControllerInfo ControllerInfo;
|
||||
};
|
|
@ -64,6 +64,8 @@ namespace Pad
|
|||
NotConnected,
|
||||
DualShock2,
|
||||
Guitar,
|
||||
Jogcon,
|
||||
Negcon,
|
||||
Popn,
|
||||
Count
|
||||
};
|
||||
|
|
|
@ -291,6 +291,8 @@
|
|||
<ClCompile Include="SIO\Pad\Pad.cpp" />
|
||||
<ClCompile Include="SIO\Pad\PadDualshock2.cpp" />
|
||||
<ClCompile Include="SIO\Pad\PadGuitar.cpp" />
|
||||
<ClCompile Include="SIO\Pad\PadJogcon.cpp" />
|
||||
<ClCompile Include="SIO\Pad\PadNegcon.cpp" />
|
||||
<ClCompile Include="SIO\Pad\PadNotConnected.cpp" />
|
||||
<ClCompile Include="SIO\Pad\PadPopn.cpp" />
|
||||
<ClCompile Include="SIO\Sio.cpp" />
|
||||
|
@ -733,6 +735,8 @@
|
|||
<ClInclude Include="SIO\Pad\Pad.h" />
|
||||
<ClInclude Include="SIO\Pad\PadDualshock2.h" />
|
||||
<ClInclude Include="SIO\Pad\PadGuitar.h" />
|
||||
<ClInclude Include="SIO\Pad\PadJogcon.h" />
|
||||
<ClInclude Include="SIO\Pad\PadNegcon.h" />
|
||||
<ClInclude Include="SIO\Pad\PadNotConnected.h" />
|
||||
<ClInclude Include="SIO\Pad\PadPopn.h" />
|
||||
<ClInclude Include="SIO\Pad\PadTypes.h" />
|
||||
|
|
|
@ -1431,6 +1431,12 @@
|
|||
<ClCompile Include="arm64\RecStubs.cpp">
|
||||
<Filter>System\Ps2\EmotionEngine\EE\Dynarec\arm64</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SIO\Pad\PadJogcon.cpp">
|
||||
<Filter>System\Ps2\Iop\SIO\PAD</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SIO\Pad\PadNegcon.cpp">
|
||||
<Filter>System\Ps2\Iop\SIO\PAD</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Patch.h">
|
||||
|
@ -2372,6 +2378,12 @@
|
|||
<ClInclude Include="arm64\AsmHelpers.h">
|
||||
<Filter>Tools\arm64</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SIO\Pad\PadJogcon.h">
|
||||
<Filter>System\Ps2\Iop\SIO\PAD</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SIO\Pad\PadNegcon.h">
|
||||
<Filter>System\Ps2\Iop\SIO\PAD</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuildStep Include="rdebug\deci2.h">
|
||||
|
|
Loading…
Reference in New Issue