Compare commits

..

No commits in common. "main" and "v0.1.4" have entirely different histories.
main ... v0.1.4

18 changed files with 193 additions and 472 deletions

172
Cargo.lock generated
View file

@ -1,18 +1,18 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
version = 3
[[package]]
name = "ELApse"
version = "0.1.5"
version = "0.1.4"
dependencies = [
"clap",
"ftdi-embedded-hal",
"image",
"piston",
"piston2d-graphics",
"piston_window",
"rgb",
"rand",
"unreal_asset",
"url",
]
[[package]]
@ -540,32 +540,6 @@ version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "embedded-hal"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff"
dependencies = [
"nb 0.1.3",
"void",
]
[[package]]
name = "embedded-hal"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89"
[[package]]
name = "embedded-hal-nb"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605"
dependencies = [
"embedded-hal 1.0.0",
"nb 1.1.0",
]
[[package]]
name = "enum_dispatch"
version = "0.3.13"
@ -649,38 +623,6 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "form_urlencoded"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
dependencies = [
"percent-encoding",
]
[[package]]
name = "ftdi-embedded-hal"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e328c2738c104e2649586bda4baabf376825db50014eb0d41bee74fb6064deb"
dependencies = [
"embedded-hal 0.2.7",
"embedded-hal 1.0.0",
"embedded-hal-nb",
"ftdi-mpsse",
"libftd2xx",
"nb 1.1.0",
]
[[package]]
name = "ftdi-mpsse"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa7cfcda69930a8d2fdcdd7ffb9234fe4c79a8c73934ed4904327d77bfb5078a"
dependencies = [
"static_assertions",
]
[[package]]
name = "funty"
version = "2.0.0"
@ -867,16 +809,6 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "idna"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
dependencies = [
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "image"
version = "0.25.2"
@ -1024,28 +956,6 @@ version = "0.2.158"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
[[package]]
name = "libftd2xx"
version = "0.32.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f20d68b3138aaabb97edc3db8ed8f418d60f8abd2a7d8220d562906fb38ff08e"
dependencies = [
"ftdi-mpsse",
"libftd2xx-ffi",
"log",
"paste",
"static_assertions",
]
[[package]]
name = "libftd2xx-ffi"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40bed7f53ea45282e0e4f1361d1a8094e62abe0ccfd9a6dbf7e3db932b2789ce"
dependencies = [
"cfg-if",
]
[[package]]
name = "libfuzzer-sys"
version = "0.4.7"
@ -1189,21 +1099,6 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fce7b49e1e6d8aa67232ef1c4c936c0af58756eb2db6f65c40bacb39035e7f42"
[[package]]
name = "nb"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
dependencies = [
"nb 1.1.0",
]
[[package]]
name = "nb"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d"
[[package]]
name = "ndk"
version = "0.7.0"
@ -1858,9 +1753,9 @@ checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
[[package]]
name = "rgb"
version = "0.8.52"
version = "0.8.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce"
checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a"
dependencies = [
"bytemuck",
]
@ -2026,12 +1921,6 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "strict-num"
version = "0.1.1"
@ -2147,21 +2036,6 @@ dependencies = [
"strict-num",
]
[[package]]
name = "tinyvec"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "toml"
version = "0.8.19"
@ -2219,27 +2093,12 @@ version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5be21190ff5d38e8b4a2d3b6a3ae57f612cc39c96e83cedeaf7abc338a8bac4a"
[[package]]
name = "unicode-bidi"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-normalization"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
dependencies = [
"tinyvec",
]
[[package]]
name = "unreal_asset"
version = "0.1.16"
@ -2287,17 +2146,6 @@ dependencies = [
"thiserror",
]
[[package]]
name = "url"
version = "2.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
]
[[package]]
name = "utf8parse"
version = "0.2.2"
@ -2342,12 +2190,6 @@ version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"

View file

@ -1,6 +1,6 @@
[package]
name = "ELApse"
version = "0.1.5"
version = "0.1.4"
edition = "2021"
repository = "https://github.com/BlackDragon-B/ELApse"
authors = ["BlackDragon-B <kyan@blackdrgn.nl>"]
@ -9,15 +9,12 @@ readme = "README.md"
[dependencies]
clap = { version = "4.5.17", features = ["derive"] }
ftdi-embedded-hal = { version = "0.22.0", features = ["libftd2xx"] }
image = "0.25.2"
piston = "1.0.0"
piston2d-graphics = "0.44.0"
piston_window = "0.132.0"
rgb = "0.8.52"
rand = "0.8.5"
unreal_asset = "0.1.16"
url = "2.5.2"
[profile.dev]
opt-level = 3
# The profile that 'cargo dist' will build with
[profile.dist]

