mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
221 lines
7.8 KiB
Rust
221 lines
7.8 KiB
Rust
use egui::{Color32, Pos2};
|
|
use rog_aura::advanced::LedCode;
|
|
use rog_aura::layouts::{KeyLayout, KeyShape};
|
|
use rog_aura::{AdvancedAuraType, AuraModeNum};
|
|
|
|
use crate::system_state::AuraState;
|
|
|
|
const SCALE: f32 = 2.0;
|
|
|
|
// TODO:
|
|
// - Multizone: draw regions? While iterating keys check if located in one of
|
|
// the 4 regions and mark
|
|
// - Tab for advanced effects
|
|
// - Keys need to select colour themselves
|
|
|
|
pub fn keyboard(
|
|
ui: &mut egui::Ui,
|
|
keyboard_layout: &KeyLayout,
|
|
states: &mut AuraState,
|
|
colour: Color32,
|
|
) {
|
|
let (keyboard_is_multizoned, keyboard_width, keyboard_is_per_key) =
|
|
match keyboard_layout.advanced_type() {
|
|
AdvancedAuraType::PerKey => (false, 0.0, true),
|
|
AdvancedAuraType::None => (false, keyboard_layout.max_width(), false),
|
|
AdvancedAuraType::Zoned(zones) => {
|
|
let width = if let Some(row) = keyboard_layout.rows_ref().get(2) {
|
|
row.width()
|
|
} else {
|
|
0.0
|
|
};
|
|
(!zones.contains(&LedCode::SingleZone), width, false)
|
|
}
|
|
};
|
|
let mut start_pos = None;
|
|
|
|
let y = ui.spacing().interact_size.y;
|
|
let this_size = ui.available_size();
|
|
let keys_width = keyboard_layout.max_width() * SCALE * y;
|
|
let keys_height = keyboard_layout.max_height() * SCALE * y;
|
|
let keyboard_height = keyboard_layout.keyboard_height() * SCALE;
|
|
let x_start = (this_size.x - keys_width) / SCALE;
|
|
let y_start = (this_size.y - keys_height) / SCALE;
|
|
|
|
// Initial colour states
|
|
let mut input_colour = colour;
|
|
let mut key_colour = colour;
|
|
if states.current_mode == AuraModeNum::Rainbow && !keyboard_is_per_key {
|
|
key_colour = Color32::from_rgb(
|
|
(states.wave_red[0] as u32 * 255 / 100) as u8,
|
|
(states.wave_green[0] as u32 * 255 / 100) as u8,
|
|
(states.wave_blue[0] as u32 * 255 / 100) as u8,
|
|
);
|
|
}
|
|
|
|
ui.spacing_mut().item_spacing = egui::vec2(0.0, 0.0);
|
|
blank(ui, 0.0, y_start / y);
|
|
|
|
for row in keyboard_layout.rows() {
|
|
ui.horizontal_top(|ui| {
|
|
blank(ui, x_start / y, 0.0);
|
|
for (i, key) in row.row().enumerate() {
|
|
// For per-key rainbow which cascades across
|
|
if states.current_mode == AuraModeNum::Rainbow && keyboard_is_per_key
|
|
|| key.0.is_lightbar_zone()
|
|
{
|
|
key_colour = Color32::from_rgb(
|
|
(states.wave_red[i] as u32 * 255 / 100) as u8,
|
|
(states.wave_green[i] as u32 * 255 / 100) as u8,
|
|
(states.wave_blue[i] as u32 * 255 / 100) as u8,
|
|
);
|
|
}
|
|
|
|
if (keyboard_is_multizoned && !key.0.is_lightbar_zone())
|
|
&& states.current_mode == AuraModeNum::Rainbow
|
|
{
|
|
input_colour = key_colour;
|
|
key_colour = Color32::TRANSPARENT;
|
|
}
|
|
|
|
let label = <&str>::from(key.0);
|
|
let mut shape = key.1.clone();
|
|
shape.scale(SCALE);
|
|
|
|
match shape {
|
|
KeyShape::Led {
|
|
width,
|
|
height,
|
|
pad_left,
|
|
pad_right,
|
|
pad_top,
|
|
pad_bottom,
|
|
} => {
|
|
let (pos, response) = key_shape(
|
|
ui, key_colour, width, height, pad_left, pad_right, pad_top, pad_bottom,
|
|
);
|
|
if start_pos.is_none() {
|
|
start_pos = Some(pos);
|
|
} else if let Some(old_pos) = start_pos.as_mut() {
|
|
if !key.0.is_lightbar_zone() {
|
|
if pos.x < old_pos.x {
|
|
old_pos.x = pos.x;
|
|
}
|
|
if pos.y < old_pos.y {
|
|
old_pos.y = pos.y;
|
|
}
|
|
}
|
|
}
|
|
if response.on_hover_text(label).clicked() && keyboard_is_per_key {
|
|
// TODO: set an effect on the LedCode
|
|
}
|
|
}
|
|
KeyShape::Blank { width, height } => {
|
|
blank(ui, width, height);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
if keyboard_is_multizoned {
|
|
let zone_width = keyboard_width * SCALE / 4.0 - 0.1;
|
|
for n in 0..4 {
|
|
if states.current_mode == AuraModeNum::Rainbow {
|
|
input_colour = Color32::from_rgba_unmultiplied(
|
|
(states.wave_red[n] as u32 * 255 / 100) as u8,
|
|
(states.wave_green[n] as u32 * 255 / 100) as u8,
|
|
(states.wave_blue[n] as u32 * 255 / 100) as u8,
|
|
70,
|
|
);
|
|
}
|
|
if let Some(mut pos) = start_pos {
|
|
pos.x += n as f32 * zone_width * y;
|
|
let response = zone_shape(ui, input_colour, pos, zone_width, keyboard_height);
|
|
let label = format!("Zone {}", 1 + n);
|
|
if response.on_hover_text(label).clicked() {
|
|
// TODO: set an effect on the zone
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[allow(clippy::too_many_arguments)]
|
|
fn key_shape(
|
|
ui: &mut egui::Ui,
|
|
colour: Color32,
|
|
width: f32,
|
|
height: f32,
|
|
pad_left: f32,
|
|
pad_right: f32,
|
|
pad_top: f32,
|
|
pad_bottom: f32,
|
|
) -> (egui::Pos2, egui::Response) {
|
|
// First, get some space
|
|
let y = ui.spacing().interact_size.y;
|
|
let desired_size = y * egui::vec2(width + pad_left + pad_right, height + pad_top + pad_bottom);
|
|
let (mut rect, mut response) = ui.allocate_exact_size(desired_size, egui::Sense::click());
|
|
// rect = rect.shrink(3.0);
|
|
if response.clicked() {
|
|
response.mark_changed();
|
|
}
|
|
response.widget_info(|| {
|
|
egui::WidgetInfo::selected(egui::WidgetType::Checkbox, response.clicked(), "")
|
|
});
|
|
|
|
if ui.is_rect_visible(rect) {
|
|
// Now set the actual visible rect
|
|
let visuals = ui.style().interact_selectable(&response, true);
|
|
let size = y * egui::vec2(width, height);
|
|
rect.set_width(size.x);
|
|
rect.set_height(size.y);
|
|
let center = Pos2::new(
|
|
rect.center().x + pad_left * y,
|
|
rect.center().y + pad_top * y,
|
|
);
|
|
rect.set_center(center);
|
|
// let rect = rect.expand(visuals.expansion);
|
|
ui.painter().rect(rect, 0.1, colour, visuals.fg_stroke);
|
|
}
|
|
|
|
(rect.left_top(), response)
|
|
}
|
|
|
|
#[allow(clippy::too_many_arguments)]
|
|
fn zone_shape(
|
|
ui: &mut egui::Ui,
|
|
mut colour: Color32,
|
|
pos: Pos2,
|
|
width: f32,
|
|
height: f32,
|
|
) -> egui::Response {
|
|
// First, get some space
|
|
let y = ui.spacing().interact_size.y;
|
|
let desired_size = y * egui::vec2(width, height);
|
|
let rect = egui::Rect::from_min_size(pos, desired_size);
|
|
let mut response = ui.allocate_rect(rect, egui::Sense::click());
|
|
// rect = rect.shrink(3.0);
|
|
if response.clicked() {
|
|
response.mark_changed();
|
|
}
|
|
response.widget_info(|| {
|
|
egui::WidgetInfo::selected(egui::WidgetType::Checkbox, response.clicked(), "")
|
|
});
|
|
|
|
if ui.is_rect_visible(rect) {
|
|
// Now set the actual visible rect
|
|
let visuals = ui.style().interact_selectable(&response, true);
|
|
// let rect = rect.expand(visuals.expansion);
|
|
colour[3] = 20;
|
|
ui.painter().rect(rect, 0.1, colour, visuals.fg_stroke);
|
|
}
|
|
|
|
response
|
|
}
|
|
|
|
fn blank(ui: &mut egui::Ui, ux: f32, uy: f32) {
|
|
let desired_size = ui.spacing().interact_size.y * egui::vec2(ux, uy);
|
|
ui.allocate_exact_size(desired_size, egui::Sense::click());
|
|
}
|