Skip to main content

cotis_wgpu/
cotis_traits.rs

1//! Cotis context and interactivity trait implementations for [`crate::renderer::CotisWgpuRenderer`].
2//!
3//! These impls connect the renderer to the Cotis application framework. They are defined here
4//! rather than in [`crate::renderer`] to keep the renderer module focused on GPU/window logic.
5//!
6//! | Trait | Behavior |
7//! |-------|----------|
8//! | [`cotis_utils::traits::CotisWindowContext`] | Returns physical window dimensions in pixels from winit `inner_size`. |
9//! | [`cotis_utils::traits::CotisFrameContext`] | Returns elapsed time since the previous frame. |
10//! | [`cotis_utils::traits::CotisRenderContext`] | Provided automatically via blanket impl when window and frame contexts are implemented. |
11//! | [`cotis_utils::text::RendererTextMeasuringProvider`] | Glyphon measurement with DPI-scaled font metrics. **`font_id` is ignored**; always uses `Family::SansSerif`. |
12//! | [`cotis_utils::interactivity::mouse::MouseProvider`] | Reads cursor position, button state, and scroll delta from [`crate::input::InputSnapshot`]. |
13//! | [`cotis_utils::interactivity::keyboard::SimpleKeyboardProvider`] | Reads pressed keys from [`crate::input::InputSnapshot`]. |
14//! | [`cotis_utils::interactivity::keyboard::SimpleTextProvider`] | Reads IME/preedit characters from [`crate::input::InputSnapshot`]. |
15
16use indexmap::IndexSet;
17
18use cotis_defaults::element_configs::text_config::TextConfig;
19use cotis_utils::interactivity::keyboard::{
20    KeyboardKey, SimpleKeyboardProvider, SimpleTextProvider,
21};
22use cotis_utils::interactivity::mouse::{MouseButton, MouseProvider};
23use cotis_utils::math::{Dimensions, Vector2};
24use cotis_utils::text::RendererTextMeasuringProvider;
25use cotis_utils::traits::{CotisFrameContext, CotisWindowContext};
26
27use crate::renderer::CotisWgpuRenderer;
28
29impl CotisWindowContext for CotisWgpuRenderer {
30    fn window_dimensions(&self) -> Dimensions {
31        self.window_dimensions()
32    }
33}
34
35impl CotisFrameContext for CotisWgpuRenderer {
36    fn get_delta_time(&self) -> f32 {
37        self.delta_time()
38    }
39}
40
41impl RendererTextMeasuringProvider<TextConfig> for CotisWgpuRenderer {
42    fn provide_measurer(&mut self) -> Box<dyn Fn(&str, &TextConfig) -> Dimensions> {
43        let font_system = self.text().font_system();
44        let dpi_scale = self.dpi_scale();
45        Box::new(move |text: &str, config: &TextConfig| {
46            let mut font_system = match font_system.lock() {
47                Ok(guard) => guard,
48                Err(error) => {
49                    log::error!("font system mutex poisoned: {error}");
50                    error.into_inner()
51                }
52            };
53            let font_size = config.font_size * dpi_scale;
54            let line_height = if config.line_height > 0.0 {
55                config.line_height * dpi_scale
56            } else {
57                font_size * 1.5
58            };
59
60            use glyphon::{Attrs, Buffer, Family, Metrics, Shaping};
61            let mut buffer = Buffer::new(&mut font_system, Metrics::new(font_size, line_height));
62            buffer.set_text(
63                &mut font_system,
64                text,
65                Attrs::new().family(Family::SansSerif),
66                Shaping::Advanced,
67            );
68            buffer.shape_until_scroll(&mut font_system, false);
69            let line_width = buffer
70                .layout_runs()
71                .next()
72                .map(|run| run.line_w)
73                .unwrap_or(0.0);
74            Dimensions::new(line_width, buffer.metrics().line_height)
75        })
76    }
77}
78
79impl MouseProvider for CotisWgpuRenderer {
80    fn get_mouse_position(&self) -> Vector2 {
81        self.input().mouse_position
82    }
83
84    fn mouse_button_down(&self, button: MouseButton) -> bool {
85        self.input().mouse_buttons.contains(&button)
86    }
87
88    fn get_mouse_wheel_move_v(&self) -> Vector2 {
89        self.input().scroll_delta
90    }
91}
92
93impl SimpleKeyboardProvider for CotisWgpuRenderer {
94    fn get_pressed_keys(&self) -> IndexSet<KeyboardKey> {
95        self.input().pressed_keys.clone()
96    }
97}
98
99impl SimpleTextProvider for CotisWgpuRenderer {
100    fn get_pressed_chars(&self) -> Vec<char> {
101        self.input().pressed_chars.clone()
102    }
103}