Skip to content

Commit

Permalink
added mouse-speed and mouse-flick modules
Browse files Browse the repository at this point in the history
  • Loading branch information
Zergatul committed Dec 30, 2021
1 parent 70f6b3e commit 40f0a26
Show file tree
Hide file tree
Showing 8 changed files with 293 additions and 3 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Input overlay plugin for OBS. Supported systems: Windows 10 x64
- Check `Use custom framerate`, and set FPS to `60`, if you are streaming/recording in 60 FPS
- Check `Shutdown source when not visible`. This will allow you to hide/show source after you restarted the server
- Do the same for mouse: `URL`: `http://localhost:5001/default-mouse.html`, `Width`: `250`, `Height`: `350`
- If you want mouse movement indicator, use this: `http://localhost:5001/mouse-movement.html`, `Width`: `800`, `Height`: `800`
- ![Other modules](docs/Modules.md)

![keyboard source](https://github.com/Zergatul/Zergatul.Obs.InputOverlay/blob/master/docs/keyboard-source.png?raw=true)

Expand All @@ -24,7 +24,7 @@ Input overlay plugin for OBS. Supported systems: Windows 10 x64
2. You can show more keys, change style, colors, animations if you are familiar with HTML and CSS. Check `wwwroot` folder within application folder. It contains HTML, CSS and JavaScript files. You can get all supported key names from [KeyboardButton.cs](src/Keyboard/KeyboardButton.cs) file.
3. [Customizing mouse](docs/CustomizingMouse.md).
4. If you need to restart server application, you will need to hide sources in OBS, and show them again.
5. If you want to play on one PC, and run OBS on another you need to run executable with parameter: `--urls http://<IP address>:<port>/`. IP address should be local network address of PC where you play game and run executable. You can choose port whatever you like, but it is better not use ports lower than 1000. If you have firewall make use you opened incoming TCP port. Example: `Zergatul.Obs.InputOverlay.exe --urls http://192.168.1.123:12345/`. If everything is fine, you should see in the log: `Now listening on: http://192.168.1.123:12345`.
5. If you want to play on one PC, and run OBS on another you need to run executable with parameter: `--urls http://<IP address>:<port>/`. IP address should be local network address of PC where you play game and run executable. You can choose port whatever you like, but it is better not use ports lower than 1000. If you have firewall make sure you opened incoming TCP port. Example: `Zergatul.Obs.InputOverlay.exe --urls http://192.168.1.123:12345/`. If everything is fine, you should see in the log: `Now listening on: http://192.168.1.123:12345`.

# Troubleshooting
If you encounter any problems with running Browser Source in OBS, you can open keyboard/mouse URL's in your browser and check for errors in developer console. In `<style>` element uncomment line: `background-color: black;`. Now open URL in your browser with Developer Tools opened (usually this is `F12` key). Don't forget to comment out this line again if you start using overlay in OBS. Sometimes browser source in OBS caches styles, you can use `Refresh cache of current page` button.
Expand Down
16 changes: 16 additions & 0 deletions docs/Modules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Modules

## Mouse speed (`mouse-speed.html`)
Displays mouse speed overlay. Open file in text editor to adjust settings. Browser source parameters: Width: `500`, Height: `100`.

![mouse-speed.html example](https://github.com/Zergatul/Zergatul.Obs.InputOverlay/blob/master/docs/MouseSpeed.png?raw=true)

## Mouse movement (`mouse-movement.html`)
Displays circle indicating current mouse movement direction. Open file in text editor to adjust settings. Browser source parameters: Width: `800`, Height: `800`.

![mouse-movement.html example](https://github.com/Zergatul/Zergatul.Obs.InputOverlay/blob/master/docs/MouseMovement.png?raw=true)

## Flicks (`mouse-flick.html`)
Displays text when you perform flick in FPV games (in other words when mouse moves some distance horizontally at some period of time). Open file in text editor to adjust settings. Browser source parameters: Width: `300`, Height: `100`.

![mouse-flick.html example](https://github.com/Zergatul/Zergatul.Obs.InputOverlay/blob/master/docs/MouseFlick.png?raw=true)
Binary file added docs/MouseFlick.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/MouseMovement.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/MouseSpeed.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 7 additions & 1 deletion src/Zergatul.Obs.InputOverlay.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<RootNamespace>Zergatul.Obs.InputOverlay</RootNamespace>
<Authors>Zergatul</Authors>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<Version>2.0.0</Version>
<Version>2.0.1</Version>
<SupportedOSPlatformVersion>7.0</SupportedOSPlatformVersion>
<StartupObject>Zergatul.Obs.InputOverlay.Program</StartupObject>
<PackageProjectUrl>https://github.com/Zergatul/Zergatul.Obs.InputOverlay</PackageProjectUrl>
Expand All @@ -30,9 +30,15 @@
<Content Update="wwwroot\default-mouse.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\mouse-flick.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\mouse-movement.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\mouse-speed.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\mouse.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
Expand Down
121 changes: 121 additions & 0 deletions src/wwwroot/mouse-flick.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script>
// ms, check mouse horizontal movement in this time interval
const checkingInterval = 400;

// in mouse raw units
// adjust this to match your DPI and mouse sensitivity in game
const flickMovementThreshold = 1000;

// milliseconds, without fadeout animation
const textDisplayInterval = 250;
</script>
<style>
body {
/*background-color: black;*/ /* uncomment this to debug in browser */
margin: 0;
padding: 0;
overflow: hidden;
text-align: center;
}
#mouse-flick {
display: inline-block;
color: red;
text-shadow: 0 0 4px rgb(253, 253, 18);
font-family: Verdana;
font-size: 60px;
}
#mouse-flick.fadeout {
animation: fadeout 0.25s ease-out; /* fade animation */
animation-fill-mode: forwards;
}
@keyframes fadeout {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
</style>
<script>
let listHead = null;
let listTail = null;
let deltaX = 0;
let state = null;

function listenWebSocket() {
let ws = new WebSocket('ws://' + location.host + '/ws');
ws.onopen = function () {
// listen for MoveEvent's
ws.send(JSON.stringify({ listen: 'RawMouseMovement' }));
};
ws.onmessage = function (event) {
var data = JSON.parse(event.data);

if (data.type == 'Ping') {
// reply to ping messages
ws.send(JSON.stringify({ ping: data.ping }));
return;
}

if (data.type == 'RawMouseMovement') {
// MoveEvent
processEvent(data);
}
};
}

function processEvent(evt) {
let now = window.performance.now();
evt.time = now;
if (listHead == null) {
listHead = listTail = evt;
deltaX = evt.dx;
return;
} else {
listTail.next = evt;
listTail = evt;
deltaX += evt.dx;
}

while (listHead && (now - listHead.time) > checkingInterval) {
deltaX -= listHead.dx;
listHead = listHead.next;
if (!listHead) {
listTail = null;
}
}

if (Math.abs(deltaX) > flickMovementThreshold && state == null) {
let div = document.getElementById('mouse-flick');
div.style.display = '';
div.classList.remove('fadeout');
state = 'show';
listHead = listTail = null;
deltaX = 0;
setTimeout(function () {
div.classList.add('fadeout');
state = null;
}, textDisplayInterval);
}
}

function initDiv() {
let div = document.getElementById('mouse-flick');
div.style.display = 'none';
}

document.addEventListener('DOMContentLoaded', function() {
initDiv();
listenWebSocket();
});
</script>
</head>
<body>
<div id="mouse-flick">Flick!</div>
</body>
</html>
147 changes: 147 additions & 0 deletions src/wwwroot/mouse-speed.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script>
// raw mouse sensitivy, also called DPI
const cpi = 1200;

// speed value will be updated only after specified period
const refreshMs = 100;

const decimals = 2;

// this is just for visual, no effect on value displayed
const units = 'inch/sec';

// speed in inches/sec is multiplied by this value, you can use this settings to convert to different units
const multiplier = 1;
// const multiplier = 1.0 / 39; // meters per second
// const multiplier = 1.0 / 10.936; // km/hour
// const multiplier = 1.0 / 17.6; // miles/hour

// use this table to specify color gradient for different speed values
// first element should always have value=0
const gradientTable = [
// red/green/blue [0..256), opacity [0..1], speed - mouse speed
{ red: 255, green: 255, blue: 255, opacity: 1.0, speed: 0.0 }, // white at speed=0
{ red: 255, green: 255, blue: 71, opacity: 1.0, speed: 10 }, // yellow at speed=10
{ red: 255, green: 71, blue: 71, opacity: 1.0, speed: 20 }, // red at speed = 20

// single color example
// uncomment line below to use it, and remove above lines
// { red: 255, green: 255, blue: 255, opacity: 1.0, speed: 0.0 }
];
</script>
<style>
body {
/*background-color: black;*/ /* uncomment this to debug in browser */
margin: 0;
padding: 0;
overflow: hidden;
text-align: center;
}
#mouse-speed {
display: inline-block;
font-family: Verdana;
font-size: 60px;
}
</style>
<script>
let queue = new Array();

function listenWebSocket() {
let ws = new WebSocket('ws://' + location.host + '/ws');
ws.onopen = function () {
// listen for MoveEvent's
ws.send(JSON.stringify({ listen: 'RawMouseMovement' }));
};
ws.onmessage = function (event) {
var data = JSON.parse(event.data);

if (data.type == 'Ping') {
// reply to ping messages
ws.send(JSON.stringify({ ping: data.ping }));
return;
}

if (data.type == 'RawMouseMovement') {
// MoveEvent
queue.push(data);
}
};
}

function startRefreshTimer() {
let hex = function (val) {
if (val < 0) {
val = 0;
}
if (val >= 256) {
val = 255;
}
if (val < 16) {
return '0' + val.toString(16);
} else {
return val.toString(16);
}
};
setInterval(function () {
let distance = 0;
for (let i = 0; i < queue.length; i++) {
let dx = queue[i].dx;
let dy = queue[i].dy;
distance += Math.sqrt(dx * dx + dy * dy);
}
queue.splice(0, queue.length);
let speedInchPerSec = 1000 * distance / refreshMs / cpi;
let speed = multiplier * speedInchPerSec;

let element = document.getElementById('mouse-speed');
element.innerText = speed.toFixed(decimals) + ' ' + units;

let curr = null;
let next = null;
for (let i = 0; i < gradientTable.length; i++) {
if (gradientTable[i].speed >= speed) {
next = gradientTable[i];
if (i > 0) {
curr = gradientTable[i - 1];
} else {
curr = next;
}
break;
}
}

if (next == null) {
curr = next = gradientTable[gradientTable.length - 1];
}

let delta = next.speed - curr.speed;
if (delta == 0) {
element.style.color = '#' + hex(curr.red) + hex(curr.green) + hex(curr.blue);
element.style.opacity = curr.opacity;
} else {
let factor = (speed - curr.speed) / delta;
let r = curr.red + Math.round((next.red - curr.red) * factor);
let g = curr.green + Math.round((next.green - curr.green) * factor);
let b = curr.blue + Math.round((next.blue - curr.blue) * factor);
let o = curr.opacity + (next.opacity - curr.opacity) * factor;
element.style.color = '#' + hex(r) + hex(g) + hex(b);
element.style.opacity = Math.round(o * 1000) / 1000;
}

}, refreshMs);
}

document.addEventListener('DOMContentLoaded', function() {
listenWebSocket();
startRefreshTimer();
});
</script>
</head>
<body>
<div id="mouse-speed"></div>
</body>
</html>

0 comments on commit 40f0a26

Please sign in to comment.