View file

@ -1,35 +1 @@
# ELApse
ELApse is a tool used for processing and displaying the .ELA format from a dead rhythm game
## Downloading
You can either download the latest release from the [releases](https://github.com/BlackDragon-B/ELApse/releases) or build it yourself using cargo
## Usage
```bash
ELApse --input <INPUT> --output <OUTPUT>
Options:
-i, --input <INPUT> Input to use
-o, --output <OUTPUT> Output to use
-h, --help Print help
-V, --version Print version
```
## Features
### Input
- [WARLS](https://github.com/Aircoookie/WLED/wiki/UDP-Realtime-Control) (--input udp://0.0.0.0:21324)
- Images (--input example.png)
- .uasset/.uexp (--input ELA_BP_Title_in_00.uasset)
- File containing raw rgb8 (--input file)
- Raw rgb8 from stdin (--input stdin)
### Output
- [WARLS](https://github.com/Aircoookie/WLED/wiki/UDP-Realtime-Control) (--output udp://0.0.0.0:21324)
- Built-in renderer built with [Piston](https://www.piston.rs/) (--output piston)
## Contributing
Feel free to open an issue if you think this tool is missing something critical. Pull requests are always welcome.
## License
ELApse is licensed under the [GPLv3](https://choosealicense.com/licenses/gpl-3.0/) license.

2
rust-toolchain.toml Normal file
View file

@ -0,0 +1,2 @@
[toolchain]
channel = "nightly"

View file

@ -1,6 +1,6 @@
use std::{ffi::OsStr, fs::{self, File}, path::Path};
use image::ImageFormat;
use unreal_asset::{cast, engine_version::EngineVersion, exports::Export, properties::Property, Asset};
use std::{ffi::OsStr, fs::{self, read, File}, os::raw, path::Path};
use image::{ImageFormat, ImageReader};
use unreal_asset::{asset::AssetTrait, cast, engine_version::EngineVersion, exports::{self, normal_export::NormalExport, Export, ExportBaseTrait}, properties::{array_property::ArrayProperty, color_property::ColorProperty, struct_property::StructProperty, Property}, types::{fname::FNameContainer, PackageIndex}, Asset};
fn rawrgb(path: &str) -> Result<Vec<u8>, String> {
match fs::read(path) {

67
src/input.rs Normal file
View file

@ -0,0 +1,67 @@
#![allow(non_camel_case_types)]
use std::{io::Read, net::UdpSocket, sync::mpsc::{self, Receiver, Sender}, thread, time::{Duration, Instant}};
use crate::{ parser, fileparser };
pub fn stdin(tx: Sender<Vec<[f32; 4]>>) {
let (stdintx, stdinrx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = mpsc::channel();
thread::spawn( move || {
let mut buf = [0; 1500];
let mut e = std::io::stdin().lock();
loop {
let amt = e.read(&mut buf).unwrap();
if buf[..amt].to_vec().len() > 0 {
let _ = stdintx.send(buf[..amt].to_vec());
}
}
});
thread::spawn( move || {
loop {
// let amt = e.read(&mut buf).unwrap();
match stdinrx.recv_timeout(Duration::from_millis(500)) {
Ok(d) => {
let r: Vec<[f32; 4]> = parser::parseleds(d, parser::ParserOptions::default().mirror(true).double(true).offset(15));
let _ = tx.send(r);
},
Err(_) => {
std::process::exit(0);
},
};
}
});
}
pub fn realtimeudp(tx: Sender<Vec<[f32; 4]>>) {
thread::spawn( move || {
let socket = UdpSocket::bind("127.0.0.1:21324").unwrap();
let mut buf = [0; 1500];
loop {
let (amt, _src) = socket.recv_from(&mut buf).unwrap();
let r = parser::parseleds(buf[..amt].to_vec(), parser::ParserOptions::default().stripheader(2));
let _ = tx.send(r);
}
});
}
pub fn file(tx: Sender<Vec<[f32; 4]>>, path: String) {
thread::spawn( move || {
let Ok(rawbytes) = fileparser::parse(&path) else {
std::process::exit(1)
};
for frame in rawbytes.chunks(720) {
let st = Instant::now();
let r = parser::parseleds(frame.to_vec(), parser::ParserOptions::default().mirror(true).double(true).offset(15));
let _ = tx.send(r);
if Duration::from_secs_f32(1.0/60.0) > st.elapsed() {
thread::sleep(Duration::from_secs_f32(1.0/60.0)-st.elapsed());
};
}
std::process::exit(0);
});
}
#[derive(clap::ValueEnum, Clone, Debug)]
pub enum Input {
stdin,
realtimeudp,
file,
}

View file

@ -1,29 +0,0 @@
#![allow(non_camel_case_types)]
use std::{sync::mpsc::Sender, thread, time::{Duration, Instant}};
use crate::{fileparser, input::Input, parser};
impl Input {
pub fn file(tx: Sender<Vec<[f32; 4]>>, path: String) {
thread::spawn(move || {
let Ok(rawbytes) = fileparser::parse(&path) else {
println!("File not found");
std::process::exit(1)
};
for frame in rawbytes.chunks(720) {
let st = Instant::now();
let r = parser::parseleds(
frame.to_vec(),
parser::ParserOptions::default()
.mirror(true)
.double(true)
.offset(15),
);
let _ = tx.send(r);
if Duration::from_secs_f32(1.0 / 60.0) > st.elapsed() {
thread::sleep(Duration::from_secs_f32(1.0 / 60.0) - st.elapsed());
};
}
std::process::exit(0);
});
}
}

View file

@ -1,5 +0,0 @@
mod file;
mod realtimeudp;
mod stdin;
pub struct Input;

View file

@ -1,20 +0,0 @@
#![allow(non_camel_case_types)]
use std::{net::UdpSocket, sync::mpsc::Sender, thread};
use crate::{input::Input, parser};
impl Input {
pub fn realtimeudp(tx: Sender<Vec<[f32; 4]>>, bindaddr: String) {
thread::spawn(move || {
let socket = UdpSocket::bind(bindaddr).unwrap();
let mut buf = [0; 1500];
loop {
let (amt, _src) = socket.recv_from(&mut buf).unwrap();
let r = parser::parseleds(
buf[..amt].to_vec(),
parser::ParserOptions::default().stripheader(2),
);
let _ = tx.send(r);
}
});
}
}

View file

@ -1,39 +0,0 @@
#![allow(non_camel_case_types)]
use std::{io::Read, sync::mpsc::{self, Receiver, Sender}, thread, time::Duration};
use crate::{input::Input, parser};
impl Input {
pub fn stdin(tx: Sender<Vec<[f32; 4]>>) {
let (stdintx, stdinrx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = mpsc::channel();
thread::spawn(move || {
let mut buf = [0; 1500];
let mut e = std::io::stdin().lock();
loop {
let amt = e.read(&mut buf).unwrap();
if buf[..amt].to_vec().len() > 0 {
let _ = stdintx.send(buf[..amt].to_vec());
}
}
});
thread::spawn(move || {
loop {
// let amt = e.read(&mut buf).unwrap();
match stdinrx.recv_timeout(Duration::from_millis(500)) {
Ok(d) => {
let r: Vec<[f32; 4]> = parser::parseleds(
d,
parser::ParserOptions::default()
.mirror(true)
.double(true)
.offset(15),
);
let _ = tx.send(r);
}
Err(_) => {
std::process::exit(0);
}
};
}
});
}
}

View file

@ -1,3 +1,4 @@
#![feature(array_chunks)]
mod input;
mod output;
mod parser;
@ -5,67 +6,60 @@ mod utils;
mod fileparser;
use std::sync::mpsc::{self, Receiver, Sender};
use clap::Parser;
use url::Url;
use crate::output::Output;
use crate::input::Input;
use clap::{command, error::{self, ContextKind, ContextValue, ErrorKind}, Parser};
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Args {
/// Input to use
/// Input driver to use
#[arg(short, long)]
input: String,
input: input::Input,
/// Output to use
/// File input for the file driver
#[arg(required(false), short, long, requires = "input")]
file: Option<String>,
/// Output driver to use
#[arg(short, long)]
output: String,
output: output::Output,
/// Destination IP for the realtimeudp driver
#[arg(required(false), short, long, requires = "output")]
destip: Option<String>,
}
fn main() {
let args = Args::parse();
// let mut arg = clap::command!()
// .arg(clap::arg!(-o --output <file> "The output file to write to. Use - for stdout."))
// .arg_required_else_help(true);
let (tx, rx): (Sender<Vec<[f32; 4]>>, Receiver<Vec<[f32; 4]>>) = mpsc::channel();
match args.input.as_str() {
"-" | "stdin" => Input::stdin(tx),
_ => {
match Url::parse(&args.input) {
Ok(o) => {
match o.scheme() {
"udp" => {
Input::realtimeudp(tx, utils::get_host(o));
},
"file" => Input::file(tx, o.path().to_owned()),
_ => {
println!("Unrecognized uri scheme");
std::process::exit(1);
}
}
},
Err(_) => {
Input::file(tx, args.input);
},
};
}
// if x {
// input::stdin(tx);
// } else {
// input::realtimeudp(tx)
// }
match args.input {
input::Input::stdin => input::stdin(tx),
input::Input::realtimeudp => input::realtimeudp(tx),
input::Input::file => {
if args.file.is_some() {
input::file(tx, args.file.unwrap());
} else {
utils::err_missing_args(vec!["--file".to_owned()])
}
},
}
match args.output.as_str() {
"piston" => Output::piston(rx),
"ftd2xx" => Output::ft2dxx(rx),
_ => {
match Url::parse(&args.output) {
Ok(o) => {
match o.scheme() {
"udp" => Output::realtimeudp(rx,utils::get_host(o)),
_ => {
println!("Unrecognized uri scheme");
std::process::exit(1);
}
}
},
Err(_) => {
println!("Output out of scope");
std::process::exit(1);
},
};
}
// input::file(tx);
// output::piston(rx) 21324
match args.output {
output::Output::piston => output::piston(rx),
output::Output::realtimeudp => {
if args.destip.is_some() {
output::realtimeudp(rx, args.destip.unwrap())
} else {
utils::err_missing_args(vec!["--destip".to_owned()])
}
},
}
}

59
src/output.rs Normal file
View file

@ -0,0 +1,59 @@
#![allow(non_camel_case_types)]
extern crate piston_window;
use graphics;
use piston_window::*;
use graphics::math::Scalar;
use std::{net::{SocketAddr, UdpSocket}, sync::mpsc::Receiver, time::Duration};
use crate::utils::{compare, offset};
pub fn piston(rx: Receiver<Vec<[f32; 4]>>) {
let mut window: PistonWindow =
WindowSettings::new("ELApse", [800, 800])
.transparent(true)
.exit_on_esc(true).build().unwrap();
while let Some(e) = window.next() {
let r = match rx.recv_timeout(Duration::from_millis(66)) {
Ok(e) => e,
Err(_) => vec![[0.02, 0.02, 0.02, 1.0]; 480],
};
let size = window.size();
let wh = compare(size.height, size.width)*0.75;
window.draw_2d(&e, |c, g, _device| {
for e in 1..9 {
for i in 0..60 {
let rwh = wh*(1.0-(e as f64*0.06));
circle_arc(r[i*8+(e-1)], rwh/32.0, Scalar::deg_to_rad(offset((((360/60)*i)) as i16, 360, 90) as f64), Scalar::deg_to_rad(offset((((360/60)*i)+6) as i16, 360, 90) as f64), [(size.width/2.0)-(rwh/2.0), (size.height/2.0)-(rwh/2.0), rwh, rwh], c.transform, g);
}
}
});
}
}
pub fn realtimeudp(rx: Receiver<Vec<[f32; 4]>>, addr: String) {
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
loop {
let leds = rx.recv().unwrap();
let mut packet: Vec<u8> = vec![2, 2];
for led in leds {
packet.push((led[0]*255.0) as u8);
packet.push((led[1]*255.0) as u8);
packet.push((led[2]*255.0) as u8);
}
match socket.send_to(&packet, &addr) {
Ok(_) => (),
Err(err) => {
println!("Error while sending trying to send data: {}", err);
std::process::exit(1);
},
};
}
}
#[derive(clap::ValueEnum, Clone, Debug)]
pub enum Output {
piston,
realtimeudp,
}

View file

@ -1,40 +0,0 @@
#![allow(non_camel_case_types)]
use std::sync::mpsc::Receiver;
use ftdi_embedded_hal::eh0::prelude::_embedded_hal_blocking_spi_Write;
use ftdi_embedded_hal::{self as hal, libftd2xx};
use crate::output::Output;
impl Output {
pub fn ft2dxx(rx: Receiver<Vec<[f32; 4]>>) {
let device = libftd2xx::Ft232h::with_description("Single RS232-HS").unwrap();
println!("Connected to FT232H");
let hal = hal::FtHal::init_freq(device, 3_000_000).unwrap();
let mut spi = hal.spi().unwrap();
// led stuff
loop {
let leds = rx.recv().unwrap();
let mut fdata: Vec<u8> = Vec::new();
for led in leds {
let sled = [led[1], led[0], led[2]]; //Shift colors (be gone when I make a color struct)
for i in 0..3 {
let mut data = (sled[i].clone() * 255.0) as u8;
let patterns = [0b1000_1000, 0b1000_1110, 0b11101000, 0b11101110];
for _ in 0..4 {
let bits = (data & 0b1100_0000) >> 6;
fdata.push(patterns[bits as usize]);
data <<= 2;
}
}
}
let _ = spi.write(&fdata);
// for _ in 0..140 {
// spi.write(std::array::from_ref(&0)).unwrap();
// }
}
}
}

View file

@ -1,5 +0,0 @@
mod ft2dxx;
mod piston;
mod realtimeudp;
pub struct Output;

View file

@ -1,34 +0,0 @@
#![allow(non_camel_case_types)]
use piston_window::*;
use piston_window::graphics::math::Scalar;
use std::{sync::mpsc::Receiver, time::Duration};
use crate::output::Output;
use crate::utils::{compare, offset};
impl Output {
pub fn piston(rx: Receiver<Vec<[f32; 4]>>) {
let mut window: PistonWindow =
WindowSettings::new("ELApse", [800, 800])
.transparent(true)
.exit_on_esc(true).build().unwrap();
while let Some(e) = window.next() {
let r = match rx.recv_timeout(Duration::from_millis(66)) {
Ok(e) => e,
Err(_) => vec![[0.02, 0.02, 0.02, 1.0]; 480],
};
let size = window.size();
let wh = compare(size.height, size.width)*0.75;
window.draw_2d(&e, |c, g, _device| {
for e in 1..9 {
for i in 0..60 {
let rwh = wh*(1.0-(e as f64*0.06));
circle_arc(r[i*8+(e-1)], rwh/32.0, Scalar::deg_to_rad(offset((((360/60)*i)) as i16, 360, 90) as f64), Scalar::deg_to_rad(offset((((360/60)*i)+6) as i16, 360, 90) as f64), [(size.width/2.0)-(rwh/2.0), (size.height/2.0)-(rwh/2.0), rwh, rwh], c.transform, g);
}
}
});
}
}
}

View file

@ -1,26 +0,0 @@
#![allow(non_camel_case_types)]
use std::{net::UdpSocket, sync::mpsc::Receiver};
use crate::output::Output;
impl Output {
pub fn realtimeudp(rx: Receiver<Vec<[f32; 4]>>, addr: String) {
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
loop {
let leds = rx.recv().unwrap();
let mut packet: Vec<u8> = vec![2, 2];
for led in leds {
packet.push((led[0] * 255.0) as u8);
packet.push((led[1] * 255.0) as u8);
packet.push((led[2] * 255.0) as u8);
}
match socket.send_to(&packet, &addr) {
Ok(_) => (),
Err(err) => {
println!("Error while sending trying to send data: {}", err);
std::process::exit(1);
}
};
}
}
}

View file

@ -34,7 +34,7 @@ pub fn parseleds(mut data: Vec<u8>, options: ParserOptions) -> Vec<[f32; 4]> {
if data.len() < expectedlen {
data.append(&mut vec![5; expectedlen-out.len()]);
}
for x in data.as_chunks::<3>().0.iter() {
for x in data.array_chunks::<3>() {
out.push([utils::scaleu8tof32(x[0]), utils::scaleu8tof32(x[1]), utils::scaleu8tof32(x[2]), 1.0]);
if options.double && !options.mirror {
out.push(out.last().unwrap().clone());

View file

@ -1,3 +1,5 @@
use clap::error::{ContextKind, ContextValue, ErrorKind};
pub fn compare(a: f64, b: f64) -> f64 {
if a > b {
b
@ -18,19 +20,9 @@ pub fn scaleu8tof32(old_value: u8) -> f32 { // Convert a u8 between 0 and 255 to
(((old_value as f32 - 0.0) * (0.0 - 1.0)) / (0.0 - 255.0)) + 0.0
}
pub fn get_host(url: url::Url) -> String {
match url.host_str() {
Some(addr) => {
let port = match url.port() {
Some(port) => port,
None => 21324,
};
return format!("{}:{}",addr,port);
},
None => {
println!("Invalid host");
std::process::exit(1);
},
}
pub fn err_missing_args(args: Vec<String>) {
let mut err = clap::Error::new(ErrorKind::MissingRequiredArgument);
err.insert(ContextKind::InvalidArg, ContextValue::Strings(args));
let _ = err.print();
std::process::exit(1);
}