Skip to content

Commit

Permalink
Input: Threading and Mouse Mode for gamepad
Browse files Browse the repository at this point in the history
  • Loading branch information
TheElixZammuto committed Jul 31, 2021
1 parent 584d293 commit f3119e0
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 15 deletions.
5 changes: 3 additions & 2 deletions MenuPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@

<StackPanel Padding="64">
<TextBlock FontSize="24">Moonlight</TextBlock>
<TextBlock Height="60">Experimental Software Ahead! Here be dragons!</TextBlock>
<TextBlock Margin="0,0,0,10">Experimental Software Ahead! Here be dragons!</TextBlock>
<TextBlock Margin="0,0,0,30">Mouse Mode: Press Menu+View+LB+RB+Y to enable it.<LineBreak></LineBreak>Move the pointer with the left stick, scroll with the right one<LineBreak></LineBreak>A button is the left mouse button, X is the right one</TextBlock>
<TextBlock>IP Address or Hostname:</TextBlock>
<StackPanel Orientation="Horizontal" XYFocusKeyboardNavigation="Enabled">
<TextBox Width="128" x:Name="ipAddressText" HorizontalAlignment="Left"></TextBox>
Expand All @@ -21,7 +22,7 @@
<StackPanel x:Name="appsPanel">
<TextBlock>Applications</TextBlock>
<StackPanel x:Name="appsGrid">

</StackPanel>
</StackPanel>
</StackPanel>
Expand Down
12 changes: 8 additions & 4 deletions MoonlightClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,14 @@ void MoonlightClient::SendMousePosition(float deltaX, float deltaY) {
LiSendMouseMoveEvent(deltaX, deltaY);
}

void MoonlightClient::SendMousePressed() {
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT);
void MoonlightClient::SendMousePressed(int button) {
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, button);
}

void MoonlightClient::SendMouseReleased() {
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
void MoonlightClient::SendMouseReleased(int button) {
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, button);
}

void MoonlightClient::SendScroll(float value) {
LiSendScrollEvent((signed char)(value * 2.0f));
}
5 changes: 3 additions & 2 deletions MoonlightClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ namespace moonlight_xbox_dx {
std::vector<std::wstring> GetLogLines();
void InsertLog(const char* msg);
void SendMousePosition(float x, float y);
void SendMousePressed();
void SendMouseReleased();
void SendMousePressed(int button);
void SendMouseReleased(int button);
void SendScroll(float value);
private:
SERVER_DATA serverData;
char* connectionPin = NULL;
Expand Down
77 changes: 70 additions & 7 deletions moonlight_xbox_dxMain.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "pch.h"
#include "moonlight_xbox_dxMain.h"
#include "Common\DirectXHelper.h"
using namespace Windows::Gaming::Input;


using namespace moonlight_xbox_dx;
Expand Down Expand Up @@ -62,26 +63,35 @@ void moonlight_xbox_dxMain::StartRenderLoop()
m_deviceResources->GetD3DDeviceContext()->Flush();
m_deviceResources->Present();
}
int t2 = GetTickCount64();
char msg[2084];
//sprintf(msg, "Got %d ms of rendering time\n", t2 - t1);
//OutputDebugStringA(msg);
}
});
m_renderLoopWorker = ThreadPool::RunAsync(workItemHandler, WorkItemPriority::High, WorkItemOptions::TimeSliced);
if (m_inputLoopWorker != nullptr && m_inputLoopWorker->Status == AsyncStatus::Started) {
return;
}
auto inputItemHandler = ref new WorkItemHandler([this](IAsyncAction^ action)
{
// Calculate the updated frame and render once per vertical blanking interval.
while (action->Status == AsyncStatus::Started)
{
ProcessInput();
Sleep(8); // 8ms = about 120Hz of polling rate (i guess)
}
});

