Skip to main content

oxihuman_viewer/
texture_node_view.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5//! Texture node graph view.
6
7/// A texture node entry.
8#[derive(Debug, Clone)]
9pub struct TextureNode {
10    pub id: u32,
11    pub name: String,
12    pub width: u32,
13    pub height: u32,
14}
15
16/// State for the texture node view.
17#[derive(Debug, Clone)]
18pub struct TextureNodeView {
19    pub nodes: Vec<TextureNode>,
20    pub selected_id: Option<u32>,
21    pub zoom: f32,
22    pub enabled: bool,
23}
24
25/// Create a new texture node view.
26pub fn new_texture_node_view() -> TextureNodeView {
27    TextureNodeView {
28        nodes: Vec::new(),
29        selected_id: None,
30        zoom: 1.0,
31        enabled: true,
32    }
33}
34
35/// Add a texture node.
36pub fn tnv_add_node(v: &mut TextureNodeView, id: u32, name: &str, width: u32, height: u32) {
37    v.nodes.push(TextureNode {
38        id,
39        name: name.to_string(),
40        width,
41        height,
42    });
43}
44
45/// Select a texture node by ID.
46pub fn tnv_select(v: &mut TextureNodeView, id: u32) {
47    v.selected_id = Some(id);
48}
49
50/// Deselect all.
51pub fn tnv_deselect(v: &mut TextureNodeView) {
52    v.selected_id = None;
53}
54
55/// Set zoom level (clamped 0.1–10).
56pub fn tnv_set_zoom(v: &mut TextureNodeView, zoom: f32) {
57    v.zoom = zoom.clamp(0.1, 10.0);
58}
59
60/// Serialise to JSON.
61pub fn tnv_to_json(v: &TextureNodeView) -> String {
62    format!(
63        r#"{{"node_count":{},"selected":{:?},"zoom":{:.2},"enabled":{}}}"#,
64        v.nodes.len(),
65        v.selected_id,
66        v.zoom,
67        v.enabled
68    )
69}
70
71#[cfg(test)]
72mod tests {
73    use super::*;
74
75    #[test]
76    fn default_empty() {
77        let v = new_texture_node_view();
78        assert!(v.nodes.is_empty() /* no nodes */);
79    }
80
81    #[test]
82    fn add_node() {
83        let mut v = new_texture_node_view();
84        tnv_add_node(&mut v, 1, "Albedo", 1024, 1024);
85        assert_eq!(v.nodes.len(), 1 /* one node */);
86    }
87
88    #[test]
89    fn select_node() {
90        let mut v = new_texture_node_view();
91        tnv_select(&mut v, 5);
92        assert_eq!(v.selected_id, Some(5) /* selected */);
93    }
94
95    #[test]
96    fn deselect_clears() {
97        let mut v = new_texture_node_view();
98        tnv_select(&mut v, 3);
99        tnv_deselect(&mut v);
100        assert_eq!(v.selected_id, None /* deselected */);
101    }
102
103    #[test]
104    fn zoom_clamps_upper() {
105        let mut v = new_texture_node_view();
106        tnv_set_zoom(&mut v, 100.0);
107        assert!((v.zoom - 10.0).abs() < 1e-6 /* clamped to 10 */);
108    }
109
110    #[test]
111    fn zoom_clamps_lower() {
112        let mut v = new_texture_node_view();
113        tnv_set_zoom(&mut v, 0.0);
114        assert!((v.zoom - 0.1).abs() < 1e-6 /* clamped to 0.1 */);
115    }
116
117    #[test]
118    fn json_has_node_count() {
119        let v = new_texture_node_view();
120        assert!(tnv_to_json(&v).contains("node_count") /* json has field */);
121    }
122
123    #[test]
124    fn node_dimensions_stored() {
125        let mut v = new_texture_node_view();
126        tnv_add_node(&mut v, 2, "Normal", 512, 512);
127        assert_eq!(v.nodes[0].width, 512 /* width stored */);
128    }
129}