1
0
mirror of https://github.com/4yn/slidershim.git synced 2025-02-25 14:04:55 +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)] #[derive(Debug, Clone, Copy)]
pub enum ReactiveLayout { pub enum ReactiveLayout {
Even { splits: usize }, Even { splits: usize },
Six,
Voltex, Voltex,
Rainbow, 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)] #[derive(Debug, Clone)]
pub enum LightsMode { pub enum LightsMode {
None, None,
@ -14,6 +54,7 @@ pub enum LightsMode {
faster: bool, faster: bool,
layout: ReactiveLayout, layout: ReactiveLayout,
sensitivity: u8, sensitivity: u8,
color: ColorScheme,
}, },
Attract { Attract {
faster: bool, faster: bool,
@ -32,30 +73,41 @@ impl LightsMode {
pub fn from_serde_value(v: &Value) -> Option<Self> { pub fn from_serde_value(v: &Value) -> Option<Self> {
Some(match v["ledMode"].as_str()? { Some(match v["ledMode"].as_str()? {
"none" => LightsMode::None, "none" => LightsMode::None,
"reactive-4" => LightsMode::Reactive { "reactive-16" => LightsMode::Reactive {
faster: v["ledFaster"].as_bool()?, faster: v["ledFaster"].as_bool()?,
layout: ReactiveLayout::Even { splits: 4 }, layout: ReactiveLayout::Even { splits: 16 },
sensitivity: u8::try_from(v["ledSensitivity"].as_i64()?).ok()?, sensitivity: u8::try_from(v["ledSensitivity"].as_i64()?).ok()?,
color: ColorScheme::from_serde_value_or_default(v),
}, },
"reactive-8" => LightsMode::Reactive { "reactive-8" => LightsMode::Reactive {
faster: v["ledFaster"].as_bool()?, faster: v["ledFaster"].as_bool()?,
layout: ReactiveLayout::Even { splits: 8 }, layout: ReactiveLayout::Even { splits: 8 },
sensitivity: u8::try_from(v["ledSensitivity"].as_i64()?).ok()?, 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()?, faster: v["ledFaster"].as_bool()?,
layout: ReactiveLayout::Even { splits: 16 }, layout: ReactiveLayout::Six,
sensitivity: u8::try_from(v["ledSensitivity"].as_i64()?).ok()?, 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 { "reactive-rainbow" => LightsMode::Reactive {
faster: v["ledFaster"].as_bool()?, faster: v["ledFaster"].as_bool()?,
layout: ReactiveLayout::Rainbow, layout: ReactiveLayout::Rainbow,
sensitivity: u8::try_from(v["ledSensitivity"].as_i64()?).ok()?, sensitivity: u8::try_from(v["ledSensitivity"].as_i64()?).ok()?,
color: ColorScheme::default(),
}, },
"reactive-voltex" => LightsMode::Reactive { "reactive-voltex" => LightsMode::Reactive {
faster: v["ledFaster"].as_bool()?, faster: v["ledFaster"].as_bool()?,
layout: ReactiveLayout::Voltex, layout: ReactiveLayout::Voltex,
sensitivity: u8::try_from(v["ledSensitivity"].as_i64()?).ok()?, sensitivity: u8::try_from(v["ledSensitivity"].as_i64()?).ok()?,
color: ColorScheme::default(),
}, },
"attract" => LightsMode::Attract { "attract" => LightsMode::Attract {
faster: v["ledFaster"].as_bool()?, faster: v["ledFaster"].as_bool()?,

View File

@ -48,8 +48,8 @@ impl LightsJob {
serial_buffer: Option<&Buffer>, serial_buffer: Option<&Buffer>,
lights: &mut SliderLights, lights: &mut SliderLights,
) { ) {
match self.mode { match &self.mode {
LightsMode::Reactive { layout, .. } => { LightsMode::Reactive { layout, color, .. } => {
let flat_input = flat_input.unwrap(); let flat_input = flat_input.unwrap();
match layout { match layout {
@ -58,23 +58,55 @@ impl LightsJob {
let banks: Vec<bool> = flat_input let banks: Vec<bool> = flat_input
.chunks(32 / splits) .chunks(32 / splits)
.take(splits) .take(*splits)
.map(|x| x.contains(&true)) .map(|x| x.contains(&true))
.collect(); .collect();
for idx in 0..31 { for idx in 0..31 {
lights.paint( lights.paint(
idx, idx,
match (idx + 1) % buttons_per_split { match ((idx + 1) % buttons_per_split, (idx + 1) % 2) {
0 => &[255, 0, 255], (0, _) => &color.active,
(_, 0) => &color.inactive,
_ => match banks[idx / buttons_per_split] { _ => match banks[idx / buttons_per_split] {
true => &[255, 0, 255], true => &color.active,
false => &[255, 255, 0], 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 => { ReactiveLayout::Voltex => {
lights.ground.fill(0); lights.ground.fill(0);

View File

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

View File

@ -43,7 +43,7 @@ const TASOLLER_HALF_KB_MAP: [usize; 41] = [
]; ];
#[rustfmt::skip] #[rustfmt::skip]
const DEEMO_KB_MAP: [usize; 41] = [ const EIGHT_K_MAP: [usize; 41] = [
0x41, 0x41, 0x41, 0x41, // A 0x41, 0x41, 0x41, 0x41, // A
0x53, 0x53, 0x53, 0x53, // S 0x53, 0x53, 0x53, 0x53, // S
0x44, 0x44, 0x44, 0x44, // D 0x44, 0x44, 0x44, 0x44, // D
@ -56,6 +56,28 @@ const DEEMO_KB_MAP: [usize; 41] = [
0x00, 0x00, 0x00, // Disabled 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] #[rustfmt::skip]
const VOLTEX_KB_MAP: [usize; 41] = [ const VOLTEX_KB_MAP: [usize; 41] = [
0x57, 0x57, 0x57, 0x57, // W 0x57, 0x57, 0x57, 0x57, // W
@ -109,7 +131,9 @@ impl KeyboardOutput {
KeyboardLayout::Tasoller => &TASOLLER_KB_MAP, KeyboardLayout::Tasoller => &TASOLLER_KB_MAP,
KeyboardLayout::Yuancon => &YUANCON_KB_MAP, KeyboardLayout::Yuancon => &YUANCON_KB_MAP,
KeyboardLayout::TasollerHalf => &TASOLLER_HALF_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::Voltex => &VOLTEX_KB_MAP,
KeyboardLayout::Neardayo => &VOLTEX_KB_MAP_NEARDAYO, KeyboardLayout::Neardayo => &VOLTEX_KB_MAP_NEARDAYO,
}; };

View File

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