xref: /StarryEngine/starry_client/src/window.rs (revision 45e1715779ec63c9948d677df0dab834e236e747)
1bee61dcaSR0ronoa use std::{cell::Cell, fs::File, io::{Seek, SeekFrom, Write}};
2bee61dcaSR0ronoa 
3bee61dcaSR0ronoa use crate::base::{color::Color, renderer::{RenderMode, Renderer}};
4bee61dcaSR0ronoa 
5bee61dcaSR0ronoa // TODO: 读帧缓冲设备属性
6bee61dcaSR0ronoa /// 屏幕宽度
7bee61dcaSR0ronoa const SCREEN_WIDTH: usize = 1440;
8bee61dcaSR0ronoa /// 屏幕高度
9bee61dcaSR0ronoa #[allow(dead_code)]
10bee61dcaSR0ronoa const SCREEN_HEIGHT: usize = 900;
11bee61dcaSR0ronoa 
12*45e17157SR0ronoa /// 客户端的窗口类,与服务端的窗口对象一一对应
13*45e17157SR0ronoa /// 一般来说客户端应用程序不直接使用该类,而通过Toolkit库间接使用
14bee61dcaSR0ronoa #[allow(dead_code)]
15bee61dcaSR0ronoa pub struct Window {
16bee61dcaSR0ronoa     /// 窗口左上角的x坐标
17bee61dcaSR0ronoa     x: i32,
18bee61dcaSR0ronoa     /// 窗口左上角的y坐标
19bee61dcaSR0ronoa     y: i32,
20bee61dcaSR0ronoa     /// 窗口的宽度
21bee61dcaSR0ronoa     w: u32,
22bee61dcaSR0ronoa     /// 窗口的高度
23bee61dcaSR0ronoa     h: u32,
24bee61dcaSR0ronoa     /// 窗口的标题
25*45e17157SR0ronoa     title: String,
26bee61dcaSR0ronoa     /// TODO
27bee61dcaSR0ronoa     // window_async: bool,
28bee61dcaSR0ronoa     /// 窗口是否大小可变
29bee61dcaSR0ronoa     resizable: bool,
30bee61dcaSR0ronoa     /// 窗口的渲染模式
31bee61dcaSR0ronoa     mode: Cell<RenderMode>,
32bee61dcaSR0ronoa     // TODO
33bee61dcaSR0ronoa     // file_opt: Option<File>,
34bee61dcaSR0ronoa     // TODO: 改定长数组
35bee61dcaSR0ronoa     // data_opt: Option<& 'static mut [Color]>,
36bee61dcaSR0ronoa     /// 窗口的渲染数据
37bee61dcaSR0ronoa     data_opt: Option<Box<[Color]>>,
38bee61dcaSR0ronoa }
39bee61dcaSR0ronoa 
40bee61dcaSR0ronoa impl Renderer for Window {
41bee61dcaSR0ronoa     fn width(&self) -> u32 {
42bee61dcaSR0ronoa         self.w
43bee61dcaSR0ronoa     }
44bee61dcaSR0ronoa 
45bee61dcaSR0ronoa     fn height(&self) -> u32 {
46bee61dcaSR0ronoa         self.h
47bee61dcaSR0ronoa     }
48bee61dcaSR0ronoa 
49bee61dcaSR0ronoa     fn data(&self) -> &[Color] {
50bee61dcaSR0ronoa         self.data_opt.as_ref().unwrap()
51bee61dcaSR0ronoa     }
52bee61dcaSR0ronoa 
53bee61dcaSR0ronoa     fn data_mut(&mut self) -> &mut [Color]{
54bee61dcaSR0ronoa         self.data_opt.as_mut().unwrap()
55bee61dcaSR0ronoa     }
56bee61dcaSR0ronoa 
57bee61dcaSR0ronoa     fn sync(&mut self) -> bool {
58*45e17157SR0ronoa         let mut fb = File::open("/dev/fb0").expect("Unable to open framebuffer");
59*45e17157SR0ronoa 
60*45e17157SR0ronoa         for y in 0..self.height() as i32 {
61*45e17157SR0ronoa             for x in 0..self.width() as i32 {
62*45e17157SR0ronoa                 let pixel = self.get_pixel(x, y);
63*45e17157SR0ronoa                 let offset =  (((y + self.y()) * SCREEN_WIDTH as i32) + x + self.x()) * 4;
64*45e17157SR0ronoa                 // 写缓冲区
65*45e17157SR0ronoa                 fb.seek(SeekFrom::Start(offset as u64)).expect("Unable to seek framebuffer");
66*45e17157SR0ronoa                 fb.write_all(&pixel.to_bgra_bytes()).expect("Unable to write framebuffer");
67*45e17157SR0ronoa             }
68*45e17157SR0ronoa         }
69bee61dcaSR0ronoa         true
70bee61dcaSR0ronoa     }
71bee61dcaSR0ronoa 
72bee61dcaSR0ronoa     fn mode(&self) -> &Cell<RenderMode> {
73bee61dcaSR0ronoa         &self.mode
74bee61dcaSR0ronoa     }
75bee61dcaSR0ronoa }
76bee61dcaSR0ronoa 
77bee61dcaSR0ronoa #[allow(dead_code)]
78bee61dcaSR0ronoa impl Window {
79bee61dcaSR0ronoa     /// TODO: 接收flags
80bee61dcaSR0ronoa     pub fn new(x: i32, y: i32, w: u32, h: u32, title: &str) -> Self {
81bee61dcaSR0ronoa         Window {
82bee61dcaSR0ronoa             x: x,
83bee61dcaSR0ronoa             y: y,
84bee61dcaSR0ronoa             w: w,
85bee61dcaSR0ronoa             h: h,
86*45e17157SR0ronoa             title: title.to_string(),
87bee61dcaSR0ronoa             // window_async: false,
88bee61dcaSR0ronoa             resizable: false,
89bee61dcaSR0ronoa             mode: Cell::new(RenderMode::Blend),
90bee61dcaSR0ronoa             // file_opt: None,
91bee61dcaSR0ronoa             data_opt: Some(vec!(Color::rgb(0, 0, 0); (w * h) as usize).into_boxed_slice()),
92bee61dcaSR0ronoa         }
93bee61dcaSR0ronoa 
94bee61dcaSR0ronoa         // TODO: 与服务器通信
95bee61dcaSR0ronoa     }
96bee61dcaSR0ronoa 
97*45e17157SR0ronoa     /// 返回窗口x坐标
98bee61dcaSR0ronoa     pub fn x(&self) -> i32 {
99bee61dcaSR0ronoa         self.x
100bee61dcaSR0ronoa     }
101bee61dcaSR0ronoa 
102*45e17157SR0ronoa     /// 返回窗口y坐标
103bee61dcaSR0ronoa     pub fn y(&self) -> i32 {
104bee61dcaSR0ronoa         self.y
105bee61dcaSR0ronoa     }
106bee61dcaSR0ronoa 
107*45e17157SR0ronoa     /// 返回窗口标题
108bee61dcaSR0ronoa     pub fn title(&self) -> String {
109*45e17157SR0ronoa         self.title.clone()
110bee61dcaSR0ronoa     }
111bee61dcaSR0ronoa 
112*45e17157SR0ronoa     /// 改变窗口的位置
113*45e17157SR0ronoa     pub fn set_pos(&mut self, x: i32, y: i32) {
114*45e17157SR0ronoa         self.x = x;
115*45e17157SR0ronoa         self.y = y;
116*45e17157SR0ronoa     }
117bee61dcaSR0ronoa 
118*45e17157SR0ronoa     /// 改变窗口的大小
119*45e17157SR0ronoa     pub fn set_size(&mut self, width: u32, height: u32) {
120*45e17157SR0ronoa         self.w = width;
121*45e17157SR0ronoa         self.h = height;
122*45e17157SR0ronoa     }
123*45e17157SR0ronoa 
124*45e17157SR0ronoa     /// 改变窗口标题
125*45e17157SR0ronoa     pub fn set_title(&mut self, title: &str) {
126*45e17157SR0ronoa         self.title = title.to_string();
127*45e17157SR0ronoa     }
128bee61dcaSR0ronoa }