1extern crate gl;
6
7use self::gl::types::*;
8use cgmath::{Matrix4, SquareMatrix};
9use std::collections::HashMap;
10use std::ffi::CString;
11use std::ptr;
12use std::str;
13use stretch::{geometry::Size, node::Stretch};
14
15use crate::actor::Actor;
16use crate::actor::EventHandler;
17use crate::actor::Key;
18use crate::actor::LayoutMode;
19
20const VERTEX_SHADER_SOURCE: &str = r#"
21 #version 330 core
22 layout(location = 0) in vec4 a_position;
23 layout(location = 1) in vec2 a_texCoord;
24
25 uniform mat4 transform;
26 uniform mat4 projection;
27 out vec2 v_texCoord;
28
29 void main() {
30 gl_Position = projection * transform * a_position;
31 v_texCoord = a_texCoord;
32 }
33"#;
34
35const FRAGMENT_SHADER_SOURCE: &str = r#"
36 #version 330 core
37 out vec4 outColor;
38 uniform vec4 color;
39 uniform int useTexture; // Flag to determine whether to use the texture
40 in vec2 v_texCoord;
41 uniform sampler2D s_texture;
42
43 void main() {
44 if (useTexture > 0)
45 outColor = texture(s_texture, v_texCoord);
46 else
47 outColor = color;
48 }
49"#;
50
51pub fn render(name: String) {
52 println!("Render {}", name);
53}
54
55pub struct Play {
56 _name: String,
57 stage_list: Vec<Actor>,
59 shader_program: GLuint,
60 stage_map: HashMap<String, usize>,
61 projection: Matrix4<f32>,
62 pub stretch: Option<Stretch>,
63}
64
65impl Play {
66 pub fn new(
67 name: String,
68 viewport_width: i32,
69 viewport_height: i32,
70 layout_mode: LayoutMode,
71 ) -> Self {
72 let mut stretch = None;
73 match layout_mode {
74 LayoutMode::Flex => {
75 stretch = Some(Stretch::new());
76 }
77 LayoutMode::UserDefine => {
78 print!("UserDefine");
79 }
80 }
81
82 let mut play = Play {
83 _name: name,
84 stage_list: Vec::new(),
85 shader_program: 0,
86 stage_map: HashMap::new(),
87 projection: Matrix4::identity(),
88 stretch: stretch,
89 };
90
91 let orth_matrix = cgmath::ortho(
93 0.0,
94 viewport_width as f32,
95 viewport_height as f32,
96 0.0,
97 1.0,
98 -1.0,
99 );
100 play.projection = orth_matrix;
101 play.compile_shader();
103
104 play
105 }
106
107 pub fn new_actor(
108 name: String,
109 w: u32,
110 h: u32,
111 event_handler: Option<Box<dyn EventHandler>>,
112 ) -> Actor {
113 Actor::new(name, w, h, event_handler)
114 }
115
116 pub fn add_new_actor_to_stage(&mut self, stage_name: &String, actor: Actor) {
117 match self.stage_map.get(stage_name) {
118 Some(&index) => {
119 self.stage_list[index].add_sub_actor(actor);
120 }
121 _ => println!("Can't find the stage with the given name: {}", stage_name),
122 }
123 }
124
125 pub fn set_visible_stage(&mut self, name: &String, visible: bool) {
126 match self.stage_map.get(name) {
127 Some(&index) => {
128 self.stage_list[index].set_visible(visible);
129 self.stage_list[index].needs_update = true;
130 }
131 _ => println!("Can't find the stage with the given name: {}", name),
132 }
133 }
134
135 fn compile_shader(&mut self) {
137 unsafe {
138 let vertex_shader = gl::CreateShader(gl::VERTEX_SHADER);
141 let c_str_vert = CString::new(VERTEX_SHADER_SOURCE.as_bytes()).unwrap();
142 gl::ShaderSource(vertex_shader, 1, &c_str_vert.as_ptr(), ptr::null());
143 gl::CompileShader(vertex_shader);
144
145 let mut success = gl::FALSE as GLint;
147 let mut info_log = Vec::with_capacity(512);
148 info_log.set_len(512 - 1); gl::GetShaderiv(vertex_shader, gl::COMPILE_STATUS, &mut success);
150 if success != gl::TRUE as GLint {
151 gl::GetShaderInfoLog(
152 vertex_shader,
153 512,
154 ptr::null_mut(),
155 info_log.as_mut_ptr() as *mut GLchar,
156 );
157 let s = str::from_utf8(&info_log);
159 match s {
160 Err(_) => {
161 println!("Failed to decode using");
162 }
163 Ok(s) => {
164 println!("Decoded with to '{}'", s);
165 }
166 }
167 }
168
169 let fragment_shader = gl::CreateShader(gl::FRAGMENT_SHADER);
171 let c_str_frag = CString::new(FRAGMENT_SHADER_SOURCE.as_bytes()).unwrap();
172 gl::ShaderSource(fragment_shader, 1, &c_str_frag.as_ptr(), ptr::null());
173 gl::CompileShader(fragment_shader);
174 gl::GetShaderiv(fragment_shader, gl::COMPILE_STATUS, &mut success);
176 if success != gl::TRUE as GLint {
177 gl::GetShaderInfoLog(
178 fragment_shader,
179 512,
180 ptr::null_mut(),
181 info_log.as_mut_ptr() as *mut GLchar,
182 );
183 println!(
184 "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n{}",
185 str::from_utf8(&info_log).unwrap()
186 );
187 }
188
189 self.shader_program = gl::CreateProgram();
191 gl::AttachShader(self.shader_program, vertex_shader);
192 gl::AttachShader(self.shader_program, fragment_shader);
193 gl::LinkProgram(self.shader_program);
194 gl::GetProgramiv(self.shader_program, gl::LINK_STATUS, &mut success);
196 if success != gl::TRUE as GLint {
197 gl::GetProgramInfoLog(
198 self.shader_program,
199 512,
200 ptr::null_mut(),
201 info_log.as_mut_ptr() as *mut GLchar,
202 );
203 println!(
204 "ERROR::SHADER::PROGRAM::COMPILATION_FAILED\n{}",
205 str::from_utf8(&info_log).unwrap()
206 );
207 }
208 gl::DeleteShader(vertex_shader);
209 gl::DeleteShader(fragment_shader);
210 }
211 }
212
213 pub fn add_stage(&mut self, stage: Actor) -> String {
214 let stage_name = stage.name.to_string();
215 self.stage_list.push(stage);
216 self
217 .stage_map
218 .insert(stage_name.to_string(), self.stage_list.len() - 1);
219
220 stage_name
221 }
222
223 pub fn handle_input(&mut self, key: Key) {
224 for stage in self.stage_list.iter_mut() {
226 stage.handle_input(key);
227 }
228 }
229
230 pub fn render(&mut self) {
231 unsafe {
232 gl::ClearColor(0.2, 0.3, 0.3, 1.0);
233 gl::Clear(gl::COLOR_BUFFER_BIT);
234
235 for stage in self.stage_list.iter_mut() {
236 if stage.needs_update {
237 stage.layout_sub_actors(None, &mut self.stretch);
238
239 if let Some(stretch_obj) = &mut self.stretch {
240 stretch_obj
241 .compute_layout(stage.node.unwrap(), Size::undefined())
242 .unwrap();
243
244 }
247
248 stage.update_layout(&mut self.stretch);
249 stage.needs_update = false;
250 }
251
252 stage.animate();
253 stage.render(self.shader_program, None, &self.projection);
254 }
255 }
256 }
257}