1 //#![feature(slice_patterns)]
2 #[macro_use] extern crate conrod;
3 extern crate find_folder;
4 extern crate piston_window;
9 extern crate gfx_device_gl;
11 use conrod::{Theme, Color, Button, Colorable, Labelable, Frameable,
12 Positionable, Sizeable, Graphics, Canvas, Widget, Tabs,
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};
23 use data::{Data, Space, Axis, Ori, Pos};
27 use std::process::{Command, Output, Stdio, ChildStdin, ChildStdout};
28 use image::{ImageFormat, load_from_memory_with_format};
30 use graphics::Transformed;
33 use gfx_device_gl::Resources;
37 // <piston_window::G2d<'static> as Graphics>::Texture,
40 //type Ui = conrod::Ui<Backend>;
41 //type UiCell<'a> = conrod::UiCell<'a, Backend>;
43 <piston_window::G2d<'static> as Graphics>::Texture,
46 type Ui = conrod::Ui<Backend>;
47 type UiCell<'a> = conrod::UiCell<'a, Backend>;
91 Visual(Option<Texture<gfx_device_gl::Resources>>),
95 fn make_button<'a, F>(c: &Colors) -> Button<'a, F>
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")
108 .stdin(Stdio::piped())
109 .stdout(Stdio::piped())
111 .unwrap_or_else(|e| panic!("system call failed: {}", e));
112 process.stdin.unwrap().write_all(s.dot_graph_code()
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,
120 .unwrap_or_else(|e| panic!("PNG image loading failed: {}", e))
122 //assert!(output.status.success());
123 let factory = &mut w.factory;
124 let settings = piston_window::TextureSettings::new();
126 Texture::from_image(factory, &rgba_img, &settings)
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();
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)
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),
152 hide: color::rgba_bytes(57, 63, 63, 0.4),
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|
167 let wsize = (window.size().width as f64,
168 window.size().height as f64);
170 State::Visual(ref mut faces_map) => match *faces_map {
172 *faces_map = Some(generate_faces_map(&mut window, &data.space));
178 window.draw_2d(&event, |c, g| {
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);
187 data.space.changed = false;
190 &State::Visual(ref faces_map) => {
191 if let &Some(ref m) = faces_map {
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);
197 &State::Err(_) => {},
199 ui.draw_if_changed(c, g);
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) {
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() {
219 match d.space.current {
220 Pos::E((_, a)) => match a {
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(),
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(),
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(),
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(),
248 Ori::Floor => match k {
249 Key::Up => d.space.dec(),
250 Key::Down => d.space.inc(),
253 Ori::Front => match k {
254 Key::Up => d.space.dec(),
255 Key::Down => d.space.inc(),
258 Ori::Side => match k {
259 Key::Left => d.space.dec(),
260 Key::Right => d.space.inc(),
269 fn set_ui(ui: &mut UiCell, s: &mut State, d: &mut Data, c: &mut Colors)
272 &mut State::Design(DesignState::Std) => {
273 base_ui(ui, s, d, c);
276 &mut State::Design(DesignState::Add) => {
277 base_ui(ui, s, d, c);
280 &mut State::Visual(_) => {
281 base_ui(ui, s, d, c);
282 visual_ui(ui, s, d, c);
284 &mut State::Err(_) => error_ui(ui, s, d, c),
288 fn error_ui(ui: &mut UiCell, gs: &mut State, d: &mut Data, c: &mut Colors)
292 State::Err(ref mut s) => s,
293 _ => panic!("non Err state"),
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)
303 .color(c.font).mid_top_of(C_ERR)
306 .label("Cancel").bottom_right_of(C_ERR)
309 s.msg = String::from("Cannot cancel");
311 .set(BTN_CANCEL_ERR, ui);
314 .label("OK").bottom_left_of(C_ERR)
317 *gs = State::Design(DesignState::Std);
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);
332 .color(c.c1).frame_color(c.c2)
333 .y((win_h/2.0)-(header_h/2.0)).h(header_h)
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)
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)
349 fn add_ui(ui: &mut UiCell, gs: &mut State, d: &mut Data, c: &mut Colors)
352 .mid_top_of(C_SIDE).label("Exit")
355 *gs = State::Design(DesignState::Std);
359 fn visual_ui(ui: &mut UiCell, gs: &mut State, d: &mut Data, c: &mut Colors)
362 .mid_left_of(C_HEADER).label("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)
371 // &mut State::Std => State::Std,
372 // _ => panic!("non Std state"),
375 .mid_left_of(C_HEADER).w_h(50.0, 30.0)
376 .color(c.c1).frame_color(c.c2)
378 .label("<").react(|| {
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)
386 .label(">").react(|| {
391 .mid_left_of(C_HEADER).right_from(BTN_NEXT, 60.0).label("Visual")
394 *gs = State::Visual(None);
395 }).set(BTN_VISUAL, ui);
397 .mid_top_of(C_SIDE).label("Add")
400 *gs = State::Design(DesignState::Add);
403 .mid_top_of(C_SIDE).down_from(BTN1, 20.0).label("Err")
406 *gs = State::Err(ErrState {
407 msg: String::from("Error!")
411 .mid_top_of(C_SIDE).down_from(BTN2, 20.0).label("þê¿ â€ŀï ¿»")
413 println!("þê¿ â€ŀï ¿»");
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);
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);
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);