#![allow(dead_code)]
#[derive(Debug, Clone)]
pub struct PickingOverlayConfig {
pub highlight_color: (u8, u8, u8, u8),
pub show_tooltip: bool,
pub tooltip_color: (u8, u8, u8, u8),
}
#[derive(Debug, Clone)]
pub struct PickedObject {
pub id: u64,
pub name: String,
pub object_type: String,
pub hit_position: (f64, f64, f64),
}
#[derive(Debug, Clone)]
pub struct PickingOverlayState {
pub picked: Option<PickedObject>,
pub highlight_color: (u8, u8, u8, u8),
pub show_tooltip: bool,
pub tooltip_color: (u8, u8, u8, u8),
}
pub fn default_picking_overlay_config() -> PickingOverlayConfig {
PickingOverlayConfig {
highlight_color: (255, 200, 0, 180),
show_tooltip: true,
tooltip_color: (30, 30, 30, 220),
}
}
pub fn new_picking_overlay(cfg: &PickingOverlayConfig) -> PickingOverlayState {
PickingOverlayState {
picked: None,
highlight_color: cfg.highlight_color,
show_tooltip: cfg.show_tooltip,
tooltip_color: cfg.tooltip_color,
}
}
pub fn picking_overlay_set_picked(state: &mut PickingOverlayState, obj: PickedObject) {
state.picked = Some(obj);
}
pub fn picking_overlay_clear(state: &mut PickingOverlayState) {
state.picked = None;
}
pub fn picking_overlay_is_active(state: &PickingOverlayState) -> bool {
state.picked.is_some()
}
pub fn picking_overlay_object_name(state: &PickingOverlayState) -> &str {
match &state.picked {
Some(obj) => &obj.name,
None => "",
}
}
pub fn picking_overlay_show_tooltip(state: &PickingOverlayState) -> bool {
state.show_tooltip
}
pub fn picking_overlay_to_json(state: &PickingOverlayState) -> String {
let picked_json = match &state.picked {
Some(obj) => format!(
"{{\"id\":{},\"name\":\"{}\",\"type\":\"{}\",\"hit\":[{:.4},{:.4},{:.4}]}}",
obj.id, obj.name, obj.object_type, obj.hit_position.0, obj.hit_position.1, obj.hit_position.2
),
None => "null".to_string(),
};
format!(
"{{\"highlight_color\":[{},{},{},{}],\"show_tooltip\":{},\"picked\":{}}}",
state.highlight_color.0,
state.highlight_color.1,
state.highlight_color.2,
state.highlight_color.3,
state.show_tooltip,
picked_json
)
}
pub fn picking_overlay_reset(state: &mut PickingOverlayState) {
let cfg = default_picking_overlay_config();
state.picked = None;
state.highlight_color = cfg.highlight_color;
state.show_tooltip = cfg.show_tooltip;
state.tooltip_color = cfg.tooltip_color;
}
pub fn picking_overlay_color(state: &PickingOverlayState) -> (u8, u8, u8, u8) {
state.highlight_color
}
fn make_picked(id: u64, name: &str, object_type: &str, hit: (f64, f64, f64)) -> PickedObject {
PickedObject {
id,
name: name.to_string(),
object_type: object_type.to_string(),
hit_position: hit,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_config_values() {
let cfg = default_picking_overlay_config();
assert_eq!(cfg.highlight_color, (255, 200, 0, 180));
assert!(cfg.show_tooltip);
}
#[test]
fn new_overlay_has_no_pick() {
let cfg = default_picking_overlay_config();
let state = new_picking_overlay(&cfg);
assert!(!picking_overlay_is_active(&state));
assert_eq!(picking_overlay_object_name(&state), "");
}
#[test]
fn set_picked_activates_overlay() {
let cfg = default_picking_overlay_config();
let mut state = new_picking_overlay(&cfg);
picking_overlay_set_picked(&mut state, make_picked(1, "BodyMesh", "mesh", (0.0, 0.0, 0.0)));
assert!(picking_overlay_is_active(&state));
assert_eq!(picking_overlay_object_name(&state), "BodyMesh");
}
#[test]
fn clear_removes_picked() {
let cfg = default_picking_overlay_config();
let mut state = new_picking_overlay(&cfg);
picking_overlay_set_picked(&mut state, make_picked(1, "Bone", "bone", (1.0, 2.0, 3.0)));
picking_overlay_clear(&mut state);
assert!(!picking_overlay_is_active(&state));
}
#[test]
fn show_tooltip_returns_config_value() {
let cfg = default_picking_overlay_config();
let state = new_picking_overlay(&cfg);
assert!(picking_overlay_show_tooltip(&state));
}
#[test]
fn color_returns_highlight_color() {
let cfg = default_picking_overlay_config();
let state = new_picking_overlay(&cfg);
assert_eq!(picking_overlay_color(&state), (255, 200, 0, 180));
}
#[test]
fn json_contains_highlight_and_picked() {
let cfg = default_picking_overlay_config();
let mut state = new_picking_overlay(&cfg);
picking_overlay_set_picked(&mut state, make_picked(42, "Light", "light", (1.0, 2.0, 3.0)));
let json = picking_overlay_to_json(&state);
assert!(json.contains("highlight_color"));
assert!(json.contains("\"Light\""));
}
#[test]
fn json_null_when_no_pick() {
let cfg = default_picking_overlay_config();
let state = new_picking_overlay(&cfg);
let json = picking_overlay_to_json(&state);
assert!(json.contains("\"picked\":null"));
}
#[test]
fn reset_clears_pick_and_restores_defaults() {
let cfg = default_picking_overlay_config();
let mut state = new_picking_overlay(&cfg);
picking_overlay_set_picked(&mut state, make_picked(1, "X", "mesh", (0.0, 0.0, 0.0)));
state.show_tooltip = false;
picking_overlay_reset(&mut state);
assert!(!picking_overlay_is_active(&state));
assert!(picking_overlay_show_tooltip(&state));
}
}