diff --git a/src/ui/panes/pid_drawing_tool.rs b/src/ui/panes/pid_drawing_tool.rs index 26ca3ea3056035eb29826bb54806cb111e51d700..627990fdfb58436bb65ef698b0329dacb3579bf6 100644 --- a/src/ui/panes/pid_drawing_tool.rs +++ b/src/ui/panes/pid_drawing_tool.rs @@ -12,9 +12,13 @@ use glam::Vec2; use grid::GridInfo; use serde::{Deserialize, Serialize}; use strum::IntoEnumIterator; -use symbols::{icons::Icon, Symbol}; +use symbols::{Symbol, icons::Icon}; -use crate::ui::{composable_view::PaneResponse, utils::egui_to_glam}; +use crate::{ + error::ErrInstrument, + mavlink::{GSE_TM_DATA, MessageData, TimedMessage}, + ui::{app::PaneResponse, utils::egui_to_glam}, +}; use super::PaneBehavior; @@ -98,6 +102,18 @@ impl PaneBehavior for PidPane { fn contains_pointer(&self) -> bool { false } + + fn update(&mut self, messages: &[TimedMessage]) { + if let Some(msg) = messages.last() { + for element in &mut self.elements { + element.update(&msg.message); + } + } + } + + fn get_message_subscription(&self) -> Option<u32> { + Some(GSE_TM_DATA::ID) + } } impl PidPane { @@ -295,24 +311,24 @@ impl PidPane { .iter() .map(|p| p.x) .min_by(|a, b| a.total_cmp(b)) - .unwrap(); + .log_unwrap(); let min_y = points .iter() .map(|p| p.y) .min_by(|a, b| a.total_cmp(b)) - .unwrap(); + .log_unwrap(); let min = Vec2::new(min_x, min_y); let max_x = points .iter() .map(|p| p.x) .max_by(|a, b| a.total_cmp(b)) - .unwrap(); + .log_unwrap(); let max_y = points .iter() .map(|p| p.y) .max_by(|a, b| a.total_cmp(b)) - .unwrap(); + .log_unwrap(); let max = Vec2::new(max_x, max_y); self.grid.zero_pos = ui_center - min.midpoint(max) * self.grid.size(); @@ -326,7 +342,7 @@ impl PidPane { // Invalidate the cache to redraw the images for icon in Icon::iter() { let img: egui::ImageSource = icon.get_image(theme); - ui.ctx().forget_image(img.uri().unwrap()); + ui.ctx().forget_image(img.uri().log_unwrap()); } } } diff --git a/src/ui/panes/pid_drawing_tool/connections.rs b/src/ui/panes/pid_drawing_tool/connections.rs index 2a5020f28c79df7b6f4dc09a67118e84fb3553e5..3cde5f8e6a6ac5ecca442e120f25cd9044bdfff7 100644 --- a/src/ui/panes/pid_drawing_tool/connections.rs +++ b/src/ui/panes/pid_drawing_tool/connections.rs @@ -1,12 +1,12 @@ -use egui::{epaint::PathStroke, Color32, Painter, Rect, Rounding, Stroke, Theme}; +use egui::{Color32, CornerRadius, Painter, Rect, Stroke, StrokeKind, Theme}; use glam::{Mat2, Vec2}; use serde::{Deserialize, Serialize}; -use crate::ui::utils::glam_to_egui; +use crate::{error::ErrInstrument, ui::utils::glam_to_egui}; use super::{ - grid::{GridInfo, CONNECTION_LINE_THICKNESS, CONNECTION_LINE_THRESHOLD, CONNECTION_POINT_SIZE}, PidPane, + grid::{CONNECTION_LINE_THICKNESS, CONNECTION_LINE_THRESHOLD, CONNECTION_POINT_SIZE, GridInfo}, }; #[derive(Clone, Serialize, Deserialize, PartialEq, Debug)] @@ -111,11 +111,17 @@ impl Connection { .iter() .map(|p| pid.grid.grid_to_screen(*p)) .collect(); - Connection::draw_segment(&pid.grid, painter, color, start, *points.first().unwrap()); + Connection::draw_segment( + &pid.grid, + painter, + color, + start, + *points.first().log_unwrap(), + ); for i in 0..(points.len() - 1) { Connection::draw_segment(&pid.grid, painter, color, points[i], points[i + 1]); } - Connection::draw_segment(&pid.grid, painter, color, *points.last().unwrap(), end); + Connection::draw_segment(&pid.grid, painter, color, *points.last().log_unwrap(), end); if pid.editable { for point in points { @@ -124,9 +130,10 @@ impl Connection { glam_to_egui(point).to_pos2(), egui::Vec2::splat(CONNECTION_POINT_SIZE * pid.grid.size()), ), - Rounding::ZERO, + CornerRadius::ZERO, Color32::DARK_GRAY, Stroke::NONE, + StrokeKind::Middle, ); } } @@ -136,7 +143,7 @@ impl Connection { fn draw_segment(grid: &GridInfo, painter: &Painter, color: Color32, a: Vec2, b: Vec2) { painter.line_segment( [glam_to_egui(a).to_pos2(), glam_to_egui(b).to_pos2()], - PathStroke::new(CONNECTION_LINE_THICKNESS * grid.size(), color), + (CONNECTION_LINE_THICKNESS * grid.size(), color), ); } } diff --git a/src/ui/panes/pid_drawing_tool/elements.rs b/src/ui/panes/pid_drawing_tool/elements.rs index f64649842abc007f0dd81773b9737bc9757e2ca6..dc8f55fae1447c662a0749436956f6c2a7d7770b 100644 --- a/src/ui/panes/pid_drawing_tool/elements.rs +++ b/src/ui/panes/pid_drawing_tool/elements.rs @@ -1,14 +1,15 @@ -use std::f32::consts::PI; +use std::f32::consts::FRAC_PI_2; -use crate::{error::ErrInstrument, msg_broker, MSG_MANAGER}; +use egui::{Theme, Ui}; +use glam::{Mat2, Vec2}; +use serde::{Deserialize, Serialize}; + +use crate::mavlink::MavMessage; use super::{ grid::GridInfo, - symbols::{icons::Icon, Symbol, SymbolBehavior}, + symbols::{Symbol, SymbolBehavior}, }; -use egui::{Theme, Ui}; -use glam::{Mat2, Vec2}; -use serde::{Deserialize, Serialize}; #[derive(Clone, Serialize, Deserialize, Debug)] pub struct Element { @@ -77,11 +78,11 @@ impl Element { match &mut self.symbol { Symbol::Icon(_) => { if ui.button("Rotate 90° ⟲").clicked() { - self.rotate(-PI / 2.0); + self.rotate(-FRAC_PI_2); ui.close_menu(); } if ui.button("Rotate 90° ⟳").clicked() { - self.rotate(PI / 2.0); + self.rotate(FRAC_PI_2); ui.close_menu(); } } @@ -134,11 +135,9 @@ impl Element { let pos = grid.grid_to_screen(self.position); let size = grid.size(); self.symbol.paint(ui, theme, pos, size, self.rotation); + } - if let Symbol::Icon(Icon::MotorValve(motor_valve)) = &mut self.symbol { - msg_broker!().refresh_view(motor_valve).log_expect("bruh"); - } else if let Symbol::Label(label) = &mut self.symbol { - msg_broker!().refresh_view(label).log_expect("bruh"); - } + pub fn update(&mut self, message: &MavMessage) { + self.symbol.update(message); } } diff --git a/src/ui/panes/pid_drawing_tool/symbols.rs b/src/ui/panes/pid_drawing_tool/symbols.rs index 4f8f4a8b26befc953a20d79578743b82893eb20e..30bdb17b6f49c9cf8e46764e9a37e9eb68df7306 100644 --- a/src/ui/panes/pid_drawing_tool/symbols.rs +++ b/src/ui/panes/pid_drawing_tool/symbols.rs @@ -1,7 +1,6 @@ pub mod icons; mod labels; -use crate::mavlink::ViewId; use egui::{Theme, Ui}; use enum_dispatch::enum_dispatch; use glam::Vec2; @@ -10,6 +9,8 @@ use labels::Label; use serde::{Deserialize, Serialize}; use strum_macros::{Display, EnumIter}; +use crate::mavlink::MavMessage; + #[derive(Clone, Serialize, Deserialize, PartialEq, EnumIter, Display, Debug)] #[enum_dispatch] pub enum Symbol { @@ -36,6 +37,8 @@ pub trait SymbolBehavior { /// Symbol size in grid coordinates fn size(&self) -> Vec2; + fn update(&mut self, message: &MavMessage); + // /// Anchor point position relative to top right corner in grid units // pub fn anchor_points(&self) -> Vec<Vec2> { // match self { @@ -60,30 +63,3 @@ pub trait SymbolBehavior { fn context_menu(&mut self, ui: &mut Ui) {} } - -/// Single MavLink value source info -#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)] -#[serde(from = "SerialMavlinkValue")] -struct MavlinkValue { - msg_id: u32, - field: String, - - #[serde(skip)] - view_id: ViewId, -} - -#[derive(Deserialize)] -struct SerialMavlinkValue { - msg_id: u32, - field: String, -} - -impl From<SerialMavlinkValue> for MavlinkValue { - fn from(value: SerialMavlinkValue) -> Self { - Self { - msg_id: value.msg_id, - field: value.field, - view_id: ViewId::new(), - } - } -} diff --git a/src/ui/panes/pid_drawing_tool/symbols/icons.rs b/src/ui/panes/pid_drawing_tool/symbols/icons.rs index 5653b2635be6f62d10537c3be77b26c232051296..fcadab83a20f758aaa917cb29072f88396857d46 100644 --- a/src/ui/panes/pid_drawing_tool/symbols/icons.rs +++ b/src/ui/panes/pid_drawing_tool/symbols/icons.rs @@ -1,16 +1,12 @@ mod motor_valve; -use egui::{ImageSource, Theme, Ui}; +use egui::{ImageSource, Theme}; use glam::Vec2; use motor_valve::MotorValve; use serde::{Deserialize, Serialize}; use strum_macros::{Display, EnumIter}; -use crate::{ - mavlink::{MessageBroker, ViewId}, - msg_broker, - ui::utils::glam_to_egui, -}; +use crate::{mavlink::MavMessage, ui::utils::glam_to_egui}; use super::SymbolBehavior; @@ -167,6 +163,12 @@ impl SymbolBehavior for Icon { .paint_at(ui, image_rect); } + fn update(&mut self, message: &MavMessage) { + if let Icon::MotorValve(state) = self { + state.update(message) + } + } + fn anchor_points(&self) -> Option<Vec<glam::Vec2>> { Some( match self { @@ -209,30 +211,3 @@ impl SymbolBehavior for Icon { .into() } } - -/// Single MavLink value source info -#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)] -#[serde(from = "SerialMavlinkValue")] -struct MavlinkValue { - msg_id: u32, - field: String, - - #[serde(skip)] - view_id: ViewId, -} - -#[derive(Deserialize)] -struct SerialMavlinkValue { - msg_id: u32, - field: String, -} - -impl From<SerialMavlinkValue> for MavlinkValue { - fn from(value: SerialMavlinkValue) -> Self { - Self { - msg_id: value.msg_id, - field: value.field, - view_id: ViewId::new(), - } - } -} diff --git a/src/ui/panes/pid_drawing_tool/symbols/icons/motor_valve.rs b/src/ui/panes/pid_drawing_tool/symbols/icons/motor_valve.rs index 09819c6f1e26a087185386955b340e0e51338457..584e21e4157338f4ca930b7233e00cc670f08ab6 100644 --- a/src/ui/panes/pid_drawing_tool/symbols/icons/motor_valve.rs +++ b/src/ui/panes/pid_drawing_tool/symbols/icons/motor_valve.rs @@ -1,60 +1,38 @@ -use crate::mavlink::{extract_from_message, MavlinkResult, MessageView, TimedMessage, ViewId}; - -use super::MavlinkValue; - use serde::{Deserialize, Serialize}; -use skyward_mavlink::{mavlink::MessageData, orion}; + +use crate::{ + MAVLINK_PROFILE, + error::ErrInstrument, + mavlink::{ + GSE_TM_DATA, MavMessage, Message, MessageData, + reflection::{FieldLike, IndexedField}, + }, +}; #[derive(Clone, Serialize, Deserialize, PartialEq, Debug)] pub struct MotorValve { - source: MavlinkValue, + mavlink_field: IndexedField, /// false = closed, true = open pub last_value: Option<bool>, } -impl Default for MotorValve { - fn default() -> Self { - Self { - source: MavlinkValue { - msg_id: orion::GSE_TM_DATA::ID, - field: "n2o_filling_valve_state".to_string(), - view_id: ViewId::new(), - }, - last_value: None, +impl MotorValve { + pub(super) fn update(&mut self, msg: &MavMessage) { + if msg.message_id() == GSE_TM_DATA::ID { + let value = self.mavlink_field.extract_as_f64(msg).log_unwrap(); + self.last_value = Some(value != 0.0); } } } -impl MessageView for MotorValve { - fn view_id(&self) -> crate::mavlink::ViewId { - self.source.view_id - } - - fn id_of_interest(&self) -> u32 { - self.source.msg_id - } - - fn is_valid(&self) -> bool { - self.last_value.is_some() - } - - fn populate_view(&mut self, msg_slice: &[TimedMessage]) -> MavlinkResult<()> { - self.update_view(msg_slice) - } - - fn update_view(&mut self, msg_slice: &[TimedMessage]) -> MavlinkResult<()> { - if let Some(msg) = msg_slice.last() { - let values: MavlinkResult<Vec<Option<u8>>> = - extract_from_message(&msg.message, [&self.source.field]); - if let Ok(values) = values { - if !values.is_empty() { - if let Some(value) = values[0].map(|v| v != 0) { - self.last_value = Some(value); - } - } - } +impl Default for MotorValve { + fn default() -> Self { + Self { + mavlink_field: 19 + .to_mav_field(GSE_TM_DATA::ID, &MAVLINK_PROFILE) + .log_unwrap(), // n2_filling_valve_state for GSE_TM_DATA + last_value: None, } - Ok(()) } } diff --git a/src/ui/panes/pid_drawing_tool/symbols/labels.rs b/src/ui/panes/pid_drawing_tool/symbols/labels.rs index 7534969d4018fe799721a4b7e8486803eb4f26b9..1ca1979e23939fdd9770d525846ae750abb6a562 100644 --- a/src/ui/panes/pid_drawing_tool/symbols/labels.rs +++ b/src/ui/panes/pid_drawing_tool/symbols/labels.rs @@ -1,14 +1,19 @@ use serde::{Deserialize, Serialize}; -use skyward_mavlink::{mavlink::MessageData, orion}; + +use egui::{Align2, Color32, CornerRadius, FontId, Stroke, StrokeKind, Theme, Ui}; +use glam::Vec2; use crate::{ - mavlink::{extract_from_message, MavlinkResult, MessageView, ViewId}, + MAVLINK_PROFILE, + error::ErrInstrument, + mavlink::{ + GSE_TM_DATA, MavMessage, Message, MessageData, + reflection::{FieldLike, IndexedField}, + }, ui::utils::{egui_to_glam, glam_to_egui}, }; -use super::{MavlinkValue, SymbolBehavior}; -use egui::{Align2, Color32, FontId, Rounding, Stroke, Theme, Ui}; -use glam::Vec2; +use super::SymbolBehavior; const FONT_SIZE: f32 = 2.0; @@ -20,7 +25,7 @@ pub struct Label { show_window: bool, last_value: Option<f32>, - source: MavlinkValue, + mavlink_field: IndexedField, size: Vec2, } @@ -30,11 +35,9 @@ impl Default for Label { text: "0.00".to_string(), units: "".to_string(), show_window: false, - source: MavlinkValue { - msg_id: orion::GSE_TM_DATA::ID, - field: "n2o_vessel_pressure".to_string(), - view_id: ViewId::new(), - }, + mavlink_field: 6 + .to_mav_field(GSE_TM_DATA::ID, &MAVLINK_PROFILE) + .log_unwrap(), // n2_vessel_1_pressure for GSE_TM_DATA last_value: Some(0.0), size: Vec2::new(FONT_SIZE * 0.6 * 4.0, FONT_SIZE), } @@ -62,9 +65,10 @@ impl SymbolBehavior for Label { glam_to_egui(pos).to_pos2(), glam_to_egui(self.size()) * size, ), - Rounding::ZERO, + CornerRadius::ZERO, Color32::TRANSPARENT, - Stroke::new(1.0, color), + Stroke::NONE, + StrokeKind::Middle, ); println!("Drawing label edit window {}", self.show_window); @@ -81,6 +85,14 @@ impl SymbolBehavior for Label { self.show_window = show_window; } + fn update(&mut self, message: &MavMessage) { + if message.message_id() == GSE_TM_DATA::ID { + let value = self.mavlink_field.extract_as_f64(message).log_unwrap(); + self.last_value = Some(value as f32); + self.text = format!("{:.2}{}", value, self.units); + } + } + fn anchor_points(&self) -> Option<Vec<Vec2>> { None } @@ -97,43 +109,3 @@ impl SymbolBehavior for Label { } } } - -impl MessageView for Label { - fn view_id(&self) -> ViewId { - self.source.view_id - } - - fn id_of_interest(&self) -> u32 { - self.source.msg_id - } - - fn is_valid(&self) -> bool { - self.last_value.is_some() - } - - fn populate_view( - &mut self, - msg_slice: &[crate::mavlink::TimedMessage], - ) -> crate::mavlink::MavlinkResult<()> { - self.update_view(msg_slice) - } - - fn update_view( - &mut self, - msg_slice: &[crate::mavlink::TimedMessage], - ) -> crate::mavlink::MavlinkResult<()> { - if let Some(msg) = msg_slice.last() { - let values: MavlinkResult<Vec<Option<f32>>> = - extract_from_message(&msg.message, [&self.source.field]); - if let Ok(values) = values { - if !values.is_empty() { - if let Some(value) = values[0] { - self.last_value = Some(value); - self.text = format!("{:.2}{}", value, self.units); - } - } - } - } - Ok(()) - } -}