Skip to main content

oxihuman_viewer/
geometry_node_view.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5//! Geometry nodes graph view.
6
7/// Type of geometry node.
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub enum GeoNodeType {
10    Input,
11    Output,
12    Transform,
13    Mesh,
14    Curve,
15    Custom,
16}
17
18/// A geometry node.
19#[derive(Debug, Clone)]
20pub struct GeoNode {
21    pub id: u32,
22    pub node_type: GeoNodeType,
23    pub label: String,
24}
25
26/// State for the geometry node view.
27#[derive(Debug, Clone)]
28pub struct GeometryNodeView {
29    pub nodes: Vec<GeoNode>,
30    pub zoom: f32,
31    pub show_sockets: bool,
32    pub enabled: bool,
33}
34
35/// Create a new geometry node view.
36pub fn new_geometry_node_view() -> GeometryNodeView {
37    GeometryNodeView {
38        nodes: Vec::new(),
39        zoom: 1.0,
40        show_sockets: true,
41        enabled: true,
42    }
43}
44
45/// Add a geometry node.
46pub fn gnv_add_node(v: &mut GeometryNodeView, id: u32, node_type: GeoNodeType, label: &str) {
47    v.nodes.push(GeoNode {
48        id,
49        node_type,
50        label: label.to_string(),
51    });
52}
53
54/// Clear all nodes.
55pub fn gnv_clear(v: &mut GeometryNodeView) {
56    v.nodes.clear();
57}
58
59/// Set zoom level (clamped 0.1–10).
60pub fn gnv_set_zoom(v: &mut GeometryNodeView, zoom: f32) {
61    v.zoom = zoom.clamp(0.1, 10.0);
62}
63
64/// Count nodes of a given type.
65pub fn gnv_count_type(v: &GeometryNodeView, t: &GeoNodeType) -> usize {
66    v.nodes.iter().filter(|n| &n.node_type == t).count()
67}
68
69/// Serialise to JSON.
70pub fn gnv_to_json(v: &GeometryNodeView) -> String {
71    format!(
72        r#"{{"node_count":{},"zoom":{:.2},"enabled":{}}}"#,
73        v.nodes.len(),
74        v.zoom,
75        v.enabled
76    )
77}
78
79#[cfg(test)]
80mod tests {
81    use super::*;
82
83    #[test]
84    fn default_empty() {
85        let v = new_geometry_node_view();
86        assert!(v.nodes.is_empty() /* no nodes */);
87    }
88
89    #[test]
90    fn add_node_increases_count() {
91        let mut v = new_geometry_node_view();
92        gnv_add_node(&mut v, 1, GeoNodeType::Mesh, "Mesh");
93        assert_eq!(v.nodes.len(), 1 /* one node */);
94    }
95
96    #[test]
97    fn clear_removes_all() {
98        let mut v = new_geometry_node_view();
99        gnv_add_node(&mut v, 1, GeoNodeType::Input, "In");
100        gnv_clear(&mut v);
101        assert!(v.nodes.is_empty() /* cleared */);
102    }
103
104    #[test]
105    fn count_type() {
106        let mut v = new_geometry_node_view();
107        gnv_add_node(&mut v, 1, GeoNodeType::Mesh, "M1");
108        gnv_add_node(&mut v, 2, GeoNodeType::Mesh, "M2");
109        gnv_add_node(&mut v, 3, GeoNodeType::Curve, "C1");
110        assert_eq!(
111            gnv_count_type(&v, &GeoNodeType::Mesh),
112            2 /* two mesh nodes */
113        );
114    }
115
116    #[test]
117    fn zoom_clamp() {
118        let mut v = new_geometry_node_view();
119        gnv_set_zoom(&mut v, 50.0);
120        assert!((v.zoom - 10.0).abs() < 1e-6 /* clamped */);
121    }
122
123    #[test]
124    fn show_sockets_default_true() {
125        let v = new_geometry_node_view();
126        assert!(v.show_sockets /* sockets shown by default */);
127    }
128
129    #[test]
130    fn json_has_node_count() {
131        let v = new_geometry_node_view();
132        assert!(gnv_to_json(&v).contains("node_count") /* json field */);
133    }
134
135    #[test]
136    fn enabled_default() {
137        let v = new_geometry_node_view();
138        assert!(v.enabled /* enabled */);
139    }
140}