Skip to main content

mittens_engine/engine/ecs/component/
uv.rs

1use crate::engine::ecs::ComponentId;
2use crate::engine::ecs::component::Component;
3
4/// Per-vertex UVs for a renderable.
5///
6/// This is intended to be attached as a descendant of a `RenderableComponent`.
7///
8/// Lifecycle note:
9/// - UV overrides are applied when the renderable is flushed into `VisualWorld` / uploaded.
10/// - If fewer UVs are provided than the mesh's vertex count, the missing UVs are filled with 0.
11#[derive(Debug, Clone)]
12pub struct UVComponent {
13    pub uvs: Vec<[f32; 2]>,
14}
15
16impl UVComponent {
17    pub fn new() -> Self {
18        Self { uvs: Vec::new() }
19    }
20
21    /// Construct from a nested vector, where each inner vec is `[u, v]`.
22    ///
23    /// - If an inner vec has <2 values, missing values are treated as 0.
24    /// - If it has >2 values, extras are ignored.
25    pub fn from_vec(uvs: Vec<Vec<f32>>) -> Self {
26        let mut out: Vec<[f32; 2]> = Vec::with_capacity(uvs.len());
27        for uv in uvs {
28            let u = uv.get(0).copied().unwrap_or(0.0);
29            let v = uv.get(1).copied().unwrap_or(0.0);
30            out.push([u, v]);
31        }
32        Self { uvs: out }
33    }
34
35    pub fn with_uv(mut self, u: f32, v: f32) -> Self {
36        self.uvs.push([u, v]);
37        self
38    }
39}
40
41impl Default for UVComponent {
42    fn default() -> Self {
43        Self::new()
44    }
45}
46
47impl Component for UVComponent {
48    fn name(&self) -> &'static str {
49        "uv"
50    }
51
52    fn as_any(&self) -> &dyn std::any::Any {
53        self
54    }
55
56    fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
57        self
58    }
59
60    fn init(&mut self, emit: &mut dyn crate::engine::ecs::SignalEmitter, component: ComponentId) {
61        emit.push_intent_now(
62            component,
63            crate::engine::ecs::IntentValue::RegisterUv {
64                component_ids: vec![component],
65            },
66        );
67    }
68
69    fn to_mms_ast(
70        &self,
71        _world: &crate::engine::ecs::World,
72    ) -> crate::scripting::ast::ComponentExpression {
73        use crate::engine::ecs::component::ce_helpers::*;
74        let mut ce = ce("UV");
75        for [u, v] in &self.uvs {
76            ce = ce.with_call("uv", vec![num(*u as f64), num(*v as f64)]);
77        }
78        ce
79    }
80}