use std::sync::Mutex;
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Node {
pub rect: [f32; 4],
pub id: egui::accesskit::NodeId,
}
static NODES: Mutex<Vec<Node>> = Mutex::new(Vec::new());
fn lock() -> std::sync::MutexGuard<'static, Vec<Node>> {
NODES.lock().unwrap_or_else(|p| p.into_inner())
}
pub struct ActionTree;
impl egui::Plugin for ActionTree {
fn debug_name(&self) -> &'static str {
"brep-action-tree"
}
fn output_hook(&mut self, _ctx: &egui::Context, output: &mut egui::FullOutput) {
if !DRAWS.load(std::sync::atomic::Ordering::Relaxed) {
return;
}
let Some(update) = &output.platform_output.accesskit_update else { return };
let nodes = update
.nodes
.iter()
.filter(|(_, node)| node.supports_action(egui::accesskit::Action::Click) && !node.is_disabled())
.filter_map(|(id, node)| {
let b = node.bounds()?;
Some(Node { rect: [b.x0 as f32, b.y0 as f32, (b.x1 - b.x0) as f32, (b.y1 - b.y0) as f32], id: *id })
})
.collect();
*lock() = nodes;
}
}
pub fn install(ctx: &egui::Context) {
ctx.add_plugin(ActionTree);
}
static DRAWS: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(true);
pub fn note_pass(ctx: &egui::Context, draws: bool) -> bool {
let drew = DRAWS.swap(draws, std::sync::atomic::Ordering::Relaxed);
if crate::automation::registry::enabled() {
ctx.enable_accesskit();
}
drew
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum Matched {
Exact,
Contains,
}
pub fn resolve(nodes: &[Node], rect: [f32; 4]) -> Option<(Node, Matched)> {
const EPS: f32 = 0.01;
if let Some(node) = nodes.iter().find(|n| n.rect.iter().zip(rect).all(|(a, b)| (a - b).abs() <= EPS)) {
return Some((*node, Matched::Exact));
}
let (cx, cy) = (rect[0] + rect[2] / 2.0, rect[1] + rect[3] / 2.0);
nodes
.iter()
.filter(|n| cx >= n.rect[0] && cy >= n.rect[1] && cx <= n.rect[0] + n.rect[2] && cy <= n.rect[1] + n.rect[3])
.min_by(|a, b| (a.rect[2] * a.rect[3]).total_cmp(&(b.rect[2] * b.rect[3])))
.map(|n| (*n, Matched::Contains))
}
pub fn nodes() -> Vec<Node> {
lock().clone()
}