1extern crate image;
6extern crate keyframe;
7
8use cgmath::{Deg, Matrix4, SquareMatrix, Vector3};
9use image::DynamicImage;
10use std::path::Path;
11
12use stretch::{
13 node::{Node, Stretch},
14 style::*,
15};
16
17use crate::animation::Animation;
18use crate::font::FontRenderer;
19
20#[repr(i32)]
21#[derive(Copy, Clone, Debug, PartialEq)]
22pub enum Key {
23 Space = 32,
24 Enter = 36,
25 Tab = 48,
26 Backspace = 51,
27 Escape = 53,
28 Right = 262,
29 Left = 263,
30 Down = 264,
31 Up = 265,
32}
33
34#[derive(Copy, Clone, Debug)]
35pub enum LayoutMode {
36 UserDefine,
37 Flex,
38}
39
40#[repr(C)]
41#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
42pub struct Vertex {
43 pub position: [f32; 3],
44 pub tex_coords: [f32; 2],
45}
46
47impl Vertex {
48 pub fn desc() -> wgpu::VertexBufferLayout<'static> {
49 wgpu::VertexBufferLayout {
50 array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
51 step_mode: wgpu::VertexStepMode::Vertex,
52 attributes: &[
53 wgpu::VertexAttribute {
54 offset: 0,
55 shader_location: 0,
56 format: wgpu::VertexFormat::Float32x3,
57 },
58 wgpu::VertexAttribute {
59 offset: std::mem::size_of::<[f32; 3]>() as wgpu::BufferAddress,
60 shader_location: 1,
61 format: wgpu::VertexFormat::Float32x2,
62 },
63 ],
64 }
65 }
66}
67
68pub struct Layer {
69 pub name: String,
70 pub x: i32,
71 pub y: i32,
72 pub z: f32,
73 pub width: u32,
74 pub height: u32,
75 pub anchor_x: f32,
76 pub anchor_y: f32,
77 pub scale_x: f32,
78 pub scale_y: f32,
79 pub rotation: i32,
80 pub visible: bool,
81 color: [f32; 3],
82 pub opacity: f32, pub image_path: String,
84 pub sub_layer_list: Vec<Layer>,
85 pub(crate) vertex_buffer: Option<wgpu::Buffer>,
86 pub(crate) index_buffer: Option<wgpu::Buffer>,
87 pub(crate) texture: Option<wgpu::Texture>,
88 pub(crate) texture_view: Option<wgpu::TextureView>,
89 pub(crate) bind_group: Option<wgpu::BindGroup>,
90 pub animated: bool,
91 pub animation: Option<Animation>,
92 animations: std::collections::HashMap<String, Animation>, event_handler: Option<Box<dyn EventHandler>>,
94 layout: Option<Box<dyn Layout>>,
95 pub(crate) focused_sub_layer: usize,
96 pub(crate) focused: bool,
97 pub needs_update: bool,
98 pub node: Option<Node>, pub style: Option<Style>, }
101
102pub trait EventHandler {
103 fn key_focus_in(&mut self, layer: &mut Layer);
104 fn key_focus_out(&mut self, layer: &mut Layer);
105 fn key_down(&mut self, key: Key, layer: &mut Layer);
106}
107
108pub trait Layout {
109 fn layout_sub_layers(
110 &mut self,
111 layer: &mut Layer,
112 parent_layer: Option<&Layer>,
113 stretch: &mut Option<Stretch>,
114 );
115 fn update_layout(&mut self, layer: &mut Layer, stretch: &mut Option<Stretch>);
116 fn finalize(&mut self);
117}
118
119impl Layer {
120 pub fn new(name: String, w: u32, h: u32, event_handler: Option<Box<dyn EventHandler>>) -> Self {
121 let layer = Layer {
122 name: name,
123 x: 0,
124 y: 0,
125 z: 0.0,
126 width: w,
127 height: h,
128 anchor_x: 0.5,
129 anchor_y: 0.5,
130 scale_x: 1.0,
131 scale_y: 1.0,
132 rotation: 0,
133 visible: true,
134 color: [1.0, 1.0, 1.0],
135 opacity: 1.0,
136 image_path: "".to_string(),
137 sub_layer_list: Vec::new(),
138 vertex_buffer: None,
139 index_buffer: None,
140 texture: None,
141 texture_view: None,
142 bind_group: None,
143 animated: false,
144 animation: None,
145 animations: std::collections::HashMap::new(),
146 event_handler: event_handler,
147 layout: None,
148 focused_sub_layer: 0,
149 focused: false,
150 needs_update: true,
151 node: None,
152 style: None,
153 };
154
155 layer
156 }
157
158 #[allow(unused_variables)]
159 pub fn init_buffers(&mut self, device: &wgpu::Device) {
160 #[cfg(test)]
162 {
163 return;
164 }
165
166 #[cfg(not(test))]
167 {
168 let vertices = [
169 Vertex {
170 position: [self.width as f32, self.height as f32, 0.0],
171 tex_coords: [1.0, 1.0],
172 }, Vertex {
174 position: [self.width as f32, 0.0, 0.0],
175 tex_coords: [1.0, 0.0],
176 }, Vertex {
178 position: [0.0, 0.0, 0.0],
179 tex_coords: [0.0, 0.0],
180 }, Vertex {
182 position: [0.0, self.height as f32, 0.0],
183 tex_coords: [0.0, 1.0],
184 }, ];
186
187 let indices: [u16; 6] = [0, 1, 3, 1, 2, 3];
188
189 use wgpu::util::DeviceExt;
190 self.vertex_buffer = Some(
191 device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
192 label: Some("Vertex Buffer"),
193 contents: bytemuck::cast_slice(&vertices),
194 usage: wgpu::BufferUsages::VERTEX,
195 }),
196 );
197
198 self.index_buffer = Some(
199 device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
200 label: Some("Index Buffer"),
201 contents: bytemuck::cast_slice(&indices),
202 usage: wgpu::BufferUsages::INDEX,
203 }),
204 );
205 }
206 }
207
208 pub fn set_color(&mut self, r: f32, g: f32, b: f32) {
209 self.color[0] = r;
210 self.color[1] = g;
211 self.color[2] = b;
212 }
213
214 pub fn set_text(&mut self, text: &str, device: &wgpu::Device, queue: &wgpu::Queue) {
215 let mut font_renderer: FontRenderer = FontRenderer::new("fonts/DejaVuSans.ttf".to_string());
216 let image = font_renderer.render(text);
217 let dynamic_image = DynamicImage::ImageRgba8(image);
218
219 dynamic_image.save("temp.png").unwrap();
220
221 self.image_path = "temp".to_string();
222 self.width = dynamic_image.width();
223 self.height = dynamic_image.height();
224
225 println!("width: {}, height: {}", self.width, self.height);
226
227 let rgba = dynamic_image.to_rgba8();
228 let dimensions = rgba.dimensions();
229
230 let texture_size = wgpu::Extent3d {
231 width: dimensions.0,
232 height: dimensions.1,
233 depth_or_array_layers: 1,
234 };
235
236 let texture = device.create_texture(&wgpu::TextureDescriptor {
237 label: Some("Text Texture"),
238 size: texture_size,
239 mip_level_count: 1,
240 sample_count: 1,
241 dimension: wgpu::TextureDimension::D2,
242 format: wgpu::TextureFormat::Rgba8UnormSrgb,
243 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
244 view_formats: &[],
245 });
246
247 queue.write_texture(
248 wgpu::ImageCopyTexture {
249 texture: &texture,
250 mip_level: 0,
251 origin: wgpu::Origin3d::ZERO,
252 aspect: wgpu::TextureAspect::All,
253 },
254 &rgba,
255 wgpu::ImageDataLayout {
256 offset: 0,
257 bytes_per_row: Some(4 * dimensions.0),
258 rows_per_image: Some(dimensions.1),
259 },
260 texture_size,
261 );
262
263 let texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default());
264 self.texture = Some(texture);
265 self.texture_view = Some(texture_view);
266 }
267
268 pub fn set_image(&mut self, path: String) {
270 self.image_path = path;
271 }
272
273 pub fn load_image_texture(&mut self, device: &wgpu::Device, queue: &wgpu::Queue) {
275 if !self.image_path.is_empty() {
276 let img_result = image::ImageReader::open(&Path::new(&self.image_path))
278 .and_then(|reader| reader.with_guessed_format())
279 .map_err(image::ImageError::IoError)
280 .and_then(|reader| reader.decode());
281
282 match img_result {
283 Ok(img) => {
284 let rgba = img.to_rgba8();
285 let dimensions = rgba.dimensions();
286
287 let texture_size = wgpu::Extent3d {
288 width: dimensions.0,
289 height: dimensions.1,
290 depth_or_array_layers: 1,
291 };
292
293 let texture = device.create_texture(&wgpu::TextureDescriptor {
294 label: Some("Image Texture"),
295 size: texture_size,
296 mip_level_count: 1,
297 sample_count: 1,
298 dimension: wgpu::TextureDimension::D2,
299 format: wgpu::TextureFormat::Rgba8UnormSrgb,
300 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
301 view_formats: &[],
302 });
303
304 queue.write_texture(
305 wgpu::ImageCopyTexture {
306 texture: &texture,
307 mip_level: 0,
308 origin: wgpu::Origin3d::ZERO,
309 aspect: wgpu::TextureAspect::All,
310 },
311 &rgba,
312 wgpu::ImageDataLayout {
313 offset: 0,
314 bytes_per_row: Some(4 * dimensions.0),
315 rows_per_image: Some(dimensions.1),
316 },
317 texture_size,
318 );
319
320 let texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default());
321 self.texture = Some(texture);
322 self.texture_view = Some(texture_view);
323 }
324 Err(err) => println!("Fail to load a image {:?}", err),
325 }
326 }
327 }
328
329 pub fn set_layout(&mut self, layout: Option<Box<dyn Layout>>) {
330 self.layout = layout;
331 }
332
333 pub fn set_animation(&mut self, animation: Option<Animation>) {
334 self.animation = animation;
335 }
336
337 pub fn set_style(&mut self, style: Style) {
338 self.style = Some(style);
339 }
340
341 pub fn set_visible(&mut self, visible: bool) {
342 self.visible = visible;
343 }
344
345 pub fn animate(&mut self) {
351 if let Some(mut animation) = self.animation.take() {
353 animation.run(self);
354 self.animation = Some(animation);
355 }
356
357 let mut animations = std::mem::take(&mut self.animations);
360 for (_key, animation) in animations.iter_mut() {
361 animation.run(self);
362 }
363 self.animations = animations;
365
366 for sub_layer in self.sub_layer_list.iter_mut() {
367 sub_layer.animate();
368 }
369 }
370
371 pub fn select_next_sub_layer(&mut self) {
372 if self.sub_layer_list.is_empty() {
373 return;
374 }
375 if self.focused_sub_layer < self.sub_layer_list.len() - 1 {
377 let prev_focused_sub_layer = self.focused_sub_layer;
378 self.focused_sub_layer += 1;
379 self.sub_layer_list[self.focused_sub_layer].set_focus(true);
380 self.sub_layer_list[prev_focused_sub_layer].set_focus(false);
381 }
382 }
383
384 pub fn select_prev_sub_layer(&mut self) {
385 if self.sub_layer_list.is_empty() {
386 return;
387 }
388 if self.focused_sub_layer == 0 {
390 return;
391 }
392 let prev_focused_sub_layer = self.focused_sub_layer;
393 self.focused_sub_layer -= 1;
394 self.sub_layer_list[self.focused_sub_layer].set_focus(true);
395 self.sub_layer_list[prev_focused_sub_layer].set_focus(false);
396 }
397
398 pub fn set_focus(&mut self, focused: bool) {
399 self.focused = focused;
400 if let Some(mut event_handler) = self.event_handler.take() {
401 if self.focused {
404 event_handler.key_focus_in(self);
405 } else {
406 event_handler.key_focus_out(self);
407 }
408 self.event_handler = Some(event_handler);
409 }
410 }
411
412 pub fn handle_input(&mut self, key: Key) {
413 for sub_layer in self.sub_layer_list.iter_mut() {
414 if sub_layer.focused {
415 sub_layer.handle_input(key);
416 }
417 }
418 if let Some(mut event_handler) = self.event_handler.take() {
419 event_handler.key_down(key, self);
420 self.event_handler = Some(event_handler);
421 }
422 }
423
424 pub fn layout_sub_layers(
425 &mut self,
426 parent_layer: Option<&Layer>,
427 stretch: &mut Option<Stretch>,
428 ) {
429 if let Some(mut layout) = self.layout.take() {
430 layout.layout_sub_layers(self, parent_layer, stretch);
431 self.layout = Some(layout); }
433
434 let mut sub_layer_list = std::mem::replace(&mut self.sub_layer_list, Vec::new());
436
437 for sub_layer in &mut sub_layer_list {
439 sub_layer.layout_sub_layers(Some(self), stretch);
441 }
442
443 self.sub_layer_list = sub_layer_list;
445 }
446
447 pub fn update_layout(&mut self, stretch: &mut Option<Stretch>) {
448 if let Some(mut layout) = self.layout.take() {
449 layout.update_layout(self, stretch);
450 self.layout = Some(layout); }
452
453 for sub_layer in self.sub_layer_list.iter_mut() {
454 sub_layer.update_layout(stretch);
455 }
456 }
457
458 pub fn finalize_layout(&mut self) {
459 if let Some(ref mut layout) = self.layout {
460 layout.finalize();
461 }
462 }
463
464 pub fn model_matrix(&self) -> Matrix4<f32> {
465 let mut transform: Matrix4<f32> = Matrix4::identity();
466 transform = transform
467 * Matrix4::<f32>::from_translation(Vector3::new(self.x as f32, self.y as f32, self.z as f32));
468
469 transform = transform
472 * Matrix4::<f32>::from_translation(Vector3::new(
473 self.width as f32 * self.anchor_x,
474 self.height as f32 * self.anchor_y,
475 0.0,
476 ));
477
478 if self.rotation != 0 {
479 transform = transform * Matrix4::<f32>::from_angle_z(Deg(self.rotation as f32));
480 }
481
482 transform = transform * Matrix4::from_nonuniform_scale(self.scale_x, self.scale_y, 0.0);
483
484 transform = transform
486 * Matrix4::<f32>::from_translation(Vector3::new(
487 -(self.width as f32 * self.anchor_x),
488 -(self.height as f32 * self.anchor_y),
489 0.0,
490 ));
491
492 transform
493 }
494
495 pub fn render(&mut self, parent_model_matrix: Option<&Matrix4<f32>>, projection: &Matrix4<f32>) {
496 if !self.visible {
497 return;
498 }
499
500 let mut transform: Matrix4<f32> = self.model_matrix();
501 if let Some(parent_model_matrix) = parent_model_matrix {
502 transform = transform * parent_model_matrix;
503 }
504
505 for sub_layer in self.sub_layer_list.iter_mut() {
509 if sub_layer.focused == false {
510 sub_layer.render(Some(&transform), projection);
511 }
512 }
513
514 if !self.sub_layer_list.is_empty() {
516 self.sub_layer_list[self.focused_sub_layer].render(Some(&transform), projection);
517 }
518 }
519
520 pub fn add_sub_layer(&mut self, layer: Layer) {
521 self.sub_layer_list.push(layer);
522 }
523
524 pub fn set_position(&mut self, x: i32, y: i32) {
528 self.x = x;
529 self.y = y;
530 }
531
532 pub fn position(&self) -> (i32, i32) {
534 (self.x, self.y)
535 }
536
537 pub fn set_bounds(&mut self, width: u32, height: u32) {
539 self.width = width;
540 self.height = height;
541 }
542
543 pub fn bounds(&self) -> (u32, u32) {
545 (self.width, self.height)
546 }
547
548 pub fn set_opacity(&mut self, opacity: f32) {
550 self.opacity = opacity.max(0.0).min(1.0);
551 }
552
553 pub fn set_background_color(&mut self, r: f32, g: f32, b: f32) {
555 self.set_color(r, g, b);
556 }
557
558 pub fn background_color(&self) -> (f32, f32, f32) {
560 (self.color[0], self.color[1], self.color[2])
561 }
562
563 pub fn add_animation(&mut self, animation: Animation, key: Option<&str>) {
565 if let Some(key_str) = key {
566 self.animations.insert(key_str.to_string(), animation);
567 } else {
568 self.animation = Some(animation);
570 }
571 }
572
573 pub fn remove_all_animations(&mut self) {
575 self.animations.clear();
576 self.animation = None;
577 }
578
579 pub fn remove_animation(&mut self, key: &str) {
581 self.animations.remove(key);
582 }
583
584 pub fn add_sublayer(&mut self, layer: Layer) {
586 self.add_sub_layer(layer);
587 }
588
589 pub fn sublayers(&self) -> &Vec<Layer> {
591 &self.sub_layer_list
592 }
593
594 pub fn sublayers_mut(&mut self) -> &mut Vec<Layer> {
596 &mut self.sub_layer_list
597 }
598
599 pub fn create_uniform_buffer(
601 &self,
602 device: &wgpu::Device,
603 transform: &Matrix4<f32>,
604 projection: &Matrix4<f32>,
605 ) -> wgpu::Buffer {
606 use wgpu::util::DeviceExt;
607
608 #[repr(C)]
609 #[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
610 struct Uniforms {
611 transform: [[f32; 4]; 4],
612 projection: [[f32; 4]; 4],
613 color: [f32; 4],
614 use_texture: u32,
615 _padding: [u32; 3],
616 }
617
618 let use_texture = if self.texture.is_some() { 1 } else { 0 };
619
620 let uniforms = Uniforms {
621 transform: (*transform).into(),
622 projection: (*projection).into(),
623 color: [self.color[0], self.color[1], self.color[2], self.opacity],
624 use_texture,
625 _padding: [0; 3],
626 };
627
628 device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
629 label: Some("Uniform Buffer"),
630 contents: bytemuck::cast_slice(&[uniforms]),
631 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
632 })
633 }
634
635 pub fn get_or_create_bind_group(
637 &mut self,
638 device: &wgpu::Device,
639 layout: &wgpu::BindGroupLayout,
640 sampler: &wgpu::Sampler,
641 default_texture_view: &wgpu::TextureView,
642 ) -> &wgpu::BindGroup {
643 if self.bind_group.is_none() {
644 let texture_view = self.texture_view.as_ref().unwrap_or(default_texture_view);
645
646 self.bind_group = Some(device.create_bind_group(&wgpu::BindGroupDescriptor {
647 label: Some("Texture Bind Group"),
648 layout,
649 entries: &[
650 wgpu::BindGroupEntry {
651 binding: 0,
652 resource: wgpu::BindingResource::TextureView(texture_view),
653 },
654 wgpu::BindGroupEntry {
655 binding: 1,
656 resource: wgpu::BindingResource::Sampler(sampler),
657 },
658 ],
659 }));
660 }
661
662 self.bind_group.as_ref().unwrap()
663 }
664}
665
666#[cfg(test)]
667mod tests {
668 use super::*;
669 use crate::animation::{Animation, EasingFunction};
670
671 #[test]
672 fn test_position_api() {
673 let mut layer = Layer::new("test".to_string(), 100, 100, None);
674 layer.set_position(50, 75);
675 let (x, y) = layer.position();
676 assert_eq!(x, 50);
677 assert_eq!(y, 75);
678 }
679
680 #[test]
681 fn test_bounds_api() {
682 let mut layer = Layer::new("test".to_string(), 100, 100, None);
683 layer.set_bounds(200, 150);
684 let (w, h) = layer.bounds();
685 assert_eq!(w, 200);
686 assert_eq!(h, 150);
687 }
688
689 #[test]
690 fn test_opacity_api() {
691 let mut layer = Layer::new("test".to_string(), 100, 100, None);
692 assert_eq!(layer.opacity, 1.0);
693
694 layer.set_opacity(0.5);
695 assert_eq!(layer.opacity, 0.5);
696
697 layer.set_opacity(1.5);
699 assert_eq!(layer.opacity, 1.0);
700
701 layer.set_opacity(-0.5);
702 assert_eq!(layer.opacity, 0.0);
703 }
704
705 #[test]
706 fn test_background_color_api() {
707 let mut layer = Layer::new("test".to_string(), 100, 100, None);
708 layer.set_background_color(0.5, 0.6, 0.7);
709 let (r, g, b) = layer.background_color();
710 assert_eq!(r, 0.5);
711 assert_eq!(g, 0.6);
712 assert_eq!(b, 0.7);
713 }
714
715 #[test]
716 fn test_add_animation_with_key() {
717 let mut layer = Layer::new("test".to_string(), 100, 100, None);
718 let mut animation = Animation::with_key_path("position.x");
719 animation.duration = 2.0;
720 animation.timing_function = Some(EasingFunction::Linear);
721
722 layer.add_animation(animation, Some("moveX"));
723 assert_eq!(layer.animations.len(), 1);
724 assert!(layer.animations.contains_key("moveX"));
725 }
726
727 #[test]
728 fn test_remove_animation() {
729 let mut layer = Layer::new("test".to_string(), 100, 100, None);
730 let animation1 = Animation::with_key_path("position.x");
731 let animation2 = Animation::with_key_path("opacity");
732
733 layer.add_animation(animation1, Some("anim1"));
734 layer.add_animation(animation2, Some("anim2"));
735 assert_eq!(layer.animations.len(), 2);
736
737 layer.remove_animation("anim1");
738 assert_eq!(layer.animations.len(), 1);
739 assert!(!layer.animations.contains_key("anim1"));
740 assert!(layer.animations.contains_key("anim2"));
741 }
742
743 #[test]
744 fn test_remove_all_animations() {
745 let mut layer = Layer::new("test".to_string(), 100, 100, None);
746 let animation1 = Animation::with_key_path("position.x");
747 let animation2 = Animation::with_key_path("opacity");
748 let animation3 = Animation::new();
749
750 layer.add_animation(animation1, Some("anim1"));
751 layer.add_animation(animation2, Some("anim2"));
752 layer.set_animation(Some(animation3));
753
754 assert_eq!(layer.animations.len(), 2);
755 assert!(layer.animation.is_some());
756
757 layer.remove_all_animations();
758 assert_eq!(layer.animations.len(), 0);
759 assert!(layer.animation.is_none());
760 }
761
762 #[test]
763 fn test_sublayers_api() {
764 let mut parent = Layer::new("parent".to_string(), 200, 200, None);
765 let child1 = Layer::new("child1".to_string(), 50, 50, None);
766 let child2 = Layer::new("child2".to_string(), 50, 50, None);
767
768 parent.add_sublayer(child1);
769 parent.add_sublayer(child2);
770
771 let sublayers = parent.sublayers();
772 assert_eq!(sublayers.len(), 2);
773 assert_eq!(sublayers[0].name, "child1");
774 assert_eq!(sublayers[1].name, "child2");
775 }
776
777 #[test]
778 fn test_backward_compatibility() {
779 let mut layer = Layer::new("test".to_string(), 100, 100, None);
780
781 layer.x = 50;
783 layer.y = 75;
784 assert_eq!(layer.x, 50);
785 assert_eq!(layer.y, 75);
786
787 let mut animation = Animation::new();
789 animation.apply_translation_x(0, 100, 1.0, EasingFunction::Linear);
790 layer.set_animation(Some(animation));
791
792 assert!(layer.animation.is_some());
793 }
794}