RustPhysicsMQ/src/drone/input.rs

167 lines
4.9 KiB
Rust
Raw Normal View History

#![allow(unused)]
use macroquad::prelude as mq;
2026-02-23 08:23:52 +00:00
use serde::{Deserialize, Serialize};
use std::fs::File;
use std::io::{Read, Write};
2026-02-23 08:23:52 +00:00
#[derive(Default, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct JoystickInput {
pub throttle_input: f32,
2026-02-06 18:35:23 +00:00
pub roll_input: f32,
pub yaw_input: f32,
pub pitch_input: f32,
}
2026-02-23 08:23:52 +00:00
#[derive(Default, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct PositionInput {
pub lat: f32,
pub long: f32,
pub alt: f32,
}
2026-02-23 08:23:52 +00:00
#[derive(Default, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)]
pub enum ModeInput {
#[default]
Acro,
Navigation,
}
2026-02-23 08:23:52 +00:00
#[derive(Default, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct Input {
pub joystick: JoystickInput,
pub position: PositionInput,
pub mode: ModeInput,
}
2026-02-23 08:23:52 +00:00
#[derive(Default, Clone, Copy, serde::Serialize, serde::Deserialize)]
pub struct InputRecord {
input: Input,
time: f32,
}
2026-02-23 08:23:52 +00:00
#[derive(Default, Clone, serde::Serialize, serde::Deserialize)]
pub struct InputRecording {
2026-02-23 08:23:52 +00:00
records: Vec<InputRecord>,
}
impl InputRecording {
2026-02-23 08:23:52 +00:00
pub fn save_to_file(&self, path: &str) -> Result<(), Box<dyn std::error::Error>> {
let json = serde_json::to_string_pretty(self)?;
let mut file = File::create(path)?;
2026-02-23 08:23:52 +00:00
file.write_all(json.as_bytes())?;
Ok(())
}
2026-02-23 08:23:52 +00:00
pub fn load_from_file(path: &str) -> Result<Self, Box<dyn std::error::Error>> {
let mut file = File::open(path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
let recording: Self = serde_json::from_str(&contents)?;
Ok(recording)
}
2026-02-23 08:23:52 +00:00
pub fn has_ended(&self, time: f32) -> bool {
return self.records.last().unwrap_or(&InputRecord::default()).time < time;
}
pub fn get_input(&self, time: f32) -> Input {
/*
* Binary search returns index to element as OK, or where the element could be placed to
* keep order as Err, so if result is Ok return that input, if its Err, return the previous
* input if it exists, if it doesn't (because time is before the first action in the
* recorded sequence, return an empty input)
*/
let res = self
2026-02-23 08:23:52 +00:00
.records
.binary_search_by(|probe| probe.time.total_cmp(&time));
match res {
Ok(res) => {
return self
2026-02-23 08:23:52 +00:00
.records
.get(res)
.unwrap_or(&InputRecord::default())
.input;
}
Err(mut res) => {
if res > 0 {
res -= 1;
}
return self
2026-02-23 08:23:52 +00:00
.records
.get(0.max(res))
.unwrap_or(&InputRecord::default())
.input;
}
}
}
/*
* Current time should always be larger thant the last input records time.
* This method is made for recording inputs in real time, not for retroactively adding
*
* Returns the addded Joystick Input
*/
2026-02-23 08:23:52 +00:00
pub fn add_input_from_keyboard(&mut self, current_time: f32) -> Input {
let input = Input {
joystick: JoystickInput::from_keyboard(),
position: Default::default(),
mode: ModeInput::Acro,
};
let last_input = self.records.last();
match last_input {
Some(last_record) => {
if last_record.input != input {
2026-02-23 08:23:52 +00:00
self.records.push(InputRecord {
input,
2026-02-23 08:23:52 +00:00
time: current_time,
});
}
}
None => {
2026-02-23 08:23:52 +00:00
self.records.push(InputRecord {
input,
2026-02-23 08:23:52 +00:00
time: current_time,
});
}
}
return input;
}
}
2026-02-23 08:23:52 +00:00
impl JoystickInput {
pub fn from_keyboard() -> Self {
let mut input = Self::default();
if mq::is_key_down(mq::KeyCode::W) {
input.throttle_input = 1.0;
}
if mq::is_key_down(mq::KeyCode::S) {
input.throttle_input = 0.0;
}
if mq::is_key_down(mq::KeyCode::A) {
input.yaw_input = 1.0;
} else if mq::is_key_down(mq::KeyCode::D) {
input.yaw_input = -1.0;
} else {
input.yaw_input = 0.0;
}
if mq::is_key_down(mq::KeyCode::Up) {
input.pitch_input = -1.0;
} else if mq::is_key_down(mq::KeyCode::Down) {
input.pitch_input = 1.0;
} else {
input.pitch_input = 0.0;
}
if mq::is_key_down(mq::KeyCode::Left) {
input.roll_input = -1.0;
} else if mq::is_key_down(mq::KeyCode::Right) {
input.roll_input = 1.0;
} else {
input.roll_input = 0.0;
}
input = input.clamp();
return input;
}
}