// Run task on a dedicated high priority background thread.
m_renderLoopWorker = ThreadPool::RunAsync(workItemHandler, WorkItemPriority::High, WorkItemOptions::TimeSliced);
m_inputLoopWorker = ThreadPool::RunAsync(inputItemHandler, WorkItemPriority::High, WorkItemOptions::TimeSliced);
}

void moonlight_xbox_dxMain::StopRenderLoop()
{
m_renderLoopWorker->Cancel();
m_inputLoopWorker->Cancel();
}

// Updates the application state once per frame.
void moonlight_xbox_dxMain::Update()
{
ProcessInput();

// Update scene objects.
m_timer.Tick([&]()
Expand All @@ -95,12 +105,65 @@ void moonlight_xbox_dxMain::Update()
// Process all input from the user before updating game state
void moonlight_xbox_dxMain::ProcessInput()
{

MoonlightClient *client = MoonlightClient::GetInstance();
auto gamepads = Windows::Gaming::Input::Gamepad::Gamepads;
if (gamepads->Size == 0)return;
Windows::Gaming::Input::Gamepad^ gamepad = gamepads->GetAt(0);
auto reading = gamepad->GetCurrentReading();
client->SendGamepadReading(reading);
//If this combination is pressed on gamed we should handle some magic things :)
GamepadButtons magicKey[] = { GamepadButtons::LeftShoulder,GamepadButtons::RightShoulder,GamepadButtons::Menu,GamepadButtons::View };
bool isCurrentlyPressed = true;
for (auto k : magicKey) {
if ((reading.Buttons & k) != k) {
isCurrentlyPressed = false;
break;
}
}
if (isCurrentlyPressed) {
if (magicCombinationPressed)return;
if ((reading.Buttons & GamepadButtons::Y) == GamepadButtons::Y) {
client->InsertLog("Mouse mode ");
client->InsertLog(mouseMode ? "disabled\n" : "enabled\n");
mouseMode = !mouseMode;
magicCombinationPressed = true;
}
}
else {
magicCombinationPressed = false;
}
//If mouse mode is enabled the gamepad acts as a mouse, instead we pass the raw events to the host
if (mouseMode) {
//Position
client->SendMousePosition(reading.LeftThumbstickX * 5, reading.LeftThumbstickY * -5);
//Left Click
if ((reading.Buttons & GamepadButtons::A) == GamepadButtons::A) {
if (!leftMouseButtonPressed) {
leftMouseButtonPressed = true;
client->SendMousePressed(BUTTON_LEFT);
}
}
else if (leftMouseButtonPressed) {
leftMouseButtonPressed = false;
client->SendMouseReleased(BUTTON_LEFT);
}
//Right Click
if ((reading.Buttons & GamepadButtons::X) == GamepadButtons::X) {
if (!rightMouseButtonPressed) {
rightMouseButtonPressed = true;
client->SendMousePressed(BUTTON_RIGHT);
}
}
else if (rightMouseButtonPressed) {
rightMouseButtonPressed = false;
client->SendMouseReleased(BUTTON_RIGHT);
}
//Scroll
client->SendScroll(reading.RightThumbstickY);
}
else {
client->SendGamepadReading(reading);
}

}

Expand Down
5 changes: 5 additions & 0 deletions moonlight_xbox_dxMain.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,17 @@ namespace moonlight_xbox_dx
std::unique_ptr<SampleFpsTextRenderer> m_fpsTextRenderer;

Windows::Foundation::IAsyncAction^ m_renderLoopWorker;
Windows::Foundation::IAsyncAction^ m_inputLoopWorker;
Concurrency::critical_section m_criticalSection;

// Rendering loop timer.
DX::StepTimer m_timer;

// Track current input pointer position.
float m_pointerLocationX;
bool magicCombinationPressed = false;
bool mouseMode = false;
bool leftMouseButtonPressed = false;
bool rightMouseButtonPressed = false;
};
}

0 comments on commit f3119e0

Please sign in to comment.