mirror of
https://github.com/4yn/slidershim.git
synced 2025-02-01 20:18:07 +01:00
qol and bugfix
This commit is contained in:
parent
a8d72207a4
commit
fcf80538b4
@ -54,6 +54,15 @@ body {
|
||||
flex: 2 2 0;
|
||||
}
|
||||
|
||||
.serverlist {
|
||||
width: 100%;
|
||||
max-height: 5rem;
|
||||
overflow-x: auto;
|
||||
}
|
||||
.serverlist > pre {
|
||||
font-size: 0.75em;
|
||||
}
|
||||
|
||||
input,
|
||||
select {
|
||||
width: 100%;
|
||||
@ -89,6 +98,24 @@ button.primary {
|
||||
flex-flow: column nowrap;
|
||||
align-items: stretch;
|
||||
justify-content: flex-start;
|
||||
/* border: 0.125rem solid white; */
|
||||
}
|
||||
|
||||
.air {
|
||||
height: 2rem;
|
||||
display: flex;
|
||||
flex-flow: column-reverse nowrap;
|
||||
align-items: stretch;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.air-data {
|
||||
flex: 1 0;
|
||||
}
|
||||
.air-data-0 {
|
||||
background: #000;
|
||||
}
|
||||
.air-data-1 {
|
||||
background: #0aa;
|
||||
}
|
||||
|
||||
.ground {
|
||||
@ -143,3 +170,23 @@ button.primary {
|
||||
padding: 0.1rem 0;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.extra {
|
||||
height: 2rem;
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
align-items: stretch;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.extra-data {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
border-radius: 1rem;
|
||||
margin: 0.5rem;
|
||||
}
|
||||
.extra-data-0 {
|
||||
background: #000;
|
||||
}
|
||||
.extra-data-1 {
|
||||
background: #aaa;
|
||||
}
|
||||
|
2
src-tauri/Cargo.lock
generated
2
src-tauri/Cargo.lock
generated
@ -2850,7 +2850,7 @@ checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
|
||||
|
||||
[[package]]
|
||||
name = "slidershim"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"directories",
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "slidershim"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
description = "slidershim"
|
||||
authors = ["4yn"]
|
||||
license = ""
|
||||
|
@ -32,14 +32,9 @@ fn quit_app() {
|
||||
|
||||
fn main() {
|
||||
// Setup logger
|
||||
// env_logger::Builder::new()
|
||||
// .filter_level(log::LevelFilter::Debug)
|
||||
// .init();
|
||||
simple_logging::log_to_file(
|
||||
slider_io::Config::get_log_file_path().unwrap().as_path(),
|
||||
log::LevelFilter::Debug,
|
||||
)
|
||||
.unwrap();
|
||||
let log_file_path = slider_io::Config::get_log_file_path().unwrap();
|
||||
simple_logging::log_to_file(log_file_path.as_path(), log::LevelFilter::Debug).unwrap();
|
||||
// simple_logging::log_to_file("./log.txt", log::LevelFilter::Debug).unwrap();
|
||||
|
||||
let config = Arc::new(Mutex::new(Some(slider_io::Config::default())));
|
||||
let manager = Arc::new(Mutex::new(slider_io::Manager::new()));
|
||||
@ -114,6 +109,11 @@ fn main() {
|
||||
if let Ok(ips) = ips {
|
||||
app_handle.emit_all("listIps", &ips).unwrap();
|
||||
}
|
||||
|
||||
let log_file_path = slider_io::Config::get_log_file_path().unwrap();
|
||||
app_handle
|
||||
.emit_all("updateLogPath", log_file_path.as_path().to_str().unwrap())
|
||||
.unwrap();
|
||||
});
|
||||
|
||||
// UI update event
|
||||
|
52
src-tauri/src/slider_io/acio.rs
Normal file
52
src-tauri/src/slider_io/acio.rs
Normal file
@ -0,0 +1,52 @@
|
||||
// use serialport::SerialPort;
|
||||
// use std::io::{BufRead, BufReader};
|
||||
|
||||
// struct ArcadeSlider {
|
||||
// serial_port: BufReader<Box<dyn SerialPort>>,
|
||||
// }
|
||||
|
||||
// impl ArcadeSlider {
|
||||
// fn new() -> Self {
|
||||
// let serial_port = serialport::new("COM1", 152000).open().unwrap();
|
||||
// let serial_port_buf = BufReader::new(serial_port);
|
||||
// Self {
|
||||
// serial_port: serial_port_buf,
|
||||
// }
|
||||
// }
|
||||
|
||||
// fn recv(&mut self) {
|
||||
// let mut consumed = 0;
|
||||
// {
|
||||
// let d = self.serial_port.fill_buf().unwrap();
|
||||
|
||||
// let mut packets = vec![];
|
||||
// let mut packet = vec![];
|
||||
|
||||
// let mut bytes_taken = 0;
|
||||
// let mut in_escape = 0;
|
||||
// let mut checksum = 0;
|
||||
// for b in d.iter() {
|
||||
// bytes_taken += 1;
|
||||
|
||||
// match b {
|
||||
// 0xff => {
|
||||
// consumed += bytes_taken;
|
||||
// bytes_taken = 0;
|
||||
// in_escape = 0;
|
||||
// }
|
||||
// 0xfd => {
|
||||
// in_escape = 1;
|
||||
// }
|
||||
// _ => {
|
||||
// let b = b + in_escape;
|
||||
// in_escape = 0;
|
||||
// packet.push(b);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// self.serial_port.consume(consumed);
|
||||
// }
|
||||
|
||||
// fn send(&mut self) {}
|
||||
// }
|
@ -1,5 +1,5 @@
|
||||
use directories::ProjectDirs;
|
||||
use log::info;
|
||||
use log::{info, warn};
|
||||
use serde_json::Value;
|
||||
use std::{convert::TryFrom, fs, path::PathBuf};
|
||||
|
||||
@ -18,7 +18,12 @@ pub enum KeyboardLayout {
|
||||
Yuancon,
|
||||
Deemo,
|
||||
Voltex,
|
||||
GamepadVoltex,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum GamepadLayout {
|
||||
Voltex,
|
||||
Neardayo,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -28,6 +33,10 @@ pub enum OutputMode {
|
||||
layout: KeyboardLayout,
|
||||
sensitivity: u8,
|
||||
},
|
||||
Gamepad {
|
||||
layout: GamepadLayout,
|
||||
sensitivity: u8,
|
||||
},
|
||||
Websocket {
|
||||
url: String,
|
||||
},
|
||||
@ -97,8 +106,12 @@ impl Config {
|
||||
layout: KeyboardLayout::Voltex,
|
||||
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
||||
},
|
||||
"gamepad-voltex" => OutputMode::Keyboard {
|
||||
layout: KeyboardLayout::GamepadVoltex,
|
||||
"gamepad-voltex" => OutputMode::Gamepad {
|
||||
layout: GamepadLayout::Voltex,
|
||||
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
||||
},
|
||||
"gamepad-neardayo" => OutputMode::Gamepad {
|
||||
layout: GamepadLayout::Neardayo,
|
||||
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
||||
},
|
||||
"websocket" => OutputMode::Websocket {
|
||||
@ -185,7 +198,10 @@ impl Config {
|
||||
|
||||
pub fn default() -> Self {
|
||||
Self::load_saved()
|
||||
.or_else(|| Some(Self::factory()))
|
||||
.or_else(|| {
|
||||
warn!("Config loading from file failed, using default");
|
||||
Some(Self::factory())
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,12 @@ impl ControllerState {
|
||||
)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn flip_vert(&mut self) {
|
||||
for i in 0..16 {
|
||||
self.ground_state.swap(i * 2, i * 2 + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LedState {
|
||||
@ -81,6 +87,7 @@ impl FullState {
|
||||
let controller_state_handle = self.controller_state.lock().unwrap();
|
||||
buf.extend(controller_state_handle.ground_state);
|
||||
buf.extend(controller_state_handle.air_state);
|
||||
buf.extend(controller_state_handle.extra_state);
|
||||
};
|
||||
{
|
||||
let led_state_handle = self.led_state.lock().unwrap();
|
||||
|
@ -85,9 +85,10 @@ impl HidDeviceJob {
|
||||
for i in 0..32 {
|
||||
controller_state.ground_state[i] = bits[34 + i] * 255;
|
||||
}
|
||||
controller_state.flip_vert();
|
||||
|
||||
controller_state.air_state.copy_from_slice(&bits[28..34]);
|
||||
controller_state.extra_state.copy_from_slice(&bits[26..28]);
|
||||
controller_state.extra_state[0..2].copy_from_slice(&bits[26..28]);
|
||||
},
|
||||
WriteType::Bulk,
|
||||
|buf, led_state| {
|
||||
@ -121,10 +122,11 @@ impl HidDeviceJob {
|
||||
controller_state
|
||||
.ground_state
|
||||
.copy_from_slice(&buf.data[4..36]);
|
||||
controller_state.flip_vert();
|
||||
|
||||
let bits: Vec<u8> = (0..8).map(|x| (buf.data[3] >> x) & 1).collect();
|
||||
controller_state.air_state.copy_from_slice(&bits[2..8]);
|
||||
controller_state.extra_state.copy_from_slice(&bits[2..8]);
|
||||
controller_state.air_state.copy_from_slice(&bits[0..6]);
|
||||
controller_state.extra_state[0..2].copy_from_slice(&bits[6..8]);
|
||||
},
|
||||
WriteType::Bulk,
|
||||
|buf, led_state| {
|
||||
@ -159,8 +161,7 @@ impl HidDeviceJob {
|
||||
.ground_state
|
||||
.copy_from_slice(&buf.data[2..34]);
|
||||
for i in 0..6 {
|
||||
controller_state.air_state[i ^ 1] = 0;
|
||||
// controller_state.air_state[i ^ 1] = (buf.data[0] >> i) & 1;
|
||||
controller_state.air_state[i ^ 1] = (buf.data[0] >> i) & 1;
|
||||
}
|
||||
for i in 0..3 {
|
||||
controller_state.extra_state[i] = (buf.data[1] >> i) & 1;
|
||||
@ -230,8 +231,13 @@ impl ThreadJob for HidDeviceJob {
|
||||
{
|
||||
let res = handle
|
||||
.read_interrupt(self.read_endpoint, &mut self.read_buf.data, TIMEOUT)
|
||||
.map_err(|e| {
|
||||
// debug!("Device read error {}", &e);
|
||||
e
|
||||
})
|
||||
.unwrap_or(0);
|
||||
self.read_buf.len = res;
|
||||
// debug!("{:?}", self.read_buf.slice());
|
||||
if self.read_buf.len != 0 {
|
||||
let mut controller_state_handle = self.state.controller_state.lock().unwrap();
|
||||
(self.read_callback)(&self.read_buf, controller_state_handle.deref_mut());
|
||||
@ -250,11 +256,15 @@ impl ThreadJob for HidDeviceJob {
|
||||
|
||||
if self.led_buf.len != 0 {
|
||||
let res = (match self.led_write_type {
|
||||
WriteType::Bulk => handle.write_bulk(self.led_endpoint, &self.led_buf.data, TIMEOUT),
|
||||
WriteType::Bulk => handle.write_bulk(self.led_endpoint, self.led_buf.slice(), TIMEOUT),
|
||||
WriteType::Interrupt => {
|
||||
handle.write_interrupt(self.led_endpoint, &self.led_buf.data, TIMEOUT)
|
||||
handle.write_interrupt(self.led_endpoint, &self.led_buf.slice(), TIMEOUT)
|
||||
}
|
||||
})
|
||||
.map_err(|e| {
|
||||
// debug!("Device write error {}", e);
|
||||
e
|
||||
})
|
||||
.unwrap_or(0);
|
||||
if res == self.led_buf.len + 1 {
|
||||
self.led_buf.len = 0;
|
||||
|
@ -1,20 +1,26 @@
|
||||
use vigem_client::{Client, TargetId, XButtons, XGamepad, Xbox360Wired};
|
||||
|
||||
use crate::slider_io::{output::OutputHandler, voltex::VoltexState};
|
||||
use crate::slider_io::{config::GamepadLayout, output::OutputHandler, voltex::VoltexState};
|
||||
|
||||
pub struct GamepadOutput {
|
||||
target: Xbox360Wired<Client>,
|
||||
use_air: bool,
|
||||
gamepad: XGamepad,
|
||||
}
|
||||
|
||||
impl GamepadOutput {
|
||||
pub fn new() -> Self {
|
||||
pub fn new(layout: GamepadLayout) -> Self {
|
||||
let client = Client::connect().unwrap();
|
||||
let use_air = match layout {
|
||||
GamepadLayout::Neardayo => true,
|
||||
_ => false,
|
||||
};
|
||||
let mut target = Xbox360Wired::new(client, TargetId::XBOX360_WIRED);
|
||||
target.plugin().unwrap();
|
||||
target.wait_ready().unwrap();
|
||||
Self {
|
||||
target,
|
||||
use_air,
|
||||
gamepad: XGamepad::default(),
|
||||
}
|
||||
}
|
||||
@ -48,18 +54,18 @@ impl OutputHandler for GamepadOutput {
|
||||
}
|
||||
});
|
||||
|
||||
let lx = (match voltex_state.laser[0] {
|
||||
let lx = (match voltex_state.laser[0] || (self.use_air && flat_controller_state[34]) {
|
||||
true => -30000,
|
||||
false => 0,
|
||||
} + match voltex_state.laser[1] {
|
||||
} + match voltex_state.laser[1] || (self.use_air && flat_controller_state[35]) {
|
||||
true => 30000,
|
||||
false => 0,
|
||||
});
|
||||
|
||||
let rx = (match voltex_state.laser[2] {
|
||||
let rx = (match voltex_state.laser[2] || (self.use_air && flat_controller_state[36]) {
|
||||
true => -30000,
|
||||
false => 0,
|
||||
} + match voltex_state.laser[3] {
|
||||
} + match voltex_state.laser[3] || (self.use_air && flat_controller_state[37]) {
|
||||
true => 30000,
|
||||
false => 0,
|
||||
});
|
||||
|
@ -78,7 +78,6 @@ impl KeyboardOutput {
|
||||
KeyboardLayout::Yuancon => &YUANCON_KB_MAP,
|
||||
KeyboardLayout::Deemo => &DEEMO_KB_MAP,
|
||||
KeyboardLayout::Voltex => &VOLTEX_KB_MAP,
|
||||
_ => panic!("Not implemented"),
|
||||
};
|
||||
|
||||
let mut ground_to_idx = [0 as usize; 41];
|
||||
|
@ -5,6 +5,7 @@ mod worker;
|
||||
mod controller_state;
|
||||
mod voltex;
|
||||
|
||||
mod acio;
|
||||
mod brokenithm;
|
||||
mod gamepad;
|
||||
mod keyboard;
|
||||
|
@ -1,11 +1,8 @@
|
||||
use std::{thread, time::Duration};
|
||||
|
||||
use crate::slider_io::{
|
||||
config::{KeyboardLayout, OutputMode},
|
||||
controller_state::FullState,
|
||||
gamepad::GamepadOutput,
|
||||
keyboard::KeyboardOutput,
|
||||
worker::ThreadJob,
|
||||
config::OutputMode, controller_state::FullState, gamepad::GamepadOutput,
|
||||
keyboard::KeyboardOutput, worker::ThreadJob,
|
||||
};
|
||||
|
||||
pub trait OutputHandler: Send {
|
||||
@ -28,10 +25,15 @@ impl OutputJob {
|
||||
} => Self {
|
||||
state: state.clone(),
|
||||
sensitivity: *sensitivity,
|
||||
handler: match layout {
|
||||
KeyboardLayout::GamepadVoltex => Box::new(GamepadOutput::new()),
|
||||
layout => Box::new(KeyboardOutput::new(layout.clone())),
|
||||
},
|
||||
handler: Box::new(KeyboardOutput::new(layout.clone())),
|
||||
},
|
||||
OutputMode::Gamepad {
|
||||
layout,
|
||||
sensitivity,
|
||||
} => Self {
|
||||
state: state.clone(),
|
||||
sensitivity: *sensitivity,
|
||||
handler: Box::new(GamepadOutput::new(layout.clone())),
|
||||
},
|
||||
_ => panic!("Not implemented"),
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ impl Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
fn slice(&self) -> &[u8] {
|
||||
pub fn slice(&self) -> &[u8] {
|
||||
&self.data[0..self.len]
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"package": {
|
||||
"productName": "slidershim",
|
||||
"version": "0.1.0"
|
||||
"version": "0.1.1"
|
||||
},
|
||||
"build": {
|
||||
"distDir": "../public",
|
||||
@ -60,7 +60,7 @@
|
||||
{
|
||||
"title": "slidershim",
|
||||
"width": 500,
|
||||
"height": 500,
|
||||
"height": 550,
|
||||
"resizable": false,
|
||||
"fullscreen": false
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import { emit, listen } from "@tauri-apps/api/event";
|
||||
import { open } from "@tauri-apps/api/shell";
|
||||
|
||||
import Link from "./Link.svelte";
|
||||
import Preview from "./Preview.svelte";
|
||||
@ -27,6 +28,7 @@
|
||||
let polling = null;
|
||||
let tick = 0;
|
||||
let previewData = Array(131).fill(0);
|
||||
let logfile = "";
|
||||
|
||||
function updatePolling(enabled) {
|
||||
if (!!polling) {
|
||||
@ -67,6 +69,10 @@
|
||||
);
|
||||
});
|
||||
|
||||
await listen("updateLogPath", (event) => {
|
||||
logfile = event.payload as string;
|
||||
});
|
||||
|
||||
await emit("ready", "");
|
||||
|
||||
updatePolling(true);
|
||||
@ -106,6 +112,10 @@
|
||||
async function quit() {
|
||||
await emit("quit", "");
|
||||
}
|
||||
|
||||
async function logs() {
|
||||
await open(logfile);
|
||||
}
|
||||
</script>
|
||||
|
||||
<main class="main">
|
||||
@ -138,10 +148,12 @@
|
||||
<div class="row">
|
||||
<div class="label" />
|
||||
<div class="input">
|
||||
Brokenithm open at:
|
||||
<pre>
|
||||
{ips.map((x) => `http://${x}:1606/`).join("\n")}
|
||||
</pre>
|
||||
<div class="serverlist">
|
||||
Brokenithm open at:
|
||||
<pre>
|
||||
{ips.map((x) => `http://${x}:1606/`).join("\n")}
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
@ -156,6 +168,9 @@
|
||||
<option value="kb-8-deemo">Keyboard 8-zone, Deemo Layout</option>
|
||||
<option value="kb-voltex">Keyboard 10-zone, Voltex Layout</option>
|
||||
<option value="gamepad-voltex">XBOX 360 Gamepad, Voltex Layout</option>
|
||||
<option value="gamepad-neardayo"
|
||||
>XBOX 360 Gamepad, Neardayo Layout</option
|
||||
>
|
||||
<!-- <option value="websocket">Websocket</option> -->
|
||||
</select>
|
||||
</div>
|
||||
@ -299,6 +314,9 @@
|
||||
>
|
||||
<button on:click={async () => await hide()}>Hide</button>
|
||||
<button on:click={async () => await quit()}>Quit</button>
|
||||
{#if !!logfile.length}
|
||||
<button on:click={async () => await logs()}>Logs</button>
|
||||
{/if}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
let topDatas = Array(16).fill(0);
|
||||
let botDatas = Array(16).fill(0);
|
||||
let airDatas = Array(6).fill(0);
|
||||
let extraDatas = Array(3).fill(0);
|
||||
let ledDatas = Array(31)
|
||||
.fill(0)
|
||||
.map((_, idx) => ({
|
||||
@ -11,15 +13,22 @@
|
||||
}));
|
||||
|
||||
$: {
|
||||
if (data.length === 131) {
|
||||
if (data.length === 134) {
|
||||
// console.log(data);
|
||||
for (let i = 0; i < 16; i++) {
|
||||
topDatas[i] = data[i * 2 + 1];
|
||||
botDatas[i] = data[i * 2];
|
||||
}
|
||||
for (let i = 0; i < 6; i++) {
|
||||
airDatas[i] = data[32 + i];
|
||||
}
|
||||
for (let i = 0; i < 3; i++) {
|
||||
extraDatas[i] = data[38 + i];
|
||||
}
|
||||
|
||||
for (let i = 0; i < 31; i++) {
|
||||
ledDatas[i].color = `rgb(${data[38 + i * 3]}, ${data[39 + i * 3]}, ${
|
||||
data[40 + i * 3]
|
||||
ledDatas[i].color = `rgb(${data[41 + i * 3]}, ${data[42 + i * 3]}, ${
|
||||
data[43 + i * 3]
|
||||
})`;
|
||||
}
|
||||
}
|
||||
@ -27,7 +36,11 @@
|
||||
</script>
|
||||
|
||||
<main class="preview">
|
||||
<div class="air" />
|
||||
<div class="air">
|
||||
{#each airDatas as airData, idx (idx)}
|
||||
<div class={`air-data air-data-${airData}`} />
|
||||
{/each}
|
||||
</div>
|
||||
<div class="ground">
|
||||
<div class="ground-led">
|
||||
<div class="ground-row">
|
||||
@ -54,4 +67,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="extra">
|
||||
{#each extraDatas as extraData, idx (idx)}
|
||||
<div class={`extra-data extra-data-${extraData}`} />
|
||||
{/each}
|
||||
</div>
|
||||
</main>
|
||||
|
Loading…
x
Reference in New Issue
Block a user