fix display but still a coord bug
[lp74.git] / src / main.rs
bloba483f39ee232184334329af3bce9cece450f0e4d
1 //#![feature(slice_patterns)]
2 #[macro_use] extern crate conrod;
3 extern crate find_folder;
4 extern crate piston_window;
5 extern crate graphics;
6 extern crate rand;
7 extern crate input;
8 extern crate image;
9 extern crate gfx_device_gl;
11 use conrod::{Theme, Color, Button, Colorable, Labelable, Frameable,
12              Positionable, Sizeable, Graphics, Canvas, Widget, Tabs,
13              Circle, Text};
14 use conrod::color;
15 use conrod::events::input_provider::InputProvider;
16 use piston_window::{Glyphs, OpenGL, PistonWindow, WindowSettings, UpdateEvent,
17                     EventLoop, Window, Texture, Flip};
18 use input::keyboard::{Key};
20 mod data;
21 mod view;
23 use data::{Data, Space, Axis, Ori, Pos};
26 use std::io;
27 use std::process::{Command, Output, Stdio, ChildStdin, ChildStdout};
28 use image::{ImageFormat, load_from_memory_with_format};
29 use std::sync::Arc;
30 use graphics::Transformed;
31 use std::io::Write;
32 use std::io::Read;
33 use gfx_device_gl::Resources;
36 //type Backend = (
37 //    <piston_window::G2d<'static> as Graphics>::Texture,
38 //    Glyphs
39 //);
40 //type Ui = conrod::Ui<Backend>;
41 //type UiCell<'a> = conrod::UiCell<'a, Backend>;
42 type Backend = (
43     <piston_window::G2d<'static> as Graphics>::Texture,
44     Glyphs
46 type Ui = conrod::Ui<Backend>;
47 type UiCell<'a> = conrod::UiCell<'a, Backend>;
49 widget_ids! {
50     C_MASTER,
51     C_HEADER,
52     C_SIDE,
53     C_MAIN,
54     BTN1,
55     BTN2,
56     BTN3,
57     BTN_PREV,
58     BTN_NEXT,
59     CIRCLE1,
60     CIRCLE2,
61     C_ERR,
62     TXT_ERR,
63     BTN_OK_ERR,
64     BTN_CANCEL_ERR,
65     BTN_DESIGN,
66     BTN_VISUAL,
69 struct Colors {
70     c1: Color,
71     c2: Color,
72     font: Color,
73     main: Color,
74     hide: Color,
77 #[derive(Clone)]
78 struct ErrState {
79     msg: String,
82 #[derive(Clone)]
83 enum DesignState {
84     Std,
85     Add,
88 //#[derive(Clone)]
89 enum State {
90     Design(DesignState),
91     Visual(Option<Texture<gfx_device_gl::Resources>>),
92     Err(ErrState),
95 fn make_button<'a, F>(c: &Colors) -> Button<'a, F>
96     where F: FnOnce()
98     Button::new().w_h(110.0, 40.0).color(c.c1)
99         .label_color(c.font).frame_color(c.c2)
102 fn generate_faces_map(w: &mut PistonWindow,s: &Space) ->
103     Texture<gfx_device_gl::Resources>
105     println!("Generating graph... ");
106     let process = Command::new("dot")
107         .arg("-Tpng")
108         .stdin(Stdio::piped())
109         .stdout(Stdio::piped())
110         .spawn()
111         .unwrap_or_else(|e| panic!("system call failed: {}", e));
112     process.stdin.unwrap().write_all(s.dot_graph_code()
113                                      .as_bytes())
114         .unwrap_or_else(|e| panic!("piping failed: {}", e));
115     let mut png = Vec::new();
116     process.stdout.unwrap().read_to_end(&mut png)
117         .unwrap_or_else(|e| panic!("final read failed: {}"));
118     let rgba_img = load_from_memory_with_format(&png,
119                                                 ImageFormat::PNG)
120         .unwrap_or_else(|e| panic!("PNG image loading failed: {}", e))
121         .to_rgba();
122     //assert!(output.status.success());
123     let factory = &mut w.factory;
124     let settings = piston_window::TextureSettings::new();
125     println!("done");
126     Texture::from_image(factory, &rgba_img, &settings)
127              .unwrap()
130 fn main() {
131     let opengl = OpenGL::V3_2;
132     let mut window: PistonWindow = WindowSettings::new("LP74", [800, 500])
133         .opengl(opengl).exit_on_esc(true).build().unwrap();
135         let mut ui = {
136         let assets = find_folder::Search::KidsThenParents(3, 5)
137             .for_folder("assets").expect("Cannot find assets folder");
138         let font_path = assets.join("fonts/NotoSans/NotoSans-Regular.ttf");
139         let theme = Theme::default();
140         let glyph_cache = Glyphs::new(&font_path, window.factory.clone());
141         Ui::new(glyph_cache.unwrap(), theme)
142     };
144     window.set_ups(120);
145     window.set_max_fps(60);
147     let mut colors = Colors {
148         c1: color::rgb_bytes(57, 63, 63),
149         c2: color::rgb_bytes(30, 34, 34),
150         font: color::WHITE,
151         main: color::WHITE,
152         hide: color::rgba_bytes(57, 63, 63, 0.4),
153     };
155     let mut state = State::Design(DesignState::Std);
157     let mut data = Data::new();
159     while let Some(event) = window.next() {
160         handle_keys(&ui, &mut data);
161         ui.handle_event(&event);
162         event.update(|_| ui.set_widgets(|ref mut uicell|
163                                         set_ui(uicell,
164                                                &mut state,
165                                                &mut data,
166                                                &mut colors)));
167         let wsize = (window.size().width as f64,
168                      window.size().height as f64);
169         match state {
170             State::Visual(ref mut faces_map) => match *faces_map {
171                 None => {
172                     *faces_map = Some(generate_faces_map(&mut window, &data.space));
173                 },
174                 _ => {},
175             },
176             _ => {},
177         };
178         window.draw_2d(&event, |c, g| {
179             match &state {
180                 &State::Design(_) => {
181                     data.space.changed = true;
182                     if data.space.changed /*|| (ui.redraw_count() > 0)*/ {
183                         piston_window::clear([0.0, 0.0, 0.0, 0.0], g);
184                         draw_model(wsize, &data, c, g);
185                         //view::view_visual(&window, &data.space, c, g);
186                         ui.needs_redraw();
187                         data.space.changed = false;
188                     }
189                 },
190                 &State::Visual(ref faces_map) => {
191                     if let &Some(ref m) = faces_map {
192                         ui.needs_redraw();
193                         piston_window::clear([1.0, 1.0, 1.0, 1.0], g);
194                         graphics::image(m, c.transform.trans(150.0, 50.0), g);
195                     }
196                 },
197                 &State::Err(_) => {},
198             }
199             ui.draw_if_changed(c, g);
200         });
201     }
204 //fn design_mode<G: graphics::Graphics>(ui: &mut Ui) {
207 //fn visual_mode<G: graphics::Graphics>(ui: &mut Ui, d: &Data) {
210 fn draw_model<G: graphics::Graphics>(wsize: (f64, f64), d: &Data, c: graphics::Context, g: &mut G) {
211     use graphics::*;
212     //rectangle([rand::random(), rand::random(), rand::random(), 1.0], [0.0, 0.0, 200.0, 200.0], c.transform.trans(100.0, 100.0), g);
213     view::view_space(&d.space, wsize, c, g);
216 fn handle_keys(ui: &Ui, d: &mut Data) {
217     for k in ui.global_input.keys_just_pressed() {
218         println!("{:?}", k);
219         match d.space.current {
220             Pos::E((_, a)) => match a {
221                 Axis::X => match k {
222                     Key::Right => d.space.inc(),
223                     Key::Left => d.space.dec(),
224                     Key::R => d.space.rotate(),
225                     Key::S => d.space.switch_pos_type(),
226                     _ => {},
227                 },
228                 Axis::Y => match k {
229                     Key::Up => d.space.dec(),
230                     Key::Down => d.space.inc(),
231                     Key::R => d.space.rotate(),
232                     Key::S => d.space.switch_pos_type(),
233                     _ => {},
234                 },
235                 Axis::Z => match k {
236                     Key::Up => d.space.dec(),
237                     Key::Down => d.space.inc(),
238                     Key::R => d.space.rotate(),
239                     Key::S => d.space.switch_pos_type(),
240                     _ => {},
241                 },
242             },
243             Pos::F((_, o)) => match k {
244                     Key::R => d.space.rotate(),
245                     Key::S => d.space.switch_pos_type(),
246                     Key::A => d.space.set_current_face_if_none(),
247                     _ => match o {
248                         Ori::Floor => match k {
249                             Key::Up => d.space.dec(),
250                             Key::Down => d.space.inc(),
251                             _ => {},
252                         },
253                         Ori::Front => match k {
254                             Key::Up => d.space.dec(),
255                             Key::Down => d.space.inc(),
256                             _ => {},
257                         },
258                         Ori::Side => match k {
259                             Key::Left => d.space.dec(),
260                             Key::Right => d.space.inc(),
261                             _ => {},
262                     },
263                 },
264             },
265         };
266     }
269 fn set_ui(ui: &mut UiCell, s: &mut State, d: &mut Data, c: &mut Colors)
271     match s {
272         &mut State::Design(DesignState::Std) => {
273             base_ui(ui, s, d, c);
274             std_ui(ui, s, d, c);
275         },
276         &mut State::Design(DesignState::Add) => {
277             base_ui(ui, s, d, c);
278             add_ui(ui, s, d, c)
279         },
280         &mut State::Visual(_) => {
281             base_ui(ui, s, d, c);
282             visual_ui(ui, s, d, c);
283         },
284         &mut State::Err(_) => error_ui(ui, s, d, c),
285     }
288 fn error_ui(ui: &mut UiCell, gs: &mut State, d: &mut Data, c: &mut Colors)
290     {
291         let s = match *gs {
292             State::Err(ref mut s) => s,
293             _ => panic!("non Err state"),
294         };
295         Canvas::new()
296             .color(c.hide)
297             .set(C_MASTER, ui);
298         Canvas::new().middle_of(C_MASTER)
299             .color(c.c1).frame_color(c.c2)
300             .w_h(400.0, 120.0).pad(20.0)
301             .set(C_ERR, ui);
302         Text::new(&s.msg)
303             .color(c.font).mid_top_of(C_ERR)
304             .set(TXT_ERR, ui);
305         make_button(&c)
306             .label("Cancel").bottom_right_of(C_ERR)
307             .react(|| {
308                 println!("Cancel");
309                 s.msg = String::from("Cannot cancel");
310             })
311             .set(BTN_CANCEL_ERR, ui);
312     }
313     make_button(&c)
314         .label("OK").bottom_left_of(C_ERR)
315         .react(|| {
316             println!("OK");
317             *gs = State::Design(DesignState::Std);
318         })
319         .set(BTN_OK_ERR, ui);
322 fn get_win_dim(ui: &UiCell) -> (f64, f64) {
323     (ui.window_dim()[0], ui.window_dim()[1])
326 fn base_ui(ui: &mut UiCell, gs: &mut State, d: &mut Data, c: &mut Colors)
328     let (win_w, win_h) = get_win_dim(ui);
329     let header_h = 50.0;
330     let side_w = 150.0;
331     Canvas::new()
332         .color(c.c1).frame_color(c.c2)
333         .y((win_h/2.0)-(header_h/2.0)).h(header_h)
334         .pad_left(20.0)
335         .set(C_HEADER, ui);
336     Canvas::new().color(c.c1)
337         .color(c.c1).frame_color(c.c2)
338         .x_y(-((win_w/2.0)-(side_w/2.0)), -(header_h/2.0))
339         .w_h(side_w, win_h - header_h)
340         .pad(20.0)
341         .set(C_SIDE, ui);
342     //Canvas::new()
343     //    .color(c.main).frame_color(c.c2)
344     //    .x_y(side_w/2.0, -(header_h/2.0))
345     //    .w_h(win_w-side_w, win_h-header_h)
346     //    .set(C_MAIN, ui);
349 fn add_ui(ui: &mut UiCell, gs: &mut State, d: &mut Data, c: &mut Colors)
351     make_button(&c)
352         .mid_top_of(C_SIDE).label("Exit")
353         .react(|| {
354             println!("Add");
355             *gs = State::Design(DesignState::Std);
356         }).set(BTN1, ui);
359 fn visual_ui(ui: &mut UiCell, gs: &mut State, d: &mut Data, c: &mut Colors)
361     make_button(&c)
362         .mid_left_of(C_HEADER).label("Design")
363         .react(|| {
364             println!("Design");
365             *gs = State::Design(DesignState::Std);
366         }).set(BTN_DESIGN, ui);
368 fn std_ui(ui: &mut UiCell, gs: &mut State, d: &mut Data, c: &mut Colors)
370     //let s = match gs {
371     //    &mut State::Std => State::Std,
372     //    _ => panic!("non Std state"),
373     //};
374     Button::new()
375         .mid_left_of(C_HEADER).w_h(50.0, 30.0)
376         .color(c.c1).frame_color(c.c2)
377         .label_color(c.font)
378         .label("<").react(|| {
379             println!("prev")
380         })
381         .set(BTN_PREV, ui);
382     Button::new()
383         .mid_left_of(C_HEADER).right_from(BTN_PREV, 30.0).w_h(50.0, 30.0)
384         .color(c.c1).frame_color(c.c2)
385         .label_color(c.font)
386         .label(">").react(|| {
387             println!("next");
388         })
389         .set(BTN_NEXT, ui);
390     make_button(&c)
391         .mid_left_of(C_HEADER).right_from(BTN_NEXT, 60.0).label("Visual")
392         .react(|| {
393             println!("Visual");
394             *gs = State::Visual(None);
395         }).set(BTN_VISUAL, ui);
396     make_button(&c)
397         .mid_top_of(C_SIDE).label("Add")
398         .react(|| {
399             println!("Add");
400             *gs = State::Design(DesignState::Add);
401         }).set(BTN1, ui);
402     make_button(&c)
403         .mid_top_of(C_SIDE).down_from(BTN1, 20.0).label("Err")
404         .react(|| {
405             println!("Err");
406             *gs = State::Err(ErrState {
407                 msg: String::from("Error!")
408             });
409         }).set(BTN2, ui);
410     make_button(&c)
411         .mid_top_of(C_SIDE).down_from(BTN2, 20.0).label("þê¿ â€ŀï ¿»")
412         .react(|| {
413             println!("þê¿ â€ŀï ¿»");
414         }).set(BTN3, ui);
415     //Tabs::new(&[(T_OBJ, "Object"), (T_FACE, "Faces")])
416     //    .wh_of(C_MAIN).color(c.c1)
417     //    .label_color(c.font).frame_color(c.c2)
418     //    .middle_of(C_MAIN).set(TABS, ui);
419     //Canvas::new()
420     //    .color(c.main).frame_color(c.c2)
421     //    .middle_of(C_MAIN).wh_of(C_MAIN)
422     //    .pad(20.0).set(C_T_OBJ, ui);
423     //Canvas::new()
424     //    .color(c.c1).frame_color(c.c2)
425     //    .middle_of(T_FACE).wh_of(T_FACE)
426     //    .pad(20.0).set(C_T_FACE, ui);
427     //Circle::fill(100.0)
428     //    .middle_of(C_T_FACE).color(c.main)
429     //    .set(CIRCLE1, ui);
430     //Circle::outline(100.0)
431     //    .middle_of(C_T_FACE).color(c.c2)
432     //    .set(CIRCLE2, ui);