1
0
mirror of https://github.com/4yn/slidershim.git synced 2024-11-27 15:00:49 +01:00

add 4k/6k layouts and reactive color customization

This commit is contained in:
4yn 2022-03-23 01:06:16 +08:00
parent 3a3e339aca
commit 2fb8995e68
5 changed files with 172 additions and 24 deletions

View File

@ -3,10 +3,50 @@ use serde_json::Value;
#[derive(Debug, Clone, Copy)]
pub enum ReactiveLayout {
Even { splits: usize },
Six,
Voltex,
Rainbow,
}
#[derive(Debug, Clone)]
pub struct ColorScheme {
pub active: [u8; 3],
pub inactive: [u8; 3],
}
impl ColorScheme {
pub fn from_serde_value(v: &Value) -> Option<Self> {
Some(Self {
active: [
u8::from_str_radix(&v["ledColorActive"].as_str()?[1..3], 16).ok()?,
u8::from_str_radix(&v["ledColorActive"].as_str()?[3..5], 16).ok()?,
u8::from_str_radix(&v["ledColorActive"].as_str()?[5..7], 16).ok()?,
],
inactive: [
u8::from_str_radix(&v["ledColorInactive"].as_str()?[1..3], 16).ok()?,
u8::from_str_radix(&v["ledColorInactive"].as_str()?[3..5], 16).ok()?,
u8::from_str_radix(&v["ledColorInactive"].as_str()?[5..7], 16).ok()?,
],
})
}
pub fn default() -> Self {
Self {
active: [255, 0, 255],
inactive: [255, 255, 0],
}
}
pub fn from_serde_value_or_default(v: &Value) -> Self {
Self::from_serde_value(v)
.or(Some(Self {
active: [255, 0, 255],
inactive: [255, 255, 0],
}))
.unwrap()
}
}
#[derive(Debug, Clone)]
pub enum LightsMode {
None,
@ -14,6 +54,7 @@ pub enum LightsMode {
faster: bool,
layout: ReactiveLayout,
sensitivity: u8,
color: ColorScheme,
},
Attract {
faster: bool,
@ -32,30 +73,41 @@ impl LightsMode {
pub fn from_serde_value(v: &Value) -> Option<Self> {
Some(match v["ledMode"].as_str()? {
"none" => LightsMode::None,
"reactive-4" => LightsMode::Reactive {
"reactive-16" => LightsMode::Reactive {
faster: v["ledFaster"].as_bool()?,
layout: ReactiveLayout::Even { splits: 4 },
layout: ReactiveLayout::Even { splits: 16 },
sensitivity: u8::try_from(v["ledSensitivity"].as_i64()?).ok()?,
color: ColorScheme::from_serde_value_or_default(v),
},
"reactive-8" => LightsMode::Reactive {
faster: v["ledFaster"].as_bool()?,
layout: ReactiveLayout::Even { splits: 8 },
sensitivity: u8::try_from(v["ledSensitivity"].as_i64()?).ok()?,
color: ColorScheme::from_serde_value_or_default(v),
},
"reactive-16" => LightsMode::Reactive {
"reactive-6" => LightsMode::Reactive {
faster: v["ledFaster"].as_bool()?,
layout: ReactiveLayout::Even { splits: 16 },
layout: ReactiveLayout::Six,
sensitivity: u8::try_from(v["ledSensitivity"].as_i64()?).ok()?,
color: ColorScheme::from_serde_value_or_default(v),
},
"reactive-4" => LightsMode::Reactive {
faster: v["ledFaster"].as_bool()?,
layout: ReactiveLayout::Even { splits: 4 },
sensitivity: u8::try_from(v["ledSensitivity"].as_i64()?).ok()?,
color: ColorScheme::from_serde_value_or_default(v),
},
"reactive-rainbow" => LightsMode::Reactive {
faster: v["ledFaster"].as_bool()?,
layout: ReactiveLayout::Rainbow,
sensitivity: u8::try_from(v["ledSensitivity"].as_i64()?).ok()?,
color: ColorScheme::default(),
},
"reactive-voltex" => LightsMode::Reactive {
faster: v["ledFaster"].as_bool()?,
layout: ReactiveLayout::Voltex,
sensitivity: u8::try_from(v["ledSensitivity"].as_i64()?).ok()?,
color: ColorScheme::default(),
},
"attract" => LightsMode::Attract {
faster: v["ledFaster"].as_bool()?,

View File

@ -48,8 +48,8 @@ impl LightsJob {
serial_buffer: Option<&Buffer>,
lights: &mut SliderLights,
) {
match self.mode {
LightsMode::Reactive { layout, .. } => {
match &self.mode {
LightsMode::Reactive { layout, color, .. } => {
let flat_input = flat_input.unwrap();
match layout {
@ -58,23 +58,55 @@ impl LightsJob {
let banks: Vec<bool> = flat_input
.chunks(32 / splits)
.take(splits)
.take(*splits)
.map(|x| x.contains(&true))
.collect();
for idx in 0..31 {
lights.paint(
idx,
match (idx + 1) % buttons_per_split {
0 => &[255, 0, 255],
match ((idx + 1) % buttons_per_split, (idx + 1) % 2) {
(0, _) => &color.active,
(_, 0) => &color.inactive,
_ => match banks[idx / buttons_per_split] {
true => &[255, 0, 255],
false => &[255, 255, 0],
true => &color.active,
false => &color.inactive,
},
},
);
}
}
ReactiveLayout::Six => {
let banks: Vec<bool> = [0..6, 6..10, 10..16, 16..22, 22..26, 26..32]
.into_iter()
.map(|x| flat_input[x].contains(&true))
.collect();
for idx in (1..31).step_by(2) {
lights.paint(
idx,
match idx {
5 | 9 | 15 | 21 | 25 => &color.active,
_ => &color.inactive,
},
);
}
for (bank_idxs, bank_val) in [0..6, 6..10, 10..16, 16..22, 22..26, 26..32]
.into_iter()
.zip(banks)
{
for idx in bank_idxs.step_by(2) {
lights.paint(
idx,
match bank_val {
true => &color.active,
false => &color.inactive,
},
)
}
}
}
ReactiveLayout::Voltex => {
lights.ground.fill(0);

View File

@ -14,7 +14,9 @@ pub enum KeyboardLayout {
Tasoller,
Yuancon,
TasollerHalf,
Deemo,
EightK,
SixK,
FourK,
Voltex,
Neardayo,
}
@ -81,13 +83,23 @@ impl OutputMode {
polling: PollingRate::from_str(v["outputPolling"].as_str()?)?,
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
},
"kb-16-tasoller" => OutputMode::Keyboard {
"kb-16" => OutputMode::Keyboard {
layout: KeyboardLayout::TasollerHalf,
polling: PollingRate::from_str(v["outputPolling"].as_str()?)?,
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
},
"kb-8-deemo" => OutputMode::Keyboard {
layout: KeyboardLayout::Deemo,
"kb-8" => OutputMode::Keyboard {
layout: KeyboardLayout::EightK,
polling: PollingRate::from_str(v["outputPolling"].as_str()?)?,
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
},
"kb-6" => OutputMode::Keyboard {
layout: KeyboardLayout::SixK,
polling: PollingRate::from_str(v["outputPolling"].as_str()?)?,
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
},
"kb-4" => OutputMode::Keyboard {
layout: KeyboardLayout::FourK,
polling: PollingRate::from_str(v["outputPolling"].as_str()?)?,
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
},

View File

@ -43,7 +43,7 @@ const TASOLLER_HALF_KB_MAP: [usize; 41] = [
];
#[rustfmt::skip]
const DEEMO_KB_MAP: [usize; 41] = [
const EIGHT_K_MAP: [usize; 41] = [
0x41, 0x41, 0x41, 0x41, // A
0x53, 0x53, 0x53, 0x53, // S
0x44, 0x44, 0x44, 0x44, // D
@ -56,6 +56,28 @@ const DEEMO_KB_MAP: [usize; 41] = [
0x00, 0x00, 0x00, // Disabled
];
#[rustfmt::skip]
const SIX_K_MAP: [usize; 41] = [
0x53, 0x53, 0x53, 0x53, 0x53, 0x53, // S
0x44, 0x44, 0x44, 0x44, // D
0x46, 0x46, 0x46, 0x46, 0x46, 0x46, // F
0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, // J
0x4b, 0x4b, 0x4b, 0x4b, // K
0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, // L
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // VK_SPACE
0x00, 0x00, 0x00, // Disabled
];
#[rustfmt::skip]
const FOUR_K_MAP: [usize; 41] = [
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, // D
0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, // F
0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, // J
0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, // K
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // VK_SPACE
0x00, 0x00, 0x00, // Disabled
];
#[rustfmt::skip]
const VOLTEX_KB_MAP: [usize; 41] = [
0x57, 0x57, 0x57, 0x57, // W
@ -109,7 +131,9 @@ impl KeyboardOutput {
KeyboardLayout::Tasoller => &TASOLLER_KB_MAP,
KeyboardLayout::Yuancon => &YUANCON_KB_MAP,
KeyboardLayout::TasollerHalf => &TASOLLER_HALF_KB_MAP,
KeyboardLayout::Deemo => &DEEMO_KB_MAP,
KeyboardLayout::EightK => &EIGHT_K_MAP,
KeyboardLayout::SixK => &SIX_K_MAP,
KeyboardLayout::FourK => &FOUR_K_MAP,
KeyboardLayout::Voltex => &VOLTEX_KB_MAP,
KeyboardLayout::Neardayo => &VOLTEX_KB_MAP_NEARDAYO,
};

View File

@ -17,6 +17,8 @@
let outputPolling = "100";
let outputWebsocketUrl = "http://localhost:3000";
let ledFaster = false;
let ledColorActive = "#ff00ff";
let ledColorInactive = "#ffff00";
let ledSensitivity = 20;
let ledWebsocketUrl = "http://localhost:3001";
let ledSerialPort = "COM5";
@ -68,6 +70,8 @@
outputWebsocketUrl =
payload.outputWebsocketUrl || "http://localhost:3000/";
ledFaster = payload.ledFaster || false;
ledColorActive = payload.ledColorActive || "#ff00ff";
ledColorInactive = payload.ledColorInactive || "#ffff00";
ledSensitivity = payload.ledSensitivity || 20;
ledWebsocketUrl = payload.ledWebsocketUrl || "http://localhost:3001";
ledSerialPort = payload.ledSerialPort || "COM5";
@ -119,6 +123,8 @@
outputPolling,
outputWebsocketUrl,
ledFaster,
ledColorActive,
ledColorInactive,
ledSensitivity,
ledWebsocketUrl,
ledSerialPort,
@ -205,7 +211,10 @@
<div class="serverlist">
Brokenithm server running, access at one of:
<pre>
{ips.map((x) => `http://${x}:1606/`).join("\n")}
{ips
.map((x) => `http://${x}:1606/`)
.join("\n")
.trim()}
</pre>
</div>
</div>
@ -264,10 +273,10 @@
<option value="kb-32-tasoller">Keyboard 32-zone, Tasoller Layout</option
>
<option value="kb-32-yuancon">Keyboard 32-zone, Yuancon Layout</option>
<option value="kb-16-tasoller"
>Keyboard 16-zone, Tasoller (Bottom Half) Layout</option
>
<option value="kb-8-deemo">Keyboard 8-zone, Deemo Layout</option>
<option value="kb-16">Keyboard 16-zone, Linear</option>
<option value="kb-8">Keyboard 8-zone, Linear</option>
<option value="kb-6">Keyboard 6-zone, Linear</option>
<option value="kb-4">Keyboard 4-zone, Linear</option>
<option value="kb-voltex">Keyboard 10-zone, Voltex Layout</option>
<option value="kb-neardayo">Keyboard 10-zone, Neardayo Layout</option>
<option value="gamepad-voltex">XBOX 360 Gamepad, Voltex Layout</option>
@ -350,9 +359,10 @@
<div class="input">
<select bind:value={ledMode} on:change={markDirty}>
<option value="none">None</option>
<option value="reactive-4">Reactive, 4-Zone</option>
<option value="reactive-8">Reactive, 8-Zone</option>
<option value="reactive-16">Reactive, 16-Zone</option>
<option value="reactive-8">Reactive, 8-Zone</option>
<option value="reactive-6">Reactive, 6-Zone</option>
<option value="reactive-4">Reactive, 4-Zone</option>
<option value="reactive-rainbow">Reactive, 16-Zone Rainbow</option>
<option value="reactive-voltex">Reactive, Voltex Layout</option>
<option value="attract">Rainbow Attract Mode</option>
@ -378,6 +388,24 @@
</div>
</div>
{/if}
{#if ledMode.slice(0, 8) === "reactive" && ["16", "8", "6", "4"].includes(ledMode.slice(9))}
<div class="row">
<div class="label">Active Color</div>
<div class="input">
<input type="color" bind:value={ledColorActive} on:change={markDirty} />
</div>
</div>
<div class="row">
<div class="label">Base Color</div>
<div class="input">
<input
type="color"
bind:value={ledColorInactive}
on:change={markDirty}
/>
</div>
</div>
{/if}
{#if ledMode.slice(0, 8) === "reactive" && deviceMode.slice(0, 10) !== "brokenithm"}
<div class="row">
<div class="label" title="Larger means harder to trigger">