added some clear states (and bugs)
This commit is contained in:
parent
386e632efb
commit
66acd4698f
9 changed files with 111 additions and 63 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1153,7 +1153,7 @@ checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
|||
|
||||
[[package]]
|
||||
name = "joystick-controller-client"
|
||||
version = "1.1.0"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"config",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "joystick-controller-client"
|
||||
version = "1.1.0"
|
||||
version = "2.0.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
|
|
@ -36,7 +36,7 @@ impl TrackerMetrics {
|
|||
for _ in 0..10 {
|
||||
self.tracker_times.pop_front();
|
||||
}
|
||||
self.insert_time(Duration::new(0, 0));
|
||||
// self.insert_time(Duration::new(0, 0));
|
||||
if let Ok(mut writer) = self.header_text.write() {
|
||||
writer.clear();
|
||||
writer.push_str("Status: Disconnected");
|
||||
|
|
|
@ -146,6 +146,24 @@ pub async fn remote_video_loop(
|
|||
let mut tm = tracker_metrics.lock().await;
|
||||
tm.clear_times();
|
||||
}
|
||||
{
|
||||
if let Ok(mut ts) = tracker_state.lock() {
|
||||
ts.clear();
|
||||
}
|
||||
// This message forces a redraw after clearing the queue
|
||||
if let Err(e) = to_mec
|
||||
.send(ApplicationEvent::MoveEvent(
|
||||
crate::coordinator::MoveEvent { x: 0, y: 0 },
|
||||
crate::coordinator::ConnectionType::Automated,
|
||||
))
|
||||
.await
|
||||
{
|
||||
error!(
|
||||
"Error sending message to MEC during shutdown of tracker thread: {}",
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
socket_state.is_connected.store(false, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ const APP_ID: &str = "net.nickiel.joystick-controller-client";
|
|||
fn main() -> glib::ExitCode {
|
||||
// set the environment var to make gtk use window's default action bar
|
||||
env::set_var("gtk_csd", "0");
|
||||
|
||||
|
||||
// #[cfg(not(debug_assertions))]
|
||||
let file_appender = tracing_appender::rolling::daily(".\\logs", "camera-controller");
|
||||
let (non_blocking, _gaurd) = tracing_appender::non_blocking(file_appender);
|
||||
|
|
|
@ -37,6 +37,17 @@ pub struct TrackerState {
|
|||
pub identity_boxes: Vec<NormalizedBoxCoords>,
|
||||
}
|
||||
|
||||
impl TrackerState {
|
||||
pub fn clear(&mut self) {
|
||||
self.tracking_id = 0;
|
||||
self.highlighted_id = None;
|
||||
self.last_detect = Instant::now();
|
||||
self.enabled = false;
|
||||
self.update_ids = false;
|
||||
self.identity_boxes.clear();
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(rt, mec))]
|
||||
pub async fn start_socketserver(
|
||||
rt: Handle,
|
||||
|
|
|
@ -24,6 +24,7 @@ pub struct ControlPanel {
|
|||
pub current_id: Label,
|
||||
|
||||
pub items: StringList,
|
||||
pub list_view: ListView,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -51,7 +52,7 @@ impl ControlPanel {
|
|||
.bind(&label, "label", Widget::NONE);
|
||||
});
|
||||
|
||||
let items = StringList::new(&["item1", "item2", "item3"]);
|
||||
let items = StringList::new(&["Please connect automatic source"]);
|
||||
|
||||
let model = SingleSelection::builder()
|
||||
.model(&items)
|
||||
|
@ -114,6 +115,7 @@ impl ControlPanel {
|
|||
current_id,
|
||||
|
||||
items,
|
||||
list_view,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -183,11 +183,12 @@ fn calc_box_under_mouse(
|
|||
|
||||
let overlap_area =
|
||||
(median_two_x[1] - median_two_x[0]) * (median_two_y[1] - median_two_y[0]);
|
||||
|
||||
|
||||
// We want the one with the largest percentage of it's area as overlap
|
||||
// to be the highlighted one
|
||||
mouse_over.sort_by(|a, b| {
|
||||
let result = ((a.area() - overlap_area) / a.area()) - ((b.area() - overlap_area) / b.area());
|
||||
let result =
|
||||
((a.area() - overlap_area) / a.area()) - ((b.area() - overlap_area) / b.area());
|
||||
if 0.0001 > result && result > -0.0001 {
|
||||
Ordering::Equal
|
||||
} else if result > 0.0 {
|
||||
|
@ -195,7 +196,7 @@ fn calc_box_under_mouse(
|
|||
} else {
|
||||
Ordering::Less
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
mouse_over
|
||||
|
|
126
src/ui/mod.rs
126
src/ui/mod.rs
|
@ -1,6 +1,6 @@
|
|||
use std::fmt::Display;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Instant;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use gtk::cairo::Context;
|
||||
use gtk::gdk::Paintable;
|
||||
|
@ -191,61 +191,73 @@ pub fn build_ui(app: &Application, config: Arc<RwLock<AppConfig>>, runtime: Hand
|
|||
|
||||
let items = control_panel.items.clone();
|
||||
let id_label = control_panel.current_id.clone();
|
||||
let model = control_panel
|
||||
.list_view
|
||||
.model()
|
||||
.expect("The list view should have a model!");
|
||||
|
||||
glib::timeout_add_seconds_local(
|
||||
1,
|
||||
glib::clone!(@strong items, @strong id_label => move || {
|
||||
#[cfg(feature = "tracker-state-debug")]
|
||||
debug!("Getting lock on tracker state for checking identity boxes");
|
||||
glib::timeout_add_local(Duration::from_millis(500), move || {
|
||||
#[cfg(feature = "tracker-state-debug")]
|
||||
debug!("Getting lock on tracker state for checking identity boxes");
|
||||
|
||||
// don't update the stringlist until after letting go of the tracker state
|
||||
// due to async interweaving causing a mutex deadlock
|
||||
let mut ids: Option<Vec<String>> = None;
|
||||
let mut current_id: Option<u32> = None;
|
||||
if let Ok(ts) = tracker_state.lock() {
|
||||
current_id = Some(ts.tracking_id);
|
||||
if ts.update_ids {
|
||||
ids = Some(ts.identity_boxes
|
||||
.iter()
|
||||
.map(|t| t.id.to_string())
|
||||
.collect());
|
||||
// don't update the stringlist until after letting go of the tracker state
|
||||
// due to async interweaving causing a mutex deadlock
|
||||
let mut ids: Option<Vec<String>> = None;
|
||||
let mut current_id: u32 = 0;
|
||||
if let Ok(ts) = tracker_state.lock() {
|
||||
current_id = ts.tracking_id;
|
||||
if ts.update_ids {
|
||||
ids = Some(ts.identity_boxes.iter().map(|t| t.id.to_string()).collect());
|
||||
}
|
||||
}
|
||||
|
||||
if current_id > 0 {
|
||||
id_label.set_text(current_id.to_string().as_str());
|
||||
}
|
||||
|
||||
let current_id: String = current_id.to_string();
|
||||
|
||||
if let Some(mut ids) = ids {
|
||||
let mut active_index = 0;
|
||||
let mut to_delete_indexes: Vec<u32> = vec![];
|
||||
|
||||
// find all indexes where matching item does not exist in
|
||||
// the ids, list, and remove all items in the ids list
|
||||
// that already exists in the stringList
|
||||
for i in 0..items.n_items() {
|
||||
let item = items.string(i).unwrap_or("Empty".into()).to_string();
|
||||
if item == current_id {
|
||||
active_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(id) = current_id {
|
||||
id_label.set_text(id.to_string().as_str());
|
||||
}
|
||||
|
||||
if let Some(mut ids) = ids {
|
||||
let mut to_delete_indexes: Vec<u32> = vec![];
|
||||
|
||||
// find all indexes where matching item does not exist in
|
||||
// the ids, list, and remove all items in the ids list
|
||||
// that already exists in the stringList
|
||||
for i in 0..items.n_items() {
|
||||
let item = items.string(i).unwrap_or("Empty".into()).to_string();
|
||||
if !ids.contains(&item) {
|
||||
to_delete_indexes.push(i);
|
||||
} else {
|
||||
if let Some(pos) = ids.iter().position(|x| **x == item) {
|
||||
ids.remove(pos);
|
||||
}
|
||||
if !ids.contains(&item) {
|
||||
to_delete_indexes.push(i);
|
||||
} else {
|
||||
if let Some(pos) = ids.iter().position(|x| **x == item) {
|
||||
ids.remove(pos);
|
||||
}
|
||||
}
|
||||
|
||||
// invert the order so we don't have to adjust after each deletion
|
||||
to_delete_indexes.sort();
|
||||
to_delete_indexes.reverse();
|
||||
|
||||
to_delete_indexes.iter().for_each(|x| {
|
||||
items.remove(*x);
|
||||
});
|
||||
items.splice(items.n_items(), 0, &ids.iter().map(|x| x.as_str()).collect::<Vec<&str>>()[0..])
|
||||
}
|
||||
|
||||
glib::ControlFlow::Continue
|
||||
}),
|
||||
);
|
||||
if active_index > 0 {
|
||||
model.select_item(active_index, true);
|
||||
}
|
||||
|
||||
// invert the order so we don't have to adjust after each deletion
|
||||
to_delete_indexes.sort();
|
||||
to_delete_indexes.reverse();
|
||||
|
||||
to_delete_indexes.iter().for_each(|x| {
|
||||
items.remove(*x);
|
||||
});
|
||||
items.splice(
|
||||
items.n_items(),
|
||||
0,
|
||||
&ids.iter().map(|x| x.as_str()).collect::<Vec<&str>>()[0..],
|
||||
)
|
||||
}
|
||||
|
||||
glib::ControlFlow::Continue
|
||||
});
|
||||
|
||||
let tracker_status_label = liveview_panel.tracker_status_label.clone();
|
||||
let tracker_enable_toggle = control_panel
|
||||
|
@ -259,18 +271,21 @@ pub fn build_ui(app: &Application, config: Arc<RwLock<AppConfig>>, runtime: Hand
|
|||
if reader.contains("Failed") || reader.contains("Disconnected") {
|
||||
tracker_status_label.set_css_classes(&["NoConnection"]);
|
||||
|
||||
tracker_enable_toggle.set_label("Press to Connect Tracker");
|
||||
tracker_enable_toggle.set_label("Connect to Tracker Computer");
|
||||
tracker_enable_toggle.set_active(false);
|
||||
tracker_enable_toggle.set_sensitive(true);
|
||||
} else if reader.contains("Degraded") || reader.contains("Connecting") {
|
||||
tracker_status_label.set_css_classes(&["LoadingConnection"]);
|
||||
|
||||
tracker_enable_toggle.set_label("Press to Connect");
|
||||
tracker_enable_toggle.set_label("Please Wait");
|
||||
tracker_enable_toggle.set_active(false);
|
||||
tracker_enable_toggle.set_sensitive(false);
|
||||
} else if reader.contains("Nominal") {
|
||||
tracker_status_label.set_css_classes(&["YesConnection"]);
|
||||
|
||||
tracker_enable_toggle.set_label("Press to Disconnect");
|
||||
tracker_enable_toggle.set_label("Disconnect Tracker Computer");
|
||||
tracker_enable_toggle.set_active(true);
|
||||
tracker_enable_toggle.set_sensitive(true);
|
||||
}
|
||||
glib::ControlFlow::Continue
|
||||
} else {
|
||||
|
@ -290,7 +305,7 @@ pub fn build_ui(app: &Application, config: Arc<RwLock<AppConfig>>, runtime: Hand
|
|||
}
|
||||
GuiUpdate::SocketConnected => {
|
||||
control_panel.connection_buttons.camera_connection.set_sensitive(true);
|
||||
control_panel.connection_buttons.camera_connection.set_label("Press to Disconnect");
|
||||
control_panel.connection_buttons.camera_connection.set_label("Disconnect Camera");
|
||||
liveview_panel.cam_status_label.set_label("Connected");
|
||||
|
||||
liveview_panel.cam_status_label.set_css_classes(&["YesConnection"]);
|
||||
|
@ -306,7 +321,7 @@ pub fn build_ui(app: &Application, config: Arc<RwLock<AppConfig>>, runtime: Hand
|
|||
},
|
||||
GuiUpdate::SocketDisconnected => {
|
||||
control_panel.connection_buttons.camera_connection.set_sensitive(true);
|
||||
control_panel.connection_buttons.camera_connection.set_label("Press to Connect to Camera");
|
||||
control_panel.connection_buttons.camera_connection.set_label("Connect to Camera");
|
||||
liveview_panel.cam_status_label.set_label("Not Connected to Camera");
|
||||
|
||||
liveview_panel.cam_status_label.set_css_classes(&["NoConnection"]);
|
||||
|
@ -339,6 +354,7 @@ fn draw_boxes(width: i32, height: i32, ctx: &Context, tracker_state: &Arc<Mutex<
|
|||
#[cfg(feature = "tracker-state-debug")]
|
||||
debug!("Getting tracker state for drawing boxes");
|
||||
if let Ok(ts) = tracker_state.lock() {
|
||||
println!("ts currently tracking: {}", ts.tracking_id);
|
||||
let active = ts.tracking_id;
|
||||
let highlighted_id = ts.highlighted_id.unwrap_or(0);
|
||||
for nb in ts.identity_boxes.iter() {
|
||||
|
@ -349,7 +365,7 @@ fn draw_boxes(width: i32, height: i32, ctx: &Context, tracker_state: &Arc<Mutex<
|
|||
} else {
|
||||
ctx.set_source_rgb(0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
|
||||
if nb.id == active && nb.id == highlighted_id {
|
||||
ctx.set_source_rgb(1.0, 1.0, 0.0);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue