1extern crate gl;
6extern crate image;
7extern crate keyframe;
8
9use self::gl::types::*;
10use cgmath::{Deg, Matrix, Matrix4, SquareMatrix, Vector3};
11use std::ffi::CStr;
12use std::mem;
13use std::os::raw::c_void;
14use std::path::Path;
15use std::ptr;
16
17use stretch::{
18 node::{Node, Stretch},
19 style::*,
20};
21
22use crate::animation::Animation;
23
24#[repr(i32)]
25#[derive(Copy, Clone, Debug, PartialEq)]
26pub enum Key {
27 Space = 32,
28 Enter = 36,
29 Tab = 48,
30 Backspace = 51,
31 Escape = 53,
32 Right = 262,
33 Left = 263,
34 Down = 264,
35 Up = 265,
36}
37
38#[derive(Copy, Clone, Debug)]
39pub enum LayoutMode {
40 UserDefine,
41 Flex,
42}
43
44macro_rules! c_str {
45 ($literal:expr) => {
46 CStr::from_bytes_with_nul_unchecked(concat!($literal, "\0").as_bytes())
47 };
48}
49
50pub struct Actor {
51 pub name: String,
52 pub x: i32,
53 pub y: i32,
54 pub z: f32,
55 pub width: u32,
56 pub height: u32,
57 pub anchor_x: f32,
58 pub anchor_y: f32,
59 pub scale_x: f32,
60 pub scale_y: f32,
61 pub rotation: i32,
62 pub visible: bool,
63 color: [f32; 3],
64 pub image_path: String,
65 pub sub_actor_list: Vec<Actor>,
66 vertex_array_obj: gl::types::GLuint,
67 texture: gl::types::GLuint,
68 pub animated: bool,
69 pub animation: Option<Animation>,
70 event_handler: Option<Box<dyn EventHandler>>,
71 layout: Option<Box<dyn Layout>>,
72 focused_sub_actor: usize,
73 focused: bool,
74 pub needs_update: bool,
75 pub node: Option<Node>, pub style: Option<Style>, }
78
79pub trait EventHandler {
80 fn key_focus_in(&mut self, actor: &mut Actor);
81 fn key_focus_out(&mut self, actor: &mut Actor);
82 fn key_down(&mut self, key: Key, actor: &mut Actor);
83}
84
85pub trait Layout {
86 fn layout_sub_actors(
87 &mut self,
88 actor: &mut Actor,
89 parent_actor: Option<&Actor>,
90 stretch: &mut Option<Stretch>,
91 );
92 fn update_layout(&mut self, actor: &mut Actor, stretch: &mut Option<Stretch>);
93 fn finalize(&mut self);
94}
95
96impl Actor {
97 pub fn new(name: String, w: u32, h: u32, event_handler: Option<Box<dyn EventHandler>>) -> Self {
98 let mut actor = Actor {
99 name: name,
100 x: 0,
101 y: 0,
102 z: 0.0,
103 width: w,
104 height: h,
105 anchor_x: 0.5,
106 anchor_y: 0.5,
107 scale_x: 1.0,
108 scale_y: 1.0,
109 rotation: 0,
110 visible: true,
111 color: [1.0, 1.0, 1.0],
112 image_path: "".to_string(),
113 sub_actor_list: Vec::new(),
114 vertex_array_obj: gl::types::GLuint::default(),
115 texture: gl::types::GLuint::default(),
116 animated: false,
117 animation: None,
118 event_handler: event_handler,
119 layout: None,
120 focused_sub_actor: 0,
121 focused: false,
122 needs_update: true,
123 node: None,
124 style: None,
125 };
126 actor.init_gl();
127
128 actor
129 }
130
131 pub fn init_gl(&mut self) {
132 unsafe {
133 let (mut vertex_array_buffer, mut elem_array_buffer) = (0, 0);
134 let vertices: [f32; 20] = [
135 self.width as f32,
137 self.height as f32,
138 0.0,
139 1.0,
140 1.0, self.width as f32,
142 0.0,
143 0.0,
144 1.0,
145 0.0, 0.0,
147 0.0,
148 0.0,
149 0.0,
150 0.0, 0.0,
152 self.height as f32,
153 0.0,
154 0.0,
155 1.0, ];
157 let indices = [
158 0, 1, 3, 1, 2, 3, ];
161
162 gl::GenVertexArrays(1, &mut self.vertex_array_obj);
163 gl::BindVertexArray(self.vertex_array_obj);
164
165 gl::GenBuffers(1, &mut vertex_array_buffer);
167 gl::BindBuffer(gl::ARRAY_BUFFER, vertex_array_buffer);
168 gl::BufferData(
169 gl::ARRAY_BUFFER,
170 (vertices.len() * mem::size_of::<GLfloat>()) as GLsizeiptr,
171 &vertices[0] as *const f32 as *const c_void,
172 gl::STATIC_DRAW,
173 );
174 gl::GenBuffers(1, &mut elem_array_buffer);
176 gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, elem_array_buffer);
177 gl::BufferData(
178 gl::ELEMENT_ARRAY_BUFFER,
179 (indices.len() * mem::size_of::<GLfloat>()) as GLsizeiptr,
180 &indices[0] as *const i32 as *const c_void,
181 gl::STATIC_DRAW,
182 );
183
184 let stride = 5 * mem::size_of::<GLfloat>() as GLsizei;
185 gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE, stride, ptr::null());
187 gl::EnableVertexAttribArray(0);
188 }
189 }
190
191 pub fn set_color(&mut self, r: f32, g: f32, b: f32) {
192 self.color[0] = r;
193 self.color[1] = g;
194 self.color[2] = b;
195 }
196
197 pub fn set_image(&mut self, path: String) {
198 self.image_path = path;
199
200 if self.image_path.len() > 0 {
201 let stride = 5 * mem::size_of::<GLfloat>() as GLsizei;
202 unsafe {
203 gl::VertexAttribPointer(
205 1,
206 2,
207 gl::FLOAT,
208 gl::FALSE,
209 stride,
210 (3 * mem::size_of::<GLfloat>()) as *const c_void,
211 );
212 gl::EnableVertexAttribArray(1);
213
214 gl::GenTextures(1, &mut self.texture);
216 gl::BindTexture(gl::TEXTURE_2D, self.texture);
217 gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::REPEAT as i32);
219 gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::REPEAT as i32);
220 gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as i32);
222 gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);
223
224 match image::open(&Path::new(&self.image_path)) {
225 Ok(img) => {
226 let to_rgba = img.to_rgba8();
227 let data = to_rgba.into_vec();
228 gl::TexImage2D(
229 gl::TEXTURE_2D,
230 0,
231 gl::RGB as i32,
232 img.width() as i32,
233 img.height() as i32,
234 0,
235 gl::RGBA,
236 gl::UNSIGNED_BYTE,
237 &data[0] as *const u8 as *const c_void,
238 );
239 gl::GenerateMipmap(gl::TEXTURE_2D);
240 }
241 Err(err) => println!("Fail to load a image {:?}", err),
242 }
243 }
244 }
245 }
246
247 pub fn set_layout(&mut self, layout: Option<Box<dyn Layout>>) {
248 self.layout = layout;
249 }
250
251 pub fn set_animation(&mut self, animation: Option<Animation>) {
252 self.animation = animation;
253 }
254
255 pub fn set_style(&mut self, style: Style) {
256 self.style = Some(style);
257 }
258
259 pub fn set_visible(&mut self, visible: bool) {
260 self.visible = visible;
261 }
262
263 pub fn animate(&mut self) {
269 if let Some(mut animation) = self.animation.take() {
270 animation.run(self);
271 self.animation = Some(animation);
272 }
273
274 for sub_actor in self.sub_actor_list.iter_mut() {
275 sub_actor.animate();
276 }
277 }
278
279 pub fn select_next_sub_actor(&mut self) {
280 if self.sub_actor_list.len() <= 0 {
281 return;
282 }
283 if self.focused_sub_actor < self.sub_actor_list.len() - 1 {
285 let prev_focused_sub_actor = self.focused_sub_actor;
286 self.focused_sub_actor += 1;
287 self.sub_actor_list[self.focused_sub_actor].set_focus(true);
288 self.sub_actor_list[prev_focused_sub_actor].set_focus(false);
289 }
290 }
291
292 pub fn select_prev_sub_actor(&mut self) {
293 if self.sub_actor_list.len() <= 0 {
294 return;
295 }
296 if self.focused_sub_actor == 0 {
298 return;
299 }
300 let prev_focused_sub_actor = self.focused_sub_actor;
301 self.focused_sub_actor -= 1;
302 self.sub_actor_list[self.focused_sub_actor].set_focus(true);
303 self.sub_actor_list[prev_focused_sub_actor].set_focus(false);
304 }
305
306 pub fn set_focus(&mut self, focused: bool) {
307 self.focused = focused;
308 if let Some(mut event_handler) = self.event_handler.take() {
309 if self.focused {
312 event_handler.key_focus_in(self);
313 } else {
314 event_handler.key_focus_out(self);
315 }
316 self.event_handler = Some(event_handler);
317 }
318 }
319
320 pub fn handle_input(&mut self, key: Key) {
321 for sub_actor in self.sub_actor_list.iter_mut() {
322 if sub_actor.focused {
323 sub_actor.handle_input(key);
324 }
325 }
326 if let Some(mut event_handler) = self.event_handler.take() {
327 event_handler.key_down(key, self);
328 self.event_handler = Some(event_handler);
329 }
330 }
331
332 pub fn layout_sub_actors(&mut self, parent_actor: Option<&Actor>, stretch: &mut Option<Stretch>) {
333 if let Some(mut layout) = self.layout.take() {
334 layout.layout_sub_actors(self, parent_actor, stretch);
335 self.layout = Some(layout); }
337
338 let mut sub_actor_list = std::mem::replace(&mut self.sub_actor_list, Vec::new());
340
341 for sub_actor in &mut sub_actor_list {
343 sub_actor.layout_sub_actors(Some(self), stretch);
345 }
346
347 self.sub_actor_list = sub_actor_list;
349 }
350
351 pub fn update_layout(&mut self, stretch: &mut Option<Stretch>) {
352 if let Some(mut layout) = self.layout.take() {
353 layout.update_layout(self, stretch);
354 self.layout = Some(layout); }
356
357 for sub_actor in self.sub_actor_list.iter_mut() {
358 sub_actor.update_layout(stretch);
359 }
360 }
361
362 pub fn finalize_layout(&mut self) {
363 if let Some(ref mut layout) = self.layout {
364 layout.finalize();
365 }
366 }
367
368 pub fn model_matrix(&self) -> Matrix4<f32> {
369 let mut transform: Matrix4<f32> = Matrix4::identity();
370 transform = transform
371 * Matrix4::<f32>::from_translation(Vector3::new(self.x as f32, self.y as f32, self.z as f32));
372
373 transform = transform
376 * Matrix4::<f32>::from_translation(Vector3::new(
377 self.width as f32 * self.anchor_x,
378 self.height as f32 * self.anchor_y,
379 0.0,
380 ));
381
382 if self.rotation != 0 {
383 transform = transform * Matrix4::<f32>::from_angle_z(Deg(self.rotation as f32));
384 }
385
386 transform = transform * Matrix4::from_nonuniform_scale(self.scale_x, self.scale_y, 0.0);
387
388 transform = transform
390 * Matrix4::<f32>::from_translation(Vector3::new(
391 -(self.width as f32 * self.anchor_x),
392 -(self.height as f32 * self.anchor_y),
393 0.0,
394 ));
395
396 transform
397 }
398
399 pub fn render(
400 &mut self,
401 shader_program: GLuint,
402 parent_model_matrix: Option<&Matrix4<f32>>,
403 projection: &Matrix4<f32>,
404 ) {
405 if !self.visible {
406 return;
407 }
408
409 let mut transform: Matrix4<f32> = self.model_matrix();
410 if let Some(parent_model_matrix) = parent_model_matrix {
411 transform = transform * parent_model_matrix;
412 }
413
414 unsafe {
415 gl::UseProgram(shader_program);
416 let loc_color = gl::GetUniformLocation(shader_program, c_str!("color").as_ptr());
417 let loc_transform = gl::GetUniformLocation(shader_program, c_str!("transform").as_ptr());
418 let loc_projection = gl::GetUniformLocation(shader_program, c_str!("projection").as_ptr());
419 let loc_use_texture = gl::GetUniformLocation(shader_program, c_str!("useTexture").as_ptr());
420
421 gl::Uniform4f(loc_color, self.color[0], self.color[1], self.color[2], 1.0);
422 gl::UniformMatrix4fv(loc_transform, 1, gl::FALSE, transform.as_ptr());
423 gl::UniformMatrix4fv(loc_projection, 1, gl::FALSE, projection.as_ptr());
424
425 if self.image_path.len() > 0 {
426 gl::BindTexture(gl::TEXTURE_2D, self.texture);
427 gl::Uniform1i(loc_use_texture, 1);
428 } else {
429 gl::Uniform1i(loc_use_texture, 0);
430 }
431
432 gl::BindVertexArray(self.vertex_array_obj);
433 gl::DrawElements(gl::TRIANGLES, 6, gl::UNSIGNED_INT, ptr::null());
434 }
435
436 for sub_actor in self.sub_actor_list.iter_mut() {
437 if sub_actor.focused == false {
438 sub_actor.render(shader_program, Some(&transform), projection);
439 }
440 }
441
442 if self.sub_actor_list.len() > 0 {
444 self.sub_actor_list[self.focused_sub_actor].render(
445 shader_program,
446 Some(&transform),
447 projection,
448 );
449 }
450 }
451
452 pub fn add_sub_actor(&mut self, actor: Actor) {
453 self.sub_actor_list.push(actor);
454 }
455}