mirror of
https://github.com/azahar-emu/azahar.git
synced 2026-06-06 02:33:44 -04:00
Merge 36118a1409 into 379649dbce
This commit is contained in:
commit
7a636915f0
25 changed files with 663 additions and 106 deletions
|
|
@ -33,6 +33,7 @@ const std::array<int, Settings::NativeButton::NumButtons> QtConfig::default_butt
|
||||||
Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_T, Qt::Key_G,
|
Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_T, Qt::Key_G,
|
||||||
Qt::Key_F, Qt::Key_H, Qt::Key_Q, Qt::Key_W, Qt::Key_M, Qt::Key_N,
|
Qt::Key_F, Qt::Key_H, Qt::Key_Q, Qt::Key_W, Qt::Key_M, Qt::Key_N,
|
||||||
Qt::Key_O, Qt::Key_P, Qt::Key_1, Qt::Key_2, Qt::Key_B, Qt::Key_V,
|
Qt::Key_O, Qt::Key_P, Qt::Key_1, Qt::Key_2, Qt::Key_B, Qt::Key_V,
|
||||||
|
Qt::Key_U,
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> QtConfig::default_analogs{{
|
const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> QtConfig::default_analogs{{
|
||||||
|
|
|
||||||
|
|
@ -171,7 +171,7 @@ ConfigureInput::ConfigureInput(Core::System& _system, QWidget* parent)
|
||||||
ui->buttonDpadUp, ui->buttonDpadDown, ui->buttonDpadLeft, ui->buttonDpadRight,
|
ui->buttonDpadUp, ui->buttonDpadDown, ui->buttonDpadLeft, ui->buttonDpadRight,
|
||||||
ui->buttonL, ui->buttonR, ui->buttonStart, ui->buttonSelect,
|
ui->buttonL, ui->buttonR, ui->buttonStart, ui->buttonSelect,
|
||||||
ui->buttonDebug, ui->buttonGpio14, ui->buttonZL, ui->buttonZR,
|
ui->buttonDebug, ui->buttonGpio14, ui->buttonZL, ui->buttonZR,
|
||||||
ui->buttonHome, ui->buttonPower,
|
ui->buttonHome, ui->buttonPower, ui->buttonToggleCStick,
|
||||||
};
|
};
|
||||||
|
|
||||||
analog_map_buttons = {{
|
analog_map_buttons = {{
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer_2">
|
<spacer name="horizontalSpacer_2">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizeHint" stdset="0">
|
<property name="sizeHint" stdset="0">
|
||||||
<size>
|
<size>
|
||||||
|
|
@ -68,6 +68,14 @@
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="scrollAreaContents">
|
<widget class="QWidget" name="scrollAreaContents">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>-180</y>
|
||||||
|
<width>416</width>
|
||||||
|
<height>802</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QGridLayout" name="gridLayout_7">
|
<layout class="QGridLayout" name="gridLayout_7">
|
||||||
|
|
@ -88,7 +96,7 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_18">
|
<widget class="QLabel" name="label_18">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>ZR:</string>
|
<string>Stylus Touch / ZR:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
@ -124,7 +132,7 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_20">
|
<widget class="QLabel" name="label_20">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>ZL:</string>
|
<string>Stylus Mod / ZL:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
@ -344,17 +352,17 @@
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_6">
|
<layout class="QGridLayout" name="gridLayout_6">
|
||||||
<item row="0" column="0">
|
<item row="2" column="0">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_25">
|
<layout class="QVBoxLayout" name="verticalLayout_28">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_29">
|
<widget class="QLabel" name="label_36">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Start:</string>
|
<string>Circle Mod:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="buttonStart">
|
<widget class="QPushButton" name="buttonCircleMod">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
|
|
@ -380,24 +388,6 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_27">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_31">
|
|
||||||
<property name="text">
|
|
||||||
<string>Home:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="buttonHome">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_34">
|
<layout class="QVBoxLayout" name="verticalLayout_34">
|
||||||
<item>
|
<item>
|
||||||
|
|
@ -416,24 +406,6 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_28">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_36">
|
|
||||||
<property name="text">
|
|
||||||
<string>Circle Mod:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="buttonCircleMod">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_33">
|
<layout class="QVBoxLayout" name="verticalLayout_33">
|
||||||
<item>
|
<item>
|
||||||
|
|
@ -452,6 +424,42 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_25">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_29">
|
||||||
|
<property name="text">
|
||||||
|
<string>Start:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="buttonStart">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_27">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_31">
|
||||||
|
<property name="text">
|
||||||
|
<string>Home:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="buttonHome">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_32">
|
<layout class="QVBoxLayout" name="verticalLayout_32">
|
||||||
<item>
|
<item>
|
||||||
|
|
@ -470,6 +478,24 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_40">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_42">
|
||||||
|
<property name="text">
|
||||||
|
<string>Toggle C-Stick:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="buttonToggleCStick">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
@ -572,7 +598,7 @@
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="sliderCirclePadDeadzoneAndModifierHorizontalLayout">
|
<layout class="QHBoxLayout" name="sliderCirclePadDeadzoneAndModifierHorizontalLayout">
|
||||||
<property name="sizeConstraint">
|
<property name="sizeConstraint">
|
||||||
<enum>QLayout::SetDefaultConstraint</enum>
|
<enum>QLayout::SizeConstraint::SetDefaultConstraint</enum>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="labelCirclePadDeadzoneAndModifier">
|
<widget class="QLabel" name="labelCirclePadDeadzoneAndModifier">
|
||||||
|
|
@ -580,7 +606,7 @@
|
||||||
<string>Deadzone: 0</string>
|
<string>Deadzone: 0</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignHCenter</set>
|
<set>Qt::AlignmentFlag::AlignHCenter</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
@ -589,7 +615,7 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSlider" name="sliderCirclePadDeadzoneAndModifier">
|
<widget class="QSlider" name="sliderCirclePadDeadzoneAndModifier">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
@ -634,25 +660,25 @@
|
||||||
<item row="4" column="1" colspan="2">
|
<item row="4" column="1" colspan="2">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_38">
|
<layout class="QVBoxLayout" name="verticalLayout_38">
|
||||||
<property name="sizeConstraint">
|
<property name="sizeConstraint">
|
||||||
<enum>QLayout::SetDefaultConstraint</enum>
|
<enum>QLayout::SizeConstraint::SetDefaultConstraint</enum>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_14">
|
<widget class="QLabel" name="label_14">
|
||||||
<property name="layoutDirection">
|
<property name="layoutDirection">
|
||||||
<enum>Qt::LeftToRight</enum>
|
<enum>Qt::LayoutDirection::LeftToRight</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Diagonals</string>
|
<string>Diagonals</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignCenter</set>
|
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="Line" name="line">
|
<widget class="Line" name="line">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
@ -697,7 +723,7 @@
|
||||||
<item row="14" column="1" colspan="2">
|
<item row="14" column="1" colspan="2">
|
||||||
<widget class="Line" name="line_3">
|
<widget class="Line" name="line_3">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
@ -707,7 +733,7 @@
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QGroupBox" name="faceButtons_5">
|
<widget class="QGroupBox" name="faceButtons_5">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>C-Stick</string>
|
<string>Stylus / C-Stick</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="flat">
|
<property name="flat">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
|
|
@ -868,14 +894,14 @@
|
||||||
<string>Diagonals</string>
|
<string>Diagonals</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignCenter</set>
|
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="Line" name="line_2">
|
<widget class="Line" name="line_2">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
@ -884,7 +910,7 @@
|
||||||
<item row="9" column="0" colspan="2">
|
<item row="9" column="0" colspan="2">
|
||||||
<layout class="QVBoxLayout" name="sliderCStickDeadzoneAndModifierVerticalLayout">
|
<layout class="QVBoxLayout" name="sliderCStickDeadzoneAndModifierVerticalLayout">
|
||||||
<property name="sizeConstraint">
|
<property name="sizeConstraint">
|
||||||
<enum>QLayout::SetDefaultConstraint</enum>
|
<enum>QLayout::SizeConstraint::SetDefaultConstraint</enum>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="sliderCStickDeadzoneAndModifierHorizontalLayout">
|
<layout class="QHBoxLayout" name="sliderCStickDeadzoneAndModifierHorizontalLayout">
|
||||||
|
|
@ -894,7 +920,7 @@
|
||||||
<string>Deadzone: 0</string>
|
<string>Deadzone: 0</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignHCenter</set>
|
<set>Qt::AlignmentFlag::AlignHCenter</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
@ -903,7 +929,7 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSlider" name="sliderCStickDeadzoneAndModifier">
|
<widget class="QSlider" name="sliderCStickDeadzoneAndModifier">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
@ -919,7 +945,7 @@
|
||||||
<item row="7" column="0" colspan="2">
|
<item row="7" column="0" colspan="2">
|
||||||
<widget class="Line" name="line_4">
|
<widget class="Line" name="line_4">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
@ -957,7 +983,7 @@
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="layoutDirection">
|
<property name="layoutDirection">
|
||||||
<enum>Qt::LeftToRight</enum>
|
<enum>Qt::LayoutDirection::LeftToRight</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Motion / Touch...</string>
|
<string>Motion / Touch...</string>
|
||||||
|
|
@ -985,7 +1011,7 @@
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="layoutDirection">
|
<property name="layoutDirection">
|
||||||
<enum>Qt::LeftToRight</enum>
|
<enum>Qt::LayoutDirection::LeftToRight</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Auto Map</string>
|
<string>Auto Map</string>
|
||||||
|
|
@ -1013,7 +1039,7 @@
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="layoutDirection">
|
<property name="layoutDirection">
|
||||||
<enum>Qt::LeftToRight</enum>
|
<enum>Qt::LayoutDirection::LeftToRight</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Clear All</string>
|
<string>Clear All</string>
|
||||||
|
|
@ -1041,7 +1067,7 @@
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="layoutDirection">
|
<property name="layoutDirection">
|
||||||
<enum>Qt::LeftToRight</enum>
|
<enum>Qt::LayoutDirection::LeftToRight</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Restore Defaults</string>
|
<string>Restore Defaults</string>
|
||||||
|
|
@ -1094,6 +1120,7 @@
|
||||||
<tabstop>buttonCircleMod</tabstop>
|
<tabstop>buttonCircleMod</tabstop>
|
||||||
<tabstop>buttonDebug</tabstop>
|
<tabstop>buttonDebug</tabstop>
|
||||||
<tabstop>buttonGpio14</tabstop>
|
<tabstop>buttonGpio14</tabstop>
|
||||||
|
<tabstop>buttonToggleCStick</tabstop>
|
||||||
<tabstop>buttonMotionTouch</tabstop>
|
<tabstop>buttonMotionTouch</tabstop>
|
||||||
<tabstop>buttonAutoMap</tabstop>
|
<tabstop>buttonAutoMap</tabstop>
|
||||||
<tabstop>buttonClearAll</tabstop>
|
<tabstop>buttonClearAll</tabstop>
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,8 @@ enum Values {
|
||||||
Home,
|
Home,
|
||||||
Power,
|
Power,
|
||||||
|
|
||||||
|
ToggleCStick,
|
||||||
|
|
||||||
NumButtons,
|
NumButtons,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -185,6 +187,7 @@ static const std::array<const char*, NumButtons> mapping = {{
|
||||||
"button_zr",
|
"button_zr",
|
||||||
"button_home",
|
"button_home",
|
||||||
"button_power",
|
"button_power",
|
||||||
|
"button_togglecstick",
|
||||||
}};
|
}};
|
||||||
|
|
||||||
} // namespace NativeButton
|
} // namespace NativeButton
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,8 @@ add_library(citra_core STATIC EXCLUDE_FROM_ALL
|
||||||
frontend/camera/interface.h
|
frontend/camera/interface.h
|
||||||
frontend/emu_window.cpp
|
frontend/emu_window.cpp
|
||||||
frontend/emu_window.h
|
frontend/emu_window.h
|
||||||
|
frontend/cursor.cpp
|
||||||
|
frontend/cursor.h
|
||||||
frontend/framebuffer_layout.cpp
|
frontend/framebuffer_layout.cpp
|
||||||
frontend/framebuffer_layout.h
|
frontend/framebuffer_layout.h
|
||||||
frontend/image_interface.cpp
|
frontend/image_interface.cpp
|
||||||
|
|
|
||||||
276
src/core/frontend/cursor.cpp
Normal file
276
src/core/frontend/cursor.cpp
Normal file
|
|
@ -0,0 +1,276 @@
|
||||||
|
#include "cursor.h"
|
||||||
|
#include <cmath>
|
||||||
|
#include <algorithm>
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "common/logging/types.h"
|
||||||
|
#include "core/hle/service/hid/hid.h"
|
||||||
|
|
||||||
|
|
||||||
|
void Cursor::update(){
|
||||||
|
if (emuWindow != nullptr){
|
||||||
|
stylusInput = Service::HID::Module::getStylusInputs();
|
||||||
|
modButtons = Service::HID::Module::getModButtons();
|
||||||
|
setRotation();
|
||||||
|
if (deviceInUse == 0){
|
||||||
|
if (!Service::HID::Module::cstickEnabled){
|
||||||
|
if (inMacro){
|
||||||
|
runMacro();
|
||||||
|
} else {
|
||||||
|
// LOG_INFO(Core, "Stylus X: {:.2f}, Stylus Y: {:.2f}, Stylus Mod: {}, Stylus Touch: {}", stylusInput[0], stylusInput[1], stylusInput[2], stylusInput[3]);
|
||||||
|
// Reset the cursor position if macro was just played
|
||||||
|
if (justFinishedMacro > 0){
|
||||||
|
justFinishedMacro = 0;
|
||||||
|
rawCursorPos[0] = macroInitPos[0];
|
||||||
|
rawCursorPos[1] = macroInitPos[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Macros
|
||||||
|
if (modButtons[0]){
|
||||||
|
circle(0);
|
||||||
|
return;
|
||||||
|
} else if (modButtons[1]){
|
||||||
|
rub();
|
||||||
|
return;
|
||||||
|
} else if (modButtons[2]){
|
||||||
|
if (!macroBtnPressed){
|
||||||
|
// Add macro
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (modButtons[3]){
|
||||||
|
circle(1);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (macroBtnPressed){
|
||||||
|
macroBtnPressed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
normStylusDirection[0] = stylusInput[0];
|
||||||
|
normStylusDirection[1] = stylusInput[1];
|
||||||
|
|
||||||
|
int maxSpeed = 50;
|
||||||
|
float multiplier = 0.5f * pow(4.0f, maxSpeed / 100.0f); // 0 is 0.5x speed, 100 is 2.0x speed.
|
||||||
|
float heightSpeed = (240.0f / 33.0f) * multiplier;
|
||||||
|
bool stylusModPressed = stylusInput[2];
|
||||||
|
float responsecurve = 175.0f / 100.0f;
|
||||||
|
float speedupratio = 400.0f / 100.0f;
|
||||||
|
float joystickScaled[2] = {0.0f};
|
||||||
|
float radialLength = std::sqrt((normStylusDirection[0] * normStylusDirection[0]) + (normStylusDirection[1] * normStylusDirection[1]));
|
||||||
|
float finalLength;
|
||||||
|
float curvedLength;
|
||||||
|
if (radialLength > 0) {
|
||||||
|
// Get X and Y as a relation to the radial length
|
||||||
|
float rComponents[2];
|
||||||
|
rComponents[0] = normStylusDirection[0]/radialLength;
|
||||||
|
rComponents[1] = normStylusDirection[1]/radialLength;
|
||||||
|
// Apply response curve and output
|
||||||
|
curvedLength = std::pow(radialLength, responsecurve);
|
||||||
|
finalLength = stylusModPressed ? curvedLength * speedupratio : curvedLength;
|
||||||
|
joystickScaled[0] = rComponents[0] * finalLength;
|
||||||
|
joystickScaled[1] = rComponents[1] * finalLength;
|
||||||
|
}
|
||||||
|
// The code below sets the cursor position to the position of the joystick (absolute). Needs to be readjusted for standalone melonDS
|
||||||
|
// _joystickCursorPosition = vec2((NDS_SCREEN_WIDTH/2.0f)+(std::min<float>(1.0,(normStylusDirection[0]/0.7071))*(NDS_SCREEN_WIDTH/2.0f)), (NDS_SCREEN_HEIGHT/2.0f)+(std::min<float>(1.0,(normStylusDirection[1]/0.7071))*(NDS_SCREEN_HEIGHT/2.0f)));
|
||||||
|
|
||||||
|
float tempX = joystickScaled[0];
|
||||||
|
float tempY = joystickScaled[1];
|
||||||
|
|
||||||
|
switch (rotation)
|
||||||
|
{
|
||||||
|
case 1: // 90°
|
||||||
|
joystickScaled[0] = tempY;
|
||||||
|
joystickScaled[1] = -tempX;
|
||||||
|
break;
|
||||||
|
case 2: // 180°
|
||||||
|
joystickScaled[0] = -tempX;
|
||||||
|
joystickScaled[1] = -tempY;
|
||||||
|
break;
|
||||||
|
case 3: // 270°
|
||||||
|
joystickScaled[0] = -tempY;
|
||||||
|
joystickScaled[1] = tempX;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rawCursorPos[0] += joystickScaled[0]*heightSpeed;
|
||||||
|
rawCursorPos[1] += joystickScaled[1]*heightSpeed;
|
||||||
|
|
||||||
|
// Clamp to region and ready position information for touchscreen
|
||||||
|
clamp();
|
||||||
|
updateCursorPos();
|
||||||
|
|
||||||
|
// Handle stylus touch button presses
|
||||||
|
if (stylusInput[3]){
|
||||||
|
touchScreen();
|
||||||
|
wasTouching = true;
|
||||||
|
} else if (wasTouching && !stylusInput[3]){
|
||||||
|
release();
|
||||||
|
wasTouching = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Update cursor based on mouse position
|
||||||
|
clamp();
|
||||||
|
updateCursorPos();
|
||||||
|
|
||||||
|
// Handle stylus touch button presses
|
||||||
|
if (stylusInput[3]){
|
||||||
|
touchScreen();
|
||||||
|
wasTouching = true;
|
||||||
|
} else if (wasTouching && !stylusInput[3]){
|
||||||
|
release();
|
||||||
|
wasTouching = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
setDeviceInUse(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cursor::setDeviceInUse(int device){
|
||||||
|
deviceInUse = device;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cursor::setRawCursorPos(float x, float y){
|
||||||
|
rawCursorPos[0] = x;
|
||||||
|
rawCursorPos[1] = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cursor::clamp(){
|
||||||
|
rawCursorPos[0] = std::clamp(rawCursorPos[0], 0.0f, 319.0f);
|
||||||
|
rawCursorPos[1] = std::clamp(rawCursorPos[1], 0.0f, 239.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cursor::touchScreen(){
|
||||||
|
emuWindow->TouchDirectlyPressed(cursorPos[0], cursorPos[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cursor::release(){
|
||||||
|
emuWindow->TouchReleased();
|
||||||
|
}
|
||||||
|
void Cursor::setEmuWindow(Frontend::EmuWindow* emuWindow){
|
||||||
|
this->emuWindow = emuWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cursor::updateCursorPos(){
|
||||||
|
cursorPos[0] = std::floor(rawCursorPos[0]);
|
||||||
|
cursorPos[1] = std::floor(rawCursorPos[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cursor::circle(int direction){
|
||||||
|
macroBtnPressed = true;
|
||||||
|
inMacro = true;
|
||||||
|
wasTouching = true;
|
||||||
|
macroType = 1;
|
||||||
|
float radius = 240.0f/4.0f;
|
||||||
|
if (justFinishedMacro != 1){ // Set the original position if just starting
|
||||||
|
macroInitPos = {rawCursorPos[0], rawCursorPos[1]};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<std::array<float, 2>> offsetArray;
|
||||||
|
if (direction == 0){
|
||||||
|
offsetArray.push_back({(0.0f*radius), (-1.0f*radius)});
|
||||||
|
offsetArray.push_back({(0.7071f*radius), (-0.7071f*radius)});
|
||||||
|
offsetArray.push_back({(1.0f*radius), (0.0f*radius)});
|
||||||
|
offsetArray.push_back({(0.7071f*radius), (0.7071f*radius)});
|
||||||
|
offsetArray.push_back({(0.0f*radius), (1.0f*radius)});
|
||||||
|
offsetArray.push_back({(-0.7071f*radius), (0.7071f*radius)});
|
||||||
|
offsetArray.push_back({(-1.0f*radius), (0.0f*radius)});
|
||||||
|
offsetArray.push_back({(-0.7071f*radius), (-0.7071f*radius)});
|
||||||
|
} else {
|
||||||
|
offsetArray.push_back({(0.0f*radius), (-1.0f*radius)});
|
||||||
|
offsetArray.push_back({(-0.7071f*radius), (-0.7071f*radius)});
|
||||||
|
offsetArray.push_back({(-1.0f*radius), (0.0f*radius)});
|
||||||
|
offsetArray.push_back({(-0.7071f*radius), (0.7071f*radius)});
|
||||||
|
offsetArray.push_back({(0.0f*radius), (1.0f*radius)});
|
||||||
|
offsetArray.push_back({(0.7071f*radius), (0.7071f*radius)});
|
||||||
|
offsetArray.push_back({(1.0f*radius), (0.0f*radius)});
|
||||||
|
offsetArray.push_back({(0.7071f*radius), (-0.7071f*radius)});
|
||||||
|
}
|
||||||
|
offsetArray = rotateVector(offsetArray);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < offsetArray.size(); i++){
|
||||||
|
macroPositions.push_back({rawCursorPos[0]+offsetArray[i][0], rawCursorPos[1]+offsetArray[i][1]});
|
||||||
|
}
|
||||||
|
macroFrames = macroPositions.size();
|
||||||
|
runMacro();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cursor::rub(){
|
||||||
|
macroBtnPressed = true;
|
||||||
|
inMacro = true;
|
||||||
|
wasTouching = true;
|
||||||
|
macroType = 2;
|
||||||
|
float radius = 240.0f/6.0f;
|
||||||
|
if (justFinishedMacro != 2){ // Set the original position if just starting
|
||||||
|
macroInitPos = {rawCursorPos[0], rawCursorPos[1]};
|
||||||
|
}
|
||||||
|
std::vector<std::array<float, 2>> offsetArray;
|
||||||
|
offsetArray.push_back({(0.0f*radius), 0});
|
||||||
|
offsetArray.push_back({(0.5f*radius), 0});
|
||||||
|
offsetArray.push_back({(1.0f*radius), 0});
|
||||||
|
offsetArray.push_back({(0.5f*radius), 0});
|
||||||
|
offsetArray.push_back({(0.0f*radius), 0});
|
||||||
|
offsetArray.push_back({(-0.5f*radius), 0});
|
||||||
|
offsetArray.push_back({(-1.0f*radius), 0});
|
||||||
|
offsetArray.push_back({(-0.5f*radius), 0});
|
||||||
|
offsetArray = rotateVector(offsetArray);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < offsetArray.size(); i++){
|
||||||
|
macroPositions.push_back({rawCursorPos[0]+offsetArray[i][0], rawCursorPos[1]+offsetArray[i][1]});
|
||||||
|
}
|
||||||
|
macroFrames = macroPositions.size();
|
||||||
|
runMacro();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Cursor::runMacro(){
|
||||||
|
rawCursorPos[0] = macroPositions.front()[0];
|
||||||
|
rawCursorPos[1] = macroPositions.front()[1];
|
||||||
|
macroPositions.pop_front();
|
||||||
|
clamp();
|
||||||
|
updateCursorPos();
|
||||||
|
touchScreen();
|
||||||
|
macroFrames--;
|
||||||
|
if (macroFrames == 0){
|
||||||
|
macroPositions.clear();
|
||||||
|
inMacro = false;
|
||||||
|
justFinishedMacro = macroType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cursor::setRotation(){
|
||||||
|
if (emuWindow->GetFramebufferLayout().is_portrait){
|
||||||
|
rotation = 1;
|
||||||
|
} else {
|
||||||
|
rotation = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::array<float, 2>> Cursor::rotateVector(std::vector<std::array<float, 2>> input){
|
||||||
|
for (auto& currArray : input){
|
||||||
|
float tempX = currArray[0];
|
||||||
|
float tempY = currArray[1];
|
||||||
|
switch (rotation)
|
||||||
|
{
|
||||||
|
case 1: // 90°
|
||||||
|
currArray[0] = tempY;
|
||||||
|
currArray[1] = -tempX;
|
||||||
|
break;
|
||||||
|
case 2: // 180°
|
||||||
|
currArray[0] = -tempX;
|
||||||
|
currArray[1] = -tempY;
|
||||||
|
break;
|
||||||
|
case 3: // 270°
|
||||||
|
currArray[0] = -tempY;
|
||||||
|
currArray[1] = tempX;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return input;
|
||||||
|
}
|
||||||
48
src/core/frontend/cursor.h
Normal file
48
src/core/frontend/cursor.h
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
#ifndef CURSOR_H
|
||||||
|
#define CURSOR_H
|
||||||
|
#include <queue>
|
||||||
|
#include "emu_window.h"
|
||||||
|
#include <array>
|
||||||
|
#include <vector>
|
||||||
|
namespace Frontend {
|
||||||
|
class EmuWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Cursor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void update();
|
||||||
|
void setRawCursorPos(float x, float y);
|
||||||
|
void setDeviceInUse(int device);
|
||||||
|
void setEmuWindow(Frontend::EmuWindow* emuWindow);
|
||||||
|
void setRotation();
|
||||||
|
int cursorPos[2];
|
||||||
|
float normStylusDirection[2];
|
||||||
|
bool cursorEnabled = true;
|
||||||
|
private:
|
||||||
|
Frontend::EmuWindow* emuWindow = nullptr;
|
||||||
|
float rawCursorPos[2] = {159, 119};
|
||||||
|
void touchScreen();
|
||||||
|
void release();
|
||||||
|
void clamp();
|
||||||
|
void updateCursorPos();
|
||||||
|
bool wasTouching;
|
||||||
|
std::array<float, 4> stylusInput;
|
||||||
|
std::array<float, 4> modButtons;
|
||||||
|
void circle(int direction); //0 is clockwise, 1 is counter clockwise
|
||||||
|
void rub();
|
||||||
|
void runMacro();
|
||||||
|
|
||||||
|
std::vector<std::array<float, 2>> rotateVector(std::vector<std::array<float, 2>> input);
|
||||||
|
bool inMacro;
|
||||||
|
std::deque<std::array<float, 2>> macroPositions;
|
||||||
|
int macroFrames;
|
||||||
|
bool macroBtnPressed;
|
||||||
|
int macroType;
|
||||||
|
int justFinishedMacro;
|
||||||
|
std::array<float, 2> macroInitPos;
|
||||||
|
int rotation;
|
||||||
|
int deviceInUse; //0 is Gamepad, 1 is Mouse/Tablet
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CURSOR_H
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
|
|
@ -191,6 +192,16 @@ bool EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EmuWindow::TouchDirectlyPressed(unsigned internal_x, unsigned internal_y) {
|
||||||
|
//This assumes 0, 0 is bottom left corner
|
||||||
|
std::scoped_lock guard{touch_state->mutex};
|
||||||
|
std::clamp<unsigned>(internal_x, 0, 319);
|
||||||
|
std::clamp<unsigned>(internal_y, 0, 239);
|
||||||
|
touch_state->touch_pressed = true;
|
||||||
|
touch_state->touch_x = internal_x/320.0f;
|
||||||
|
touch_state->touch_y = (239-internal_y)/240.0f;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
void EmuWindow::TouchReleased() {
|
void EmuWindow::TouchReleased() {
|
||||||
std::scoped_lock guard{touch_state->mutex};
|
std::scoped_lock guard{touch_state->mutex};
|
||||||
touch_state->touch_pressed = false;
|
touch_state->touch_pressed = false;
|
||||||
|
|
|
||||||
|
|
@ -199,6 +199,9 @@ public:
|
||||||
*/
|
*/
|
||||||
bool TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y);
|
bool TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y);
|
||||||
|
|
||||||
|
/// Signal a touch pressed event occured, bypassing the framebuffer (e.g. stylus touch button pressed on controller)
|
||||||
|
bool TouchDirectlyPressed(unsigned internal_x, unsigned internal_y);
|
||||||
|
|
||||||
/// Signal that a touch released event has occurred (e.g. mouse click released)
|
/// Signal that a touch released event has occurred (e.g. mouse click released)
|
||||||
void TouchReleased();
|
void TouchReleased();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -639,6 +639,7 @@ FramebufferLayout reverseLayout(FramebufferLayout layout) {
|
||||||
layout.additional_screen.top = layout.height - oldRight;
|
layout.additional_screen.top = layout.height - oldRight;
|
||||||
layout.additional_screen.bottom = layout.height - oldLeft;
|
layout.additional_screen.bottom = layout.height - oldLeft;
|
||||||
}
|
}
|
||||||
|
layout.is_portrait = true;
|
||||||
return layout;
|
return layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,12 +24,15 @@
|
||||||
#include "core/hle/service/ir/ir_user.h"
|
#include "core/hle/service/ir/ir_user.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
#include "core/movie.h"
|
#include "core/movie.h"
|
||||||
|
#include "hid.h"
|
||||||
|
|
||||||
SERVICE_CONSTRUCT_IMPL(Service::HID::Module)
|
SERVICE_CONSTRUCT_IMPL(Service::HID::Module)
|
||||||
SERIALIZE_EXPORT_IMPL(Service::HID::Module)
|
SERIALIZE_EXPORT_IMPL(Service::HID::Module)
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
|
std::array<float, 4> Module::stylusInput = {};
|
||||||
|
std::array<float, 4> Module::modButtons = {};
|
||||||
|
bool Module::cstickEnabled = false;
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void Module::serialize(Archive& ar, const unsigned int file_version) {
|
void Module::serialize(Archive& ar, const unsigned int file_version) {
|
||||||
DEBUG_SERIALIZATION_POINT;
|
DEBUG_SERIALIZATION_POINT;
|
||||||
|
|
@ -121,8 +124,16 @@ void Module::LoadInputDevices() {
|
||||||
Settings::values.current_input_profile.buttons.begin() +
|
Settings::values.current_input_profile.buttons.begin() +
|
||||||
Settings::NativeButton::BUTTON_HID_END,
|
Settings::NativeButton::BUTTON_HID_END,
|
||||||
buttons.begin(), Input::CreateDevice<Input::ButtonDevice>);
|
buttons.begin(), Input::CreateDevice<Input::ButtonDevice>);
|
||||||
|
zl_button = Input::CreateDevice<Input::ButtonDevice>(
|
||||||
|
Settings::values.current_input_profile.buttons[Settings::NativeButton::ZL]);
|
||||||
|
zr_button = Input::CreateDevice<Input::ButtonDevice>(
|
||||||
|
Settings::values.current_input_profile.buttons[Settings::NativeButton::ZR]);
|
||||||
|
toggle_cstick_button = Input::CreateDevice<Input::ButtonDevice>(
|
||||||
|
Settings::values.current_input_profile.buttons[Settings::NativeButton::ToggleCStick]);
|
||||||
circle_pad = Input::CreateDevice<Input::AnalogDevice>(
|
circle_pad = Input::CreateDevice<Input::AnalogDevice>(
|
||||||
Settings::values.current_input_profile.analogs[Settings::NativeAnalog::CirclePad]);
|
Settings::values.current_input_profile.analogs[Settings::NativeAnalog::CirclePad]);
|
||||||
|
c_stick = Input::CreateDevice<Input::AnalogDevice>(
|
||||||
|
Settings::values.current_input_profile.analogs[Settings::NativeAnalog::CStick]);
|
||||||
motion_device = Input::CreateDevice<Input::MotionDevice>(
|
motion_device = Input::CreateDevice<Input::MotionDevice>(
|
||||||
Settings::values.current_input_profile.motion_device);
|
Settings::values.current_input_profile.motion_device);
|
||||||
touch_device = Input::CreateDevice<Input::TouchDevice>(
|
touch_device = Input::CreateDevice<Input::TouchDevice>(
|
||||||
|
|
@ -217,6 +228,24 @@ void Module::UpdatePadCallback(std::uintptr_t user_data, s64 cycles_late) {
|
||||||
state.debug.Assign(buttons[Debug - BUTTON_HID_BEGIN]->GetStatus());
|
state.debug.Assign(buttons[Debug - BUTTON_HID_BEGIN]->GetStatus());
|
||||||
state.gpio14.Assign(buttons[Gpio14 - BUTTON_HID_BEGIN]->GetStatus());
|
state.gpio14.Assign(buttons[Gpio14 - BUTTON_HID_BEGIN]->GetStatus());
|
||||||
|
|
||||||
|
// Setting up inputs for Cursor Class.
|
||||||
|
float c_stick_x_f, c_stick_y_f;
|
||||||
|
std::tie(c_stick_x_f, c_stick_y_f) = c_stick->GetStatus();
|
||||||
|
stylusInput[0] = c_stick_x_f;
|
||||||
|
stylusInput[1] = c_stick_y_f;
|
||||||
|
stylusInput[2] = static_cast<float>(zl_button->GetStatus());
|
||||||
|
stylusInput[3] = static_cast<float>(zr_button->GetStatus());
|
||||||
|
for (int i = 0; i < 4; i++){
|
||||||
|
modButtons[i] = zl_button->GetStatus() && buttons[i - BUTTON_HID_BEGIN]->GetStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Toggle for Cstick
|
||||||
|
if (!prev_toggle_cstick_button_state && toggle_cstick_button->GetStatus()){
|
||||||
|
cstickEnabled = !cstickEnabled;
|
||||||
|
}
|
||||||
|
//LOG_INFO(Service_HID, "C-Stick Enabled: {}, Prev C-Stick Button State {}, Current C-Stick Button State {}", cstickEnabled, prev_toggle_cstick_button_state, toggle_cstick_button->GetStatus());
|
||||||
|
prev_toggle_cstick_button_state = toggle_cstick_button->GetStatus();
|
||||||
|
|
||||||
// Get current circle pad position and update circle pad direction
|
// Get current circle pad position and update circle pad direction
|
||||||
float circle_pad_x_f, circle_pad_y_f;
|
float circle_pad_x_f, circle_pad_y_f;
|
||||||
std::tie(circle_pad_x_f, circle_pad_y_f) = circle_pad->GetStatus();
|
std::tie(circle_pad_x_f, circle_pad_y_f) = circle_pad->GetStatus();
|
||||||
|
|
@ -320,6 +349,14 @@ void Module::UpdatePadCallback(std::uintptr_t user_data, s64 cycles_late) {
|
||||||
system.CoreTiming().ScheduleEvent(pad_update_ticks - cycles_late, pad_update_event);
|
system.CoreTiming().ScheduleEvent(pad_update_ticks - cycles_late, pad_update_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::array<float, 4> Module::getStylusInputs(){
|
||||||
|
return stylusInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<float, 4> Module::getModButtons(){
|
||||||
|
return modButtons;
|
||||||
|
}
|
||||||
|
|
||||||
void Module::UpdateAccelerometerCallback(std::uintptr_t user_data, s64 cycles_late) {
|
void Module::UpdateAccelerometerCallback(std::uintptr_t user_data, s64 cycles_late) {
|
||||||
SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer());
|
SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -242,9 +242,8 @@ public:
|
||||||
class Interface : public ServiceFramework<Interface> {
|
class Interface : public ServiceFramework<Interface> {
|
||||||
public:
|
public:
|
||||||
Interface(std::shared_ptr<Module> hid, const char* name, u32 max_session);
|
Interface(std::shared_ptr<Module> hid, const char* name, u32 max_session);
|
||||||
|
// Stylus X, Y, ZL, ZR
|
||||||
std::shared_ptr<Module> GetModule() const;
|
std::shared_ptr<Module> GetModule() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* HID::GetIPCHandles service function
|
* HID::GetIPCHandles service function
|
||||||
|
|
@ -335,7 +334,9 @@ public:
|
||||||
void UseArticClient(const std::shared_ptr<Network::ArticBase::Client>& client);
|
void UseArticClient(const std::shared_ptr<Network::ArticBase::Client>& client);
|
||||||
|
|
||||||
void ReloadInputDevices();
|
void ReloadInputDevices();
|
||||||
|
static std::array<float, 4> getStylusInputs();
|
||||||
|
static std::array<float, 4> getModButtons();
|
||||||
|
static bool cstickEnabled;
|
||||||
const PadState& GetState() const;
|
const PadState& GetState() const;
|
||||||
|
|
||||||
// Updating period for each HID device. These empirical values are measured from a 11.2 3DS.
|
// Updating period for each HID device. These empirical values are measured from a 11.2 3DS.
|
||||||
|
|
@ -388,12 +389,18 @@ private:
|
||||||
std::atomic<bool> is_device_reload_pending{true};
|
std::atomic<bool> is_device_reload_pending{true};
|
||||||
std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>
|
std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>
|
||||||
buttons;
|
buttons;
|
||||||
|
std::unique_ptr<Input::ButtonDevice> zl_button;
|
||||||
|
std::unique_ptr<Input::ButtonDevice> zr_button;
|
||||||
|
std::unique_ptr<Input::ButtonDevice> toggle_cstick_button;
|
||||||
std::unique_ptr<Input::AnalogDevice> circle_pad;
|
std::unique_ptr<Input::AnalogDevice> circle_pad;
|
||||||
|
std::unique_ptr<Input::AnalogDevice> c_stick;
|
||||||
std::unique_ptr<Input::MotionDevice> motion_device;
|
std::unique_ptr<Input::MotionDevice> motion_device;
|
||||||
std::unique_ptr<Input::TouchDevice> controller_touch_device;
|
std::unique_ptr<Input::TouchDevice> controller_touch_device;
|
||||||
std::unique_ptr<Input::TouchDevice> touch_device;
|
std::unique_ptr<Input::TouchDevice> touch_device;
|
||||||
std::unique_ptr<Input::TouchDevice> touch_btn_device;
|
std::unique_ptr<Input::TouchDevice> touch_btn_device;
|
||||||
|
static std::array<float, 4> stylusInput;
|
||||||
|
static std::array<float, 4> modButtons;
|
||||||
|
bool prev_toggle_cstick_button_state = false;
|
||||||
std::shared_ptr<ArticBaseController> artic_controller;
|
std::shared_ptr<ArticBaseController> artic_controller;
|
||||||
std::shared_ptr<Network::ArticBase::Client> artic_client;
|
std::shared_ptr<Network::ArticBase::Client> artic_client;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -262,13 +262,20 @@ void ExtraHID::SendHIDStatus() {
|
||||||
} else {
|
} else {
|
||||||
float x, y;
|
float x, y;
|
||||||
std::tie(x, y) = c_stick->GetStatus();
|
std::tie(x, y) = c_stick->GetStatus();
|
||||||
|
response.buttons.battery_level.Assign(0x1F);
|
||||||
response.c_stick.header.Assign(static_cast<u8>(ResponseID::PollHID));
|
response.c_stick.header.Assign(static_cast<u8>(ResponseID::PollHID));
|
||||||
|
if (Service::HID::Module::cstickEnabled){
|
||||||
response.c_stick.c_stick_x.Assign(static_cast<u32>(C_STICK_CENTER + C_STICK_RADIUS * x));
|
response.c_stick.c_stick_x.Assign(static_cast<u32>(C_STICK_CENTER + C_STICK_RADIUS * x));
|
||||||
response.c_stick.c_stick_y.Assign(static_cast<u32>(C_STICK_CENTER + C_STICK_RADIUS * y));
|
response.c_stick.c_stick_y.Assign(static_cast<u32>(C_STICK_CENTER + C_STICK_RADIUS * y));
|
||||||
response.buttons.battery_level.Assign(0x1F);
|
|
||||||
response.buttons.zl_not_held.Assign(!zl->GetStatus());
|
response.buttons.zl_not_held.Assign(!zl->GetStatus());
|
||||||
response.buttons.zr_not_held.Assign(!zr->GetStatus());
|
response.buttons.zr_not_held.Assign(!zr->GetStatus());
|
||||||
|
} else {
|
||||||
|
response.c_stick.c_stick_x.Assign(static_cast<u32>(C_STICK_CENTER));
|
||||||
|
response.c_stick.c_stick_y.Assign(static_cast<u32>(C_STICK_CENTER));
|
||||||
|
response.buttons.zl_not_held.Assign(true);
|
||||||
|
response.buttons.zr_not_held.Assign(true);
|
||||||
|
}
|
||||||
|
|
||||||
response.buttons.r_not_held.Assign(1);
|
response.buttons.r_not_held.Assign(1);
|
||||||
response.unknown = 0;
|
response.unknown = 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,7 @@ constexpr std::array<SDL_GameControllerButton, Settings::NativeButton::NumButton
|
||||||
SDL_CONTROLLER_BUTTON_INVALID,
|
SDL_CONTROLLER_BUTTON_INVALID,
|
||||||
SDL_CONTROLLER_BUTTON_GUIDE,
|
SDL_CONTROLLER_BUTTON_GUIDE,
|
||||||
SDL_CONTROLLER_BUTTON_INVALID,
|
SDL_CONTROLLER_BUTTON_INVALID,
|
||||||
|
SDL_CONTROLLER_BUTTON_LEFTSTICK,
|
||||||
}};
|
}};
|
||||||
|
|
||||||
struct SDLJoystickDeleter {
|
struct SDLJoystickDeleter {
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,48 @@ layout(binding = 0) uniform sampler2D color_texture;
|
||||||
|
|
||||||
uniform vec4 i_resolution;
|
uniform vec4 i_resolution;
|
||||||
uniform vec4 o_resolution;
|
uniform vec4 o_resolution;
|
||||||
|
uniform vec2 cursor_pos;
|
||||||
|
uniform bool cursor_enable;
|
||||||
uniform int layer;
|
uniform int layer;
|
||||||
|
in vec2 pixelUnit;
|
||||||
void main() {
|
void main() {
|
||||||
color = texture(color_texture, frag_tex_coord);
|
vec4 pixel = texture(color_texture, frag_tex_coord);
|
||||||
|
vec2 rfrag_tex_coord = vec2(frag_tex_coord.y, frag_tex_coord.x);
|
||||||
|
//Cursor
|
||||||
|
if (cursor_enable){
|
||||||
|
//Black Outline
|
||||||
|
if (rfrag_tex_coord.x <= (cursor_pos.x + (2.0*pixelUnit.x)) &&
|
||||||
|
rfrag_tex_coord.x >= (cursor_pos.x - (1.0*pixelUnit.x))) {
|
||||||
|
if (rfrag_tex_coord.y <= (cursor_pos.y + (5.0*pixelUnit.y)) &&
|
||||||
|
rfrag_tex_coord.y >= (cursor_pos.y - (4.0*pixelUnit.y))) {
|
||||||
|
pixel = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rfrag_tex_coord.y <= (cursor_pos.y + (2.0*pixelUnit.y)) &&
|
||||||
|
rfrag_tex_coord.y >= (cursor_pos.y - (1.0*pixelUnit.y))) {
|
||||||
|
if (rfrag_tex_coord.x <= (cursor_pos.x + (5.0*pixelUnit.x)) &&
|
||||||
|
rfrag_tex_coord.x >= (cursor_pos.x - (4.0*pixelUnit.x))) {
|
||||||
|
pixel = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//White Cross
|
||||||
|
if (rfrag_tex_coord.x <= (cursor_pos.x + (1.0*pixelUnit.x)) &&
|
||||||
|
rfrag_tex_coord.x >= (cursor_pos.x - (0.0*pixelUnit.x))) {
|
||||||
|
if (rfrag_tex_coord.y <= (cursor_pos.y + (4.0*pixelUnit.y)) &&
|
||||||
|
rfrag_tex_coord.y >= (cursor_pos.y - (3.0*pixelUnit.y))) {
|
||||||
|
pixel = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rfrag_tex_coord.y <= (cursor_pos.y + (1.0*pixelUnit.y)) &&
|
||||||
|
rfrag_tex_coord.y >= (cursor_pos.y - (0.0*pixelUnit.y))) {
|
||||||
|
if (rfrag_tex_coord.x <= (cursor_pos.x + (4.0*pixelUnit.x)) &&
|
||||||
|
rfrag_tex_coord.x >= (cursor_pos.x - (3.0*pixelUnit.x))) {
|
||||||
|
pixel = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
color = vec4(pixel.rgb, 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,13 @@ layout(location = 0) out vec2 frag_tex_coord;
|
||||||
// The third row could be used for projection, which we don't need in 2D. It hence is assumed to
|
// The third row could be used for projection, which we don't need in 2D. It hence is assumed to
|
||||||
// implicitly be [0, 0, 1]
|
// implicitly be [0, 0, 1]
|
||||||
uniform mat3x2 modelview_matrix;
|
uniform mat3x2 modelview_matrix;
|
||||||
|
out vec2 pixelUnit;
|
||||||
void main() {
|
void main() {
|
||||||
// Multiply input position by the rotscale part of the matrix and then manually translate by
|
// Multiply input position by the rotscale part of the matrix and then manually translate by
|
||||||
// the last column. This is equivalent to using a full 3x3 matrix and expanding the vector
|
// the last column. This is equivalent to using a full 3x3 matrix and expanding the vector
|
||||||
// to `vec3(vert_position.xy, 1.0)`
|
// to `vec3(vert_position.xy, 1.0)`
|
||||||
gl_Position = vec4(mat2(modelview_matrix) * vert_position + modelview_matrix[2], 0.0, 1.0);
|
gl_Position = vec4(mat2(modelview_matrix) * vert_position + modelview_matrix[2], 0.0, 1.0);
|
||||||
frag_tex_coord = vert_tex_coord;
|
frag_tex_coord = vert_tex_coord;
|
||||||
|
pixelUnit.x = 1/320.0;
|
||||||
|
pixelUnit.y = 1/240.0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,13 @@
|
||||||
|
|
||||||
layout (location = 0) in vec2 frag_tex_coord;
|
layout (location = 0) in vec2 frag_tex_coord;
|
||||||
layout (location = 0) out vec4 color;
|
layout (location = 0) out vec4 color;
|
||||||
|
layout (location = 1) in vec2 pixelUnit;
|
||||||
layout (push_constant, std140) uniform DrawInfo {
|
layout (push_constant, std140) uniform DrawInfo {
|
||||||
mat4 modelview_matrix;
|
mat4 modelview_matrix;
|
||||||
vec4 i_resolution;
|
vec4 i_resolution;
|
||||||
vec4 o_resolution;
|
vec4 o_resolution;
|
||||||
|
vec2 cursor_pos;
|
||||||
|
int cursor_enable;
|
||||||
int screen_id_l;
|
int screen_id_l;
|
||||||
int screen_id_r;
|
int screen_id_r;
|
||||||
int layer;
|
int layer;
|
||||||
|
|
@ -20,6 +22,7 @@ layout (push_constant, std140) uniform DrawInfo {
|
||||||
|
|
||||||
layout (set = 0, binding = 0) uniform sampler2D screen_textures[3];
|
layout (set = 0, binding = 0) uniform sampler2D screen_textures[3];
|
||||||
|
|
||||||
|
|
||||||
vec4 GetScreen(int screen_id) {
|
vec4 GetScreen(int screen_id) {
|
||||||
#ifdef ARRAY_DYNAMIC_INDEX
|
#ifdef ARRAY_DYNAMIC_INDEX
|
||||||
return texture(screen_textures[screen_id], frag_tex_coord);
|
return texture(screen_textures[screen_id], frag_tex_coord);
|
||||||
|
|
@ -36,5 +39,42 @@ vec4 GetScreen(int screen_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
color = GetScreen(screen_id_l);
|
vec4 pixel = GetScreen(screen_id_l);
|
||||||
|
vec2 rfrag_tex_coord = vec2(frag_tex_coord.y, frag_tex_coord.x);
|
||||||
|
//Cursor
|
||||||
|
if (cursor_enable == 1){
|
||||||
|
//Black Outline
|
||||||
|
if (rfrag_tex_coord.x <= (cursor_pos.x + (2.0*pixelUnit.x)) &&
|
||||||
|
rfrag_tex_coord.x >= (cursor_pos.x - (1.0*pixelUnit.x))) {
|
||||||
|
if (rfrag_tex_coord.y <= (cursor_pos.y + (5.0*pixelUnit.y)) &&
|
||||||
|
rfrag_tex_coord.y >= (cursor_pos.y - (4.0*pixelUnit.y))) {
|
||||||
|
pixel = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rfrag_tex_coord.y <= (cursor_pos.y + (2.0*pixelUnit.y)) &&
|
||||||
|
rfrag_tex_coord.y >= (cursor_pos.y - (1.0*pixelUnit.y))) {
|
||||||
|
if (rfrag_tex_coord.x <= (cursor_pos.x + (5.0*pixelUnit.x)) &&
|
||||||
|
rfrag_tex_coord.x >= (cursor_pos.x - (4.0*pixelUnit.x))) {
|
||||||
|
pixel = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//White Cross
|
||||||
|
if (rfrag_tex_coord.x <= (cursor_pos.x + (1.0*pixelUnit.x)) &&
|
||||||
|
rfrag_tex_coord.x >= (cursor_pos.x - (0.0*pixelUnit.x))) {
|
||||||
|
if (rfrag_tex_coord.y <= (cursor_pos.y + (4.0*pixelUnit.y)) &&
|
||||||
|
rfrag_tex_coord.y >= (cursor_pos.y - (3.0*pixelUnit.y))) {
|
||||||
|
pixel = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rfrag_tex_coord.y <= (cursor_pos.y + (1.0*pixelUnit.y)) &&
|
||||||
|
rfrag_tex_coord.y >= (cursor_pos.y - (0.0*pixelUnit.y))) {
|
||||||
|
if (rfrag_tex_coord.x <= (cursor_pos.x + (4.0*pixelUnit.x)) &&
|
||||||
|
rfrag_tex_coord.x >= (cursor_pos.x - (3.0*pixelUnit.x))) {
|
||||||
|
pixel = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
color = vec4(pixel.rgb, 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,13 @@
|
||||||
layout (location = 0) in vec2 vert_position;
|
layout (location = 0) in vec2 vert_position;
|
||||||
layout (location = 1) in vec2 vert_tex_coord;
|
layout (location = 1) in vec2 vert_tex_coord;
|
||||||
layout (location = 0) out vec2 frag_tex_coord;
|
layout (location = 0) out vec2 frag_tex_coord;
|
||||||
|
layout (location = 1) out vec2 pixelUnit;
|
||||||
layout (push_constant, std140) uniform DrawInfo {
|
layout (push_constant, std140) uniform DrawInfo {
|
||||||
mat4 modelview_matrix;
|
mat4 modelview_matrix;
|
||||||
vec4 i_resolution;
|
vec4 i_resolution;
|
||||||
vec4 o_resolution;
|
vec4 o_resolution;
|
||||||
|
vec2 cursor_pos;
|
||||||
|
int cursor_enable;
|
||||||
int screen_id_l;
|
int screen_id_l;
|
||||||
int screen_id_r;
|
int screen_id_r;
|
||||||
int layer;
|
int layer;
|
||||||
|
|
@ -22,4 +24,6 @@ void main() {
|
||||||
vec4 position = vec4(vert_position, 0.0, 1.0) * modelview_matrix;
|
vec4 position = vec4(vert_position, 0.0, 1.0) * modelview_matrix;
|
||||||
gl_Position = vec4(position.x, position.y, 0.0, 1.0);
|
gl_Position = vec4(position.x, position.y, 0.0, 1.0);
|
||||||
frag_tex_coord = vert_tex_coord;
|
frag_tex_coord = vert_tex_coord;
|
||||||
|
pixelUnit.x = 1/320.0;
|
||||||
|
pixelUnit.y = 1/240.0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ layout (push_constant, std140) uniform DrawInfo {
|
||||||
mat4 modelview_matrix;
|
mat4 modelview_matrix;
|
||||||
vec4 i_resolution;
|
vec4 i_resolution;
|
||||||
vec4 o_resolution;
|
vec4 o_resolution;
|
||||||
|
vec2 cursor_pos;
|
||||||
|
int cursor_enable;
|
||||||
int screen_id_l;
|
int screen_id_l;
|
||||||
int screen_id_r;
|
int screen_id_r;
|
||||||
int layer;
|
int layer;
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ layout (push_constant, std140) uniform DrawInfo {
|
||||||
mat4 modelview_matrix;
|
mat4 modelview_matrix;
|
||||||
vec4 i_resolution;
|
vec4 i_resolution;
|
||||||
vec4 o_resolution;
|
vec4 o_resolution;
|
||||||
|
vec2 cursor_pos;
|
||||||
|
int cursor_enable;
|
||||||
int screen_id_l;
|
int screen_id_l;
|
||||||
int screen_id_r;
|
int screen_id_r;
|
||||||
int layer;
|
int layer;
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/frontend/framebuffer_layout.h"
|
#include "core/frontend/framebuffer_layout.h"
|
||||||
#include "video_core/rasterizer_interface.h"
|
#include "video_core/rasterizer_interface.h"
|
||||||
|
#include "core/frontend/cursor.h"
|
||||||
|
class Cursor;
|
||||||
|
|
||||||
namespace Frontend {
|
namespace Frontend {
|
||||||
class EmuWindow;
|
class EmuWindow;
|
||||||
|
|
@ -109,6 +111,7 @@ protected:
|
||||||
RendererSettings settings;
|
RendererSettings settings;
|
||||||
Frontend::EmuWindow& render_window; /// Reference to the render window handle.
|
Frontend::EmuWindow& render_window; /// Reference to the render window handle.
|
||||||
Frontend::EmuWindow* secondary_window; /// Reference to the secondary render window handle.
|
Frontend::EmuWindow* secondary_window; /// Reference to the secondary render window handle.
|
||||||
|
Cursor* vCursor;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
f32 current_fps = 0.0f; /// Current framerate, should be set by the renderer
|
f32 current_fps = 0.0f; /// Current framerate, should be set by the renderer
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,8 @@ RendererOpenGL::RendererOpenGL(Core::System& system, Pica::PicaCore& pica_,
|
||||||
rasterizer{system.Memory(), pica, system.CustomTexManager(), *this, driver},
|
rasterizer{system.Memory(), pica, system.CustomTexManager(), *this, driver},
|
||||||
frame_dumper{system, window} {
|
frame_dumper{system, window} {
|
||||||
const bool has_debug_tool = driver.HasDebugTool();
|
const bool has_debug_tool = driver.HasDebugTool();
|
||||||
|
vCursor = new Cursor();
|
||||||
|
vCursor->setEmuWindow(&window);
|
||||||
window.mailbox = std::make_unique<OGLTextureMailbox>(has_debug_tool);
|
window.mailbox = std::make_unique<OGLTextureMailbox>(has_debug_tool);
|
||||||
if (secondary_window) {
|
if (secondary_window) {
|
||||||
secondary_window->mailbox = std::make_unique<OGLTextureMailbox>(has_debug_tool);
|
secondary_window->mailbox = std::make_unique<OGLTextureMailbox>(has_debug_tool);
|
||||||
|
|
@ -235,6 +237,7 @@ void RendererOpenGL::RenderToMailbox(const Layout::FramebufferLayout& layout,
|
||||||
|
|
||||||
state.draw.draw_framebuffer = frame->render.handle;
|
state.draw.draw_framebuffer = frame->render.handle;
|
||||||
state.Apply();
|
state.Apply();
|
||||||
|
vCursor->update();
|
||||||
DrawScreens(layout, flipped);
|
DrawScreens(layout, flipped);
|
||||||
// Create a fence for the frontend to wait on and swap this frame to OffTex
|
// Create a fence for the frontend to wait on and swap this frame to OffTex
|
||||||
frame->render_fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
frame->render_fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||||
|
|
@ -433,6 +436,8 @@ void RendererOpenGL::ReloadShader(Settings::StereoRenderOption render_3d) {
|
||||||
uniform_i_resolution = glGetUniformLocation(shader.handle, "i_resolution");
|
uniform_i_resolution = glGetUniformLocation(shader.handle, "i_resolution");
|
||||||
uniform_o_resolution = glGetUniformLocation(shader.handle, "o_resolution");
|
uniform_o_resolution = glGetUniformLocation(shader.handle, "o_resolution");
|
||||||
uniform_layer = glGetUniformLocation(shader.handle, "layer");
|
uniform_layer = glGetUniformLocation(shader.handle, "layer");
|
||||||
|
uniform_cursor_pos = glGetUniformLocation(shader.handle, "cursor_pos");
|
||||||
|
uniform_cursor_enable = glGetUniformLocation(shader.handle, "cursor_enable");
|
||||||
attrib_position = glGetAttribLocation(shader.handle, "vert_position");
|
attrib_position = glGetAttribLocation(shader.handle, "vert_position");
|
||||||
attrib_tex_coord = glGetAttribLocation(shader.handle, "vert_tex_coord");
|
attrib_tex_coord = glGetAttribLocation(shader.handle, "vert_tex_coord");
|
||||||
}
|
}
|
||||||
|
|
@ -556,11 +561,17 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float x, fl
|
||||||
|
|
||||||
const u32 scale_factor = GetResolutionScaleFactor();
|
const u32 scale_factor = GetResolutionScaleFactor();
|
||||||
const GLuint sampler = samplers[Settings::values.filter_mode.GetValue()].handle;
|
const GLuint sampler = samplers[Settings::values.filter_mode.GetValue()].handle;
|
||||||
glUniform4f(uniform_i_resolution, static_cast<float>(screen_info.texture.width * scale_factor),
|
glUniform4f(uniform_i_resolution, static_cast<float>(screen_info.texture.height * scale_factor),
|
||||||
static_cast<float>(screen_info.texture.height * scale_factor),
|
static_cast<float>(screen_info.texture.width * scale_factor),
|
||||||
1.0f / static_cast<float>(screen_info.texture.width * scale_factor),
|
1.0f / static_cast<float>(screen_info.texture.height * scale_factor),
|
||||||
1.0f / static_cast<float>(screen_info.texture.height * scale_factor));
|
1.0f / static_cast<float>(screen_info.texture.width * scale_factor));
|
||||||
glUniform4f(uniform_o_resolution, h, w, 1.0f / h, 1.0f / w);
|
glUniform4f(uniform_o_resolution, w, h, 1.0f / w, 1.0f / h);
|
||||||
|
if (currScreenDraw == 1){
|
||||||
|
glUniform1i(uniform_cursor_enable, 1);
|
||||||
|
} else {
|
||||||
|
glUniform1i(uniform_cursor_enable, 0);
|
||||||
|
}
|
||||||
|
glUniform2f(uniform_cursor_pos, vCursor->cursorPos[0]/320.0f, vCursor->cursorPos[1]/240.0f);
|
||||||
state.texture_units[0].texture_2d = screen_info.display_texture;
|
state.texture_units[0].texture_2d = screen_info.display_texture;
|
||||||
state.texture_units[0].sampler = sampler;
|
state.texture_units[0].sampler = sampler;
|
||||||
state.Apply();
|
state.Apply();
|
||||||
|
|
@ -627,11 +638,17 @@ void RendererOpenGL::DrawSingleScreenStereo(const ScreenInfo& screen_info_l,
|
||||||
const u32 scale_factor = GetResolutionScaleFactor();
|
const u32 scale_factor = GetResolutionScaleFactor();
|
||||||
const GLuint sampler = samplers[Settings::values.filter_mode.GetValue()].handle;
|
const GLuint sampler = samplers[Settings::values.filter_mode.GetValue()].handle;
|
||||||
glUniform4f(uniform_i_resolution,
|
glUniform4f(uniform_i_resolution,
|
||||||
static_cast<float>(screen_info_l.texture.width * scale_factor),
|
|
||||||
static_cast<float>(screen_info_l.texture.height * scale_factor),
|
static_cast<float>(screen_info_l.texture.height * scale_factor),
|
||||||
1.0f / static_cast<float>(screen_info_l.texture.width * scale_factor),
|
static_cast<float>(screen_info_l.texture.width * scale_factor),
|
||||||
1.0f / static_cast<float>(screen_info_l.texture.height * scale_factor));
|
1.0f / static_cast<float>(screen_info_l.texture.height * scale_factor),
|
||||||
glUniform4f(uniform_o_resolution, h, w, 1.0f / h, 1.0f / w);
|
1.0f / static_cast<float>(screen_info_l.texture.width * scale_factor));
|
||||||
|
glUniform4f(uniform_o_resolution, w, h, 1.0f / w, 1.0f / h);
|
||||||
|
if (currScreenDraw == 1){
|
||||||
|
glUniform1i(uniform_cursor_enable, 1);
|
||||||
|
} else {
|
||||||
|
glUniform1i(uniform_cursor_enable, 0);
|
||||||
|
}
|
||||||
|
glUniform2f(uniform_cursor_pos, vCursor->cursorPos[0]/320.0f, vCursor->cursorPos[1]/240.0f);
|
||||||
state.texture_units[0].texture_2d = screen_info_l.display_texture;
|
state.texture_units[0].texture_2d = screen_info_l.display_texture;
|
||||||
state.texture_units[1].texture_2d = screen_info_r.display_texture;
|
state.texture_units[1].texture_2d = screen_info_r.display_texture;
|
||||||
state.texture_units[0].sampler = sampler;
|
state.texture_units[0].sampler = sampler;
|
||||||
|
|
@ -736,6 +753,7 @@ void RendererOpenGL::DrawTopScreen(const Layout::FramebufferLayout& layout,
|
||||||
if (!layout.top_screen_enabled) {
|
if (!layout.top_screen_enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
currScreenDraw = 0;
|
||||||
int leftside, rightside;
|
int leftside, rightside;
|
||||||
leftside = Settings::values.swap_eyes_3d.GetValue() ? 1 : 0;
|
leftside = Settings::values.swap_eyes_3d.GetValue() ? 1 : 0;
|
||||||
rightside = Settings::values.swap_eyes_3d.GetValue() ? 0 : 1;
|
rightside = Settings::values.swap_eyes_3d.GetValue() ? 0 : 1;
|
||||||
|
|
@ -797,7 +815,7 @@ void RendererOpenGL::DrawBottomScreen(const Layout::FramebufferLayout& layout,
|
||||||
if (!layout.bottom_screen_enabled) {
|
if (!layout.bottom_screen_enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
currScreenDraw = 1;
|
||||||
const float bottom_screen_left = static_cast<float>(bottom_screen.left);
|
const float bottom_screen_left = static_cast<float>(bottom_screen.left);
|
||||||
const float bottom_screen_top = static_cast<float>(bottom_screen.top);
|
const float bottom_screen_top = static_cast<float>(bottom_screen.top);
|
||||||
const float bottom_screen_width = static_cast<float>(bottom_screen.GetWidth());
|
const float bottom_screen_width = static_cast<float>(bottom_screen.GetWidth());
|
||||||
|
|
|
||||||
|
|
@ -107,9 +107,13 @@ private:
|
||||||
GLuint uniform_o_resolution;
|
GLuint uniform_o_resolution;
|
||||||
GLuint uniform_layer;
|
GLuint uniform_layer;
|
||||||
|
|
||||||
|
// Shader uniform for onscreen cursor
|
||||||
|
GLuint uniform_cursor_pos;
|
||||||
|
GLuint uniform_cursor_enable;
|
||||||
// Shader attribute input indices
|
// Shader attribute input indices
|
||||||
GLuint attrib_position;
|
GLuint attrib_position;
|
||||||
GLuint attrib_tex_coord;
|
GLuint attrib_tex_coord;
|
||||||
|
int currScreenDraw; // 0 is Top, 1 is Bottom
|
||||||
|
|
||||||
FrameDumperOpenGL frame_dumper;
|
FrameDumperOpenGL frame_dumper;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,8 @@ RendererVulkan::RendererVulkan(Core::System& system, Pica::PicaCore& pica_,
|
||||||
update_queue,
|
update_queue,
|
||||||
main_present_window.ImageCount()},
|
main_present_window.ImageCount()},
|
||||||
present_heap{instance, scheduler.GetMasterSemaphore(), PRESENT_BINDINGS, 32} {
|
present_heap{instance, scheduler.GetMasterSemaphore(), PRESENT_BINDINGS, 32} {
|
||||||
|
vCursor = new Cursor();
|
||||||
|
vCursor->setEmuWindow(&window);
|
||||||
CompileShaders();
|
CompileShaders();
|
||||||
BuildLayouts();
|
BuildLayouts();
|
||||||
BuildPipelines();
|
BuildPipelines();
|
||||||
|
|
@ -249,7 +251,7 @@ void RendererVulkan::RenderToWindow(PresentWindow& window, const Layout::Framebu
|
||||||
clear_color.float32[1] = Settings::values.bg_green.GetValue();
|
clear_color.float32[1] = Settings::values.bg_green.GetValue();
|
||||||
clear_color.float32[2] = Settings::values.bg_blue.GetValue();
|
clear_color.float32[2] = Settings::values.bg_blue.GetValue();
|
||||||
clear_color.float32[3] = 1.0f;
|
clear_color.float32[3] = 1.0f;
|
||||||
|
vCursor->update();
|
||||||
DrawScreens(frame, layout, flipped);
|
DrawScreens(frame, layout, flipped);
|
||||||
scheduler.Flush(frame->render_ready);
|
scheduler.Flush(frame->render_ready);
|
||||||
|
|
||||||
|
|
@ -783,11 +785,17 @@ void RendererVulkan::DrawSingleScreen(u32 screen_id, float x, float y, float w,
|
||||||
|
|
||||||
const u32 scale_factor = GetResolutionScaleFactor();
|
const u32 scale_factor = GetResolutionScaleFactor();
|
||||||
draw_info.i_resolution =
|
draw_info.i_resolution =
|
||||||
Common::MakeVec(static_cast<f32>(screen_info.texture.width * scale_factor),
|
Common::MakeVec(static_cast<f32>(screen_info.texture.height * scale_factor),
|
||||||
static_cast<f32>(screen_info.texture.height * scale_factor),
|
static_cast<f32>(screen_info.texture.width * scale_factor),
|
||||||
1.0f / static_cast<f32>(screen_info.texture.width * scale_factor),
|
1.0f / static_cast<f32>(screen_info.texture.height * scale_factor),
|
||||||
1.0f / static_cast<f32>(screen_info.texture.height * scale_factor));
|
1.0f / static_cast<f32>(screen_info.texture.width * scale_factor));
|
||||||
draw_info.o_resolution = Common::MakeVec(h, w, 1.0f / h, 1.0f / w);
|
draw_info.o_resolution = Common::MakeVec(w, h, 1.0f / w, 1.0f / h);
|
||||||
|
if (currScreenDraw == 1){
|
||||||
|
draw_info.cursor_enable = 1;
|
||||||
|
} else {
|
||||||
|
draw_info.cursor_enable = 0;
|
||||||
|
}
|
||||||
|
draw_info.cursor_pos = Common::MakeVec(vCursor->cursorPos[0]/320.0f, vCursor->cursorPos[1]/240.0f);
|
||||||
draw_info.screen_id_l = screen_id;
|
draw_info.screen_id_l = screen_id;
|
||||||
|
|
||||||
scheduler.Record([this, offset = offset, info = draw_info](vk::CommandBuffer cmdbuf) {
|
scheduler.Record([this, offset = offset, info = draw_info](vk::CommandBuffer cmdbuf) {
|
||||||
|
|
@ -855,11 +863,17 @@ void RendererVulkan::DrawSingleScreenStereo(u32 screen_id_l, u32 screen_id_r, fl
|
||||||
|
|
||||||
const u32 scale_factor = GetResolutionScaleFactor();
|
const u32 scale_factor = GetResolutionScaleFactor();
|
||||||
draw_info.i_resolution =
|
draw_info.i_resolution =
|
||||||
Common::MakeVec(static_cast<f32>(screen_info_l.texture.width * scale_factor),
|
Common::MakeVec(static_cast<f32>(screen_info_l.texture.height * scale_factor),
|
||||||
static_cast<f32>(screen_info_l.texture.height * scale_factor),
|
static_cast<f32>(screen_info_l.texture.width * scale_factor),
|
||||||
1.0f / static_cast<f32>(screen_info_l.texture.width * scale_factor),
|
1.0f / static_cast<f32>(screen_info_l.texture.height * scale_factor),
|
||||||
1.0f / static_cast<f32>(screen_info_l.texture.height * scale_factor));
|
1.0f / static_cast<f32>(screen_info_l.texture.width * scale_factor));
|
||||||
draw_info.o_resolution = Common::MakeVec(h, w, 1.0f / h, 1.0f / w);
|
draw_info.o_resolution = Common::MakeVec(w, h, 1.0f / w, 1.0f / h);
|
||||||
|
if (currScreenDraw == 1){
|
||||||
|
draw_info.cursor_enable = 1;
|
||||||
|
} else {
|
||||||
|
draw_info.cursor_enable = 0;
|
||||||
|
}
|
||||||
|
draw_info.cursor_pos = Common::MakeVec(vCursor->cursorPos[0]/320.0f, vCursor->cursorPos[1]/240.0f);
|
||||||
draw_info.screen_id_l = screen_id_l;
|
draw_info.screen_id_l = screen_id_l;
|
||||||
draw_info.screen_id_r = screen_id_r;
|
draw_info.screen_id_r = screen_id_r;
|
||||||
|
|
||||||
|
|
@ -886,6 +900,7 @@ void RendererVulkan::DrawTopScreen(const Layout::FramebufferLayout& layout,
|
||||||
if (!layout.top_screen_enabled) {
|
if (!layout.top_screen_enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
currScreenDraw = 0;
|
||||||
int leftside, rightside;
|
int leftside, rightside;
|
||||||
leftside = Settings::values.swap_eyes_3d.GetValue() ? 1 : 0;
|
leftside = Settings::values.swap_eyes_3d.GetValue() ? 1 : 0;
|
||||||
rightside = Settings::values.swap_eyes_3d.GetValue() ? 0 : 1;
|
rightside = Settings::values.swap_eyes_3d.GetValue() ? 0 : 1;
|
||||||
|
|
@ -944,7 +959,7 @@ void RendererVulkan::DrawBottomScreen(const Layout::FramebufferLayout& layout,
|
||||||
if (!layout.bottom_screen_enabled) {
|
if (!layout.bottom_screen_enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
currScreenDraw = 1;
|
||||||
const float bottom_screen_left = static_cast<float>(bottom_screen.left);
|
const float bottom_screen_left = static_cast<float>(bottom_screen.left);
|
||||||
const float bottom_screen_top = static_cast<float>(bottom_screen.top);
|
const float bottom_screen_top = static_cast<float>(bottom_screen.top);
|
||||||
const float bottom_screen_width = static_cast<float>(bottom_screen.GetWidth());
|
const float bottom_screen_width = static_cast<float>(bottom_screen.GetWidth());
|
||||||
|
|
@ -1007,7 +1022,6 @@ void RendererVulkan::DrawScreens(Frame* frame, const Layout::FramebufferLayout&
|
||||||
if (settings.shader_update_requested.exchange(false)) {
|
if (settings.shader_update_requested.exchange(false)) {
|
||||||
ReloadPipeline(layout.render_3d_mode);
|
ReloadPipeline(layout.render_3d_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
PrepareDraw(frame, layout);
|
PrepareDraw(frame, layout);
|
||||||
|
|
||||||
const auto& top_screen = layout.top_screen;
|
const auto& top_screen = layout.top_screen;
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/math_util.h"
|
#include "common/math_util.h"
|
||||||
|
#include "core/frontend/cursor.h"
|
||||||
#include "video_core/renderer_base.h"
|
#include "video_core/renderer_base.h"
|
||||||
#ifdef HAVE_LIBRETRO
|
#ifdef HAVE_LIBRETRO
|
||||||
#include "citra_libretro/libretro_vk.h"
|
#include "citra_libretro/libretro_vk.h"
|
||||||
|
|
@ -58,12 +59,14 @@ struct PresentUniformData {
|
||||||
std::array<f32, 4 * 4> modelview;
|
std::array<f32, 4 * 4> modelview;
|
||||||
Common::Vec4f i_resolution;
|
Common::Vec4f i_resolution;
|
||||||
Common::Vec4f o_resolution;
|
Common::Vec4f o_resolution;
|
||||||
|
Common::Vec2f cursor_pos;
|
||||||
|
int cursor_enable = 0;
|
||||||
int screen_id_l = 0;
|
int screen_id_l = 0;
|
||||||
int screen_id_r = 0;
|
int screen_id_r = 0;
|
||||||
int layer = 0;
|
int layer = 0;
|
||||||
int reverse_interlaced = 0;
|
int reverse_interlaced = 0;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(PresentUniformData) == 112,
|
static_assert(sizeof(PresentUniformData) == 124,
|
||||||
"PresentUniformData does not structure in shader!");
|
"PresentUniformData does not structure in shader!");
|
||||||
|
|
||||||
class RendererVulkan : public VideoCore::RendererBase {
|
class RendererVulkan : public VideoCore::RendererBase {
|
||||||
|
|
@ -151,6 +154,7 @@ private:
|
||||||
vk::ShaderModule cursor_fragment_shader{};
|
vk::ShaderModule cursor_fragment_shader{};
|
||||||
vk::Pipeline cursor_pipeline{};
|
vk::Pipeline cursor_pipeline{};
|
||||||
vk::UniquePipelineLayout cursor_pipeline_layout{};
|
vk::UniquePipelineLayout cursor_pipeline_layout{};
|
||||||
|
int currScreenDraw; // 0 is Top, 1 is Bottom
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue