mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-26 16:02:23 +03:00
start to move ezgui to glium. just copying extra code in, not deleting
existing stuff yet
This commit is contained in:
parent
6064aa10af
commit
974b04e74d
@ -67,3 +67,5 @@
|
||||
|
||||
- switch ezgui (could make it generic and have piston or glium support, but maybe not worth it)
|
||||
- render text
|
||||
- change ezgui API to allow uploading geometry once
|
||||
- undo the y inversion hacks at last!
|
||||
|
@ -8,6 +8,8 @@ edition = "2018"
|
||||
abstutil = { path = "../abstutil" }
|
||||
dimensioned = { git = "https://github.com/paholg/dimensioned", rev = "0e1076ebfa5128d1ee544bdc9754c948987b6fe3", features = ["serde"] }
|
||||
geom = { path = "../geom" }
|
||||
glium = "0.23.0"
|
||||
glutin = "0.19.0"
|
||||
log = "0.4.5"
|
||||
ordered-float = "1.0.1"
|
||||
palette = "0.4"
|
||||
|
171
ezgui/src/camera.rs
Normal file
171
ezgui/src/camera.rs
Normal file
@ -0,0 +1,171 @@
|
||||
use glutin;
|
||||
use std::f32;
|
||||
|
||||
pub struct CameraState {
|
||||
aspect_ratio: f32,
|
||||
position: (f32, f32, f32),
|
||||
direction: (f32, f32, f32),
|
||||
|
||||
moving_up: bool,
|
||||
moving_left: bool,
|
||||
moving_down: bool,
|
||||
moving_right: bool,
|
||||
moving_forward: bool,
|
||||
moving_backward: bool,
|
||||
}
|
||||
|
||||
impl CameraState {
|
||||
pub fn new() -> CameraState {
|
||||
CameraState {
|
||||
aspect_ratio: 1024.0 / 768.0,
|
||||
position: (0.1, 0.1, 1.0),
|
||||
direction: (0.0, 0.0, -1.0),
|
||||
moving_up: false,
|
||||
moving_left: false,
|
||||
moving_down: false,
|
||||
moving_right: false,
|
||||
moving_forward: false,
|
||||
moving_backward: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_perspective(&self) -> [[f32; 4]; 4] {
|
||||
let fov = f32::consts::PI / 2.0;
|
||||
let zfar = 1024.0;
|
||||
let znear = 0.1;
|
||||
|
||||
let f = 1.0 / (fov / 2.0).tan();
|
||||
|
||||
// note: remember that this is column-major, so the lines of code are actually columns
|
||||
[
|
||||
[f / self.aspect_ratio, 0.0, 0.0, 0.0],
|
||||
[0.0, f, 0.0, 0.0],
|
||||
[0.0, 0.0, (zfar + znear) / (zfar - znear), 1.0],
|
||||
[0.0, 0.0, -(2.0 * zfar * znear) / (zfar - znear), 0.0],
|
||||
]
|
||||
}
|
||||
|
||||
pub fn get_view(&self) -> [[f32; 4]; 4] {
|
||||
let f = {
|
||||
let f = self.direction;
|
||||
let len = f.0 * f.0 + f.1 * f.1 + f.2 * f.2;
|
||||
let len = len.sqrt();
|
||||
(f.0 / len, f.1 / len, f.2 / len)
|
||||
};
|
||||
|
||||
let up = (0.0, 1.0, 0.0);
|
||||
|
||||
let s = (
|
||||
f.1 * up.2 - f.2 * up.1,
|
||||
f.2 * up.0 - f.0 * up.2,
|
||||
f.0 * up.1 - f.1 * up.0,
|
||||
);
|
||||
|
||||
let s_norm = {
|
||||
let len = s.0 * s.0 + s.1 * s.1 + s.2 * s.2;
|
||||
let len = len.sqrt();
|
||||
(s.0 / len, s.1 / len, s.2 / len)
|
||||
};
|
||||
|
||||
let u = (
|
||||
s_norm.1 * f.2 - s_norm.2 * f.1,
|
||||
s_norm.2 * f.0 - s_norm.0 * f.2,
|
||||
s_norm.0 * f.1 - s_norm.1 * f.0,
|
||||
);
|
||||
|
||||
let p = (
|
||||
-self.position.0 * s.0 - self.position.1 * s.1 - self.position.2 * s.2,
|
||||
-self.position.0 * u.0 - self.position.1 * u.1 - self.position.2 * u.2,
|
||||
-self.position.0 * f.0 - self.position.1 * f.1 - self.position.2 * f.2,
|
||||
);
|
||||
|
||||
// note: remember that this is column-major, so the lines of code are actually columns
|
||||
[
|
||||
[s_norm.0, u.0, f.0, 0.0],
|
||||
[s_norm.1, u.1, f.1, 0.0],
|
||||
[s_norm.2, u.2, f.2, 0.0],
|
||||
[p.0, p.1, p.2, 1.0],
|
||||
]
|
||||
}
|
||||
|
||||
fn update(&mut self) {
|
||||
let f = {
|
||||
let f = self.direction;
|
||||
let len = f.0 * f.0 + f.1 * f.1 + f.2 * f.2;
|
||||
let len = len.sqrt();
|
||||
(f.0 / len, f.1 / len, f.2 / len)
|
||||
};
|
||||
|
||||
let up = (0.0, 1.0, 0.0);
|
||||
|
||||
let s = (
|
||||
f.1 * up.2 - f.2 * up.1,
|
||||
f.2 * up.0 - f.0 * up.2,
|
||||
f.0 * up.1 - f.1 * up.0,
|
||||
);
|
||||
|
||||
let s = {
|
||||
let len = s.0 * s.0 + s.1 * s.1 + s.2 * s.2;
|
||||
let len = len.sqrt();
|
||||
(s.0 / len, s.1 / len, s.2 / len)
|
||||
};
|
||||
|
||||
let u = (
|
||||
s.1 * f.2 - s.2 * f.1,
|
||||
s.2 * f.0 - s.0 * f.2,
|
||||
s.0 * f.1 - s.1 * f.0,
|
||||
);
|
||||
|
||||
let speed = 0.1;
|
||||
|
||||
if self.moving_up {
|
||||
self.position.0 += u.0 * speed;
|
||||
self.position.1 += u.1 * speed;
|
||||
self.position.2 += u.2 * speed;
|
||||
}
|
||||
|
||||
if self.moving_left {
|
||||
self.position.0 -= s.0 * speed;
|
||||
self.position.1 -= s.1 * speed;
|
||||
self.position.2 -= s.2 * speed;
|
||||
}
|
||||
|
||||
if self.moving_down {
|
||||
self.position.0 -= u.0 * speed;
|
||||
self.position.1 -= u.1 * speed;
|
||||
self.position.2 -= u.2 * speed;
|
||||
}
|
||||
|
||||
if self.moving_right {
|
||||
self.position.0 += s.0 * speed;
|
||||
self.position.1 += s.1 * speed;
|
||||
self.position.2 += s.2 * speed;
|
||||
}
|
||||
|
||||
if self.moving_forward {
|
||||
self.position.0 += f.0 * speed;
|
||||
self.position.1 += f.1 * speed;
|
||||
self.position.2 += f.2 * speed;
|
||||
}
|
||||
|
||||
if self.moving_backward {
|
||||
self.position.0 -= f.0 * speed;
|
||||
self.position.1 -= f.1 * speed;
|
||||
self.position.2 -= f.2 * speed;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process_input(&mut self, input: glutin::KeyboardInput) {
|
||||
let pressed = input.state == glutin::ElementState::Pressed;
|
||||
match input.virtual_keycode {
|
||||
Some(glutin::VirtualKeyCode::Up) => self.moving_up = pressed,
|
||||
Some(glutin::VirtualKeyCode::Down) => self.moving_down = pressed,
|
||||
Some(glutin::VirtualKeyCode::Left) => self.moving_left = pressed,
|
||||
Some(glutin::VirtualKeyCode::Right) => self.moving_right = pressed,
|
||||
Some(glutin::VirtualKeyCode::Q) => self.moving_forward = pressed,
|
||||
Some(glutin::VirtualKeyCode::A) => self.moving_backward = pressed,
|
||||
_ => {}
|
||||
};
|
||||
self.update();
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
use crate::ScreenPt;
|
||||
use glium::glutin;
|
||||
use piston::input as pi;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
@ -24,6 +25,50 @@ pub enum Event {
|
||||
}
|
||||
|
||||
impl Event {
|
||||
pub fn from_glutin_event(ev: glutin::WindowEvent) -> Option<Event> {
|
||||
match ev {
|
||||
glutin::WindowEvent::MouseInput { state, button, .. } => match (button, state) {
|
||||
(glutin::MouseButton::Left, glutin::ElementState::Pressed) => {
|
||||
Some(Event::LeftMouseButtonDown)
|
||||
}
|
||||
(glutin::MouseButton::Left, glutin::ElementState::Released) => {
|
||||
Some(Event::LeftMouseButtonUp)
|
||||
}
|
||||
(glutin::MouseButton::Right, glutin::ElementState::Pressed) => {
|
||||
Some(Event::RightMouseButtonDown)
|
||||
}
|
||||
(glutin::MouseButton::Right, glutin::ElementState::Released) => {
|
||||
Some(Event::RightMouseButtonUp)
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
glutin::WindowEvent::KeyboardInput { input, .. } => {
|
||||
if let Some(key) = Key::from_glutin_key(input) {
|
||||
if input.state == glutin::ElementState::Pressed {
|
||||
Some(Event::KeyPress(key))
|
||||
} else {
|
||||
Some(Event::KeyRelease(key))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
glutin::WindowEvent::CursorMoved { position, .. } => {
|
||||
Some(Event::MouseMovedTo(ScreenPt::new(position.x, position.y)))
|
||||
}
|
||||
//glutin::WindowEvent::MouseWheel { delta, .. } => Event::MouseWheelScroll(),
|
||||
glutin::WindowEvent::Resized(size) => {
|
||||
Some(Event::WindowResized(size.width, size.height))
|
||||
}
|
||||
glutin::WindowEvent::Focused(gained) => Some(if gained {
|
||||
Event::WindowGainedCursor
|
||||
} else {
|
||||
Event::WindowLostCursor
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_piston_event(ev: pi::Event) -> Event {
|
||||
use piston::input::{
|
||||
ButtonEvent, CursorEvent, MouseCursorEvent, MouseScrollEvent, PressEvent, ReleaseEvent,
|
||||
@ -348,4 +393,79 @@ impl Key {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn from_glutin_key(input: glutin::KeyboardInput) -> Option<Key> {
|
||||
let key = input.virtual_keycode?;
|
||||
Some(match key {
|
||||
glutin::VirtualKeyCode::A => Key::A,
|
||||
glutin::VirtualKeyCode::B => Key::B,
|
||||
glutin::VirtualKeyCode::C => Key::C,
|
||||
glutin::VirtualKeyCode::D => Key::D,
|
||||
glutin::VirtualKeyCode::E => Key::E,
|
||||
glutin::VirtualKeyCode::F => Key::F,
|
||||
glutin::VirtualKeyCode::G => Key::G,
|
||||
glutin::VirtualKeyCode::H => Key::H,
|
||||
glutin::VirtualKeyCode::I => Key::I,
|
||||
glutin::VirtualKeyCode::J => Key::J,
|
||||
glutin::VirtualKeyCode::K => Key::K,
|
||||
glutin::VirtualKeyCode::L => Key::L,
|
||||
glutin::VirtualKeyCode::M => Key::M,
|
||||
glutin::VirtualKeyCode::N => Key::N,
|
||||
glutin::VirtualKeyCode::O => Key::O,
|
||||
glutin::VirtualKeyCode::P => Key::P,
|
||||
glutin::VirtualKeyCode::Q => Key::Q,
|
||||
glutin::VirtualKeyCode::R => Key::R,
|
||||
glutin::VirtualKeyCode::S => Key::S,
|
||||
glutin::VirtualKeyCode::T => Key::T,
|
||||
glutin::VirtualKeyCode::U => Key::U,
|
||||
glutin::VirtualKeyCode::V => Key::V,
|
||||
glutin::VirtualKeyCode::W => Key::W,
|
||||
glutin::VirtualKeyCode::X => Key::X,
|
||||
glutin::VirtualKeyCode::Y => Key::Y,
|
||||
glutin::VirtualKeyCode::Z => Key::Z,
|
||||
glutin::VirtualKeyCode::Key1 => Key::Num1,
|
||||
glutin::VirtualKeyCode::Key2 => Key::Num2,
|
||||
glutin::VirtualKeyCode::Key3 => Key::Num3,
|
||||
glutin::VirtualKeyCode::Key4 => Key::Num4,
|
||||
glutin::VirtualKeyCode::Key5 => Key::Num5,
|
||||
glutin::VirtualKeyCode::Key6 => Key::Num6,
|
||||
glutin::VirtualKeyCode::Key7 => Key::Num7,
|
||||
glutin::VirtualKeyCode::Key8 => Key::Num8,
|
||||
glutin::VirtualKeyCode::Key9 => Key::Num9,
|
||||
glutin::VirtualKeyCode::Key0 => Key::Num0,
|
||||
glutin::VirtualKeyCode::LBracket => Key::LeftBracket,
|
||||
glutin::VirtualKeyCode::RBracket => Key::RightBracket,
|
||||
glutin::VirtualKeyCode::Space => Key::Space,
|
||||
glutin::VirtualKeyCode::Slash => Key::Slash,
|
||||
glutin::VirtualKeyCode::Period => Key::Dot,
|
||||
glutin::VirtualKeyCode::Comma => Key::Comma,
|
||||
glutin::VirtualKeyCode::Escape => Key::Escape,
|
||||
glutin::VirtualKeyCode::Return => Key::Enter,
|
||||
glutin::VirtualKeyCode::Tab => Key::Tab,
|
||||
glutin::VirtualKeyCode::Back => Key::Backspace,
|
||||
glutin::VirtualKeyCode::LShift => Key::LeftShift,
|
||||
glutin::VirtualKeyCode::LControl => Key::LeftControl,
|
||||
glutin::VirtualKeyCode::LAlt => Key::LeftAlt,
|
||||
glutin::VirtualKeyCode::Left => Key::LeftArrow,
|
||||
glutin::VirtualKeyCode::Right => Key::RightArrow,
|
||||
glutin::VirtualKeyCode::Up => Key::UpArrow,
|
||||
glutin::VirtualKeyCode::Down => Key::DownArrow,
|
||||
glutin::VirtualKeyCode::F1 => Key::F1,
|
||||
glutin::VirtualKeyCode::F2 => Key::F2,
|
||||
glutin::VirtualKeyCode::F3 => Key::F3,
|
||||
glutin::VirtualKeyCode::F4 => Key::F4,
|
||||
glutin::VirtualKeyCode::F5 => Key::F5,
|
||||
glutin::VirtualKeyCode::F6 => Key::F6,
|
||||
glutin::VirtualKeyCode::F7 => Key::F7,
|
||||
glutin::VirtualKeyCode::F8 => Key::F8,
|
||||
glutin::VirtualKeyCode::F9 => Key::F9,
|
||||
glutin::VirtualKeyCode::F10 => Key::F10,
|
||||
glutin::VirtualKeyCode::F11 => Key::F11,
|
||||
glutin::VirtualKeyCode::F12 => Key::F12,
|
||||
_ => {
|
||||
println!("Unknown glutin key {:?}", key);
|
||||
return None;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
8
ezgui/src/fragment.glsl
Normal file
8
ezgui/src/fragment.glsl
Normal file
@ -0,0 +1,8 @@
|
||||
#version 140
|
||||
|
||||
in vec4 pass_color;
|
||||
out vec4 f_color;
|
||||
|
||||
void main() {
|
||||
f_color = pass_color;
|
||||
}
|
189
ezgui/src/lib.rs
189
ezgui/src/lib.rs
@ -1,3 +1,4 @@
|
||||
mod camera;
|
||||
mod canvas;
|
||||
mod color;
|
||||
mod event;
|
||||
@ -12,6 +13,7 @@ mod text_box;
|
||||
mod top_menu;
|
||||
mod wizard;
|
||||
|
||||
use crate::camera::CameraState;
|
||||
pub use crate::canvas::{Canvas, HorizontalAlignment, VerticalAlignment, BOTTOM_LEFT, CENTERED};
|
||||
pub use crate::color::Color;
|
||||
pub use crate::event::{Event, Key};
|
||||
@ -25,6 +27,7 @@ pub use crate::text_box::TextBox;
|
||||
pub use crate::top_menu::{Folder, TopMenu};
|
||||
pub use crate::wizard::{Wizard, WrappedWizard};
|
||||
use geom::Pt2D;
|
||||
use glium::{implement_vertex, uniform, Surface};
|
||||
use graphics::Transformed;
|
||||
use opengl_graphics::GlGraphics;
|
||||
use std::mem;
|
||||
@ -212,3 +215,189 @@ pub enum InputResult<T: Clone> {
|
||||
StillActive,
|
||||
Done(String, T),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct Vertex {
|
||||
position: [f32; 2],
|
||||
// TODO Maybe pass color as a uniform instead
|
||||
color: [f32; 4],
|
||||
}
|
||||
|
||||
implement_vertex!(Vertex, position, color);
|
||||
|
||||
type Uniforms<'a> = glium::uniforms::UniformsStorage<
|
||||
'a,
|
||||
[[f32; 4]; 4],
|
||||
glium::uniforms::UniformsStorage<'a, [[f32; 4]; 4], glium::uniforms::EmptyUniforms>,
|
||||
>;
|
||||
|
||||
pub struct NewGfxCtx<'a> {
|
||||
display: &'a glium::Display,
|
||||
target: &'a mut glium::Frame,
|
||||
program: &'a glium::Program,
|
||||
uniforms: Uniforms<'a>,
|
||||
params: glium::DrawParameters<'a>,
|
||||
}
|
||||
|
||||
impl<'a> NewGfxCtx<'a> {
|
||||
pub fn new(
|
||||
display: &'a glium::Display,
|
||||
target: &'a mut glium::Frame,
|
||||
program: &'a glium::Program,
|
||||
) -> NewGfxCtx<'a> {
|
||||
let params = glium::DrawParameters {
|
||||
depth: glium::Depth {
|
||||
test: glium::DepthTest::IfLess,
|
||||
write: true,
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let mut camera = CameraState::new();
|
||||
// TODO setup camera based on canvas
|
||||
let uniforms = uniform! {
|
||||
persp_matrix: camera.get_perspective(),
|
||||
view_matrix: camera.get_view(),
|
||||
};
|
||||
|
||||
NewGfxCtx {
|
||||
display,
|
||||
target,
|
||||
program,
|
||||
uniforms,
|
||||
params,
|
||||
}
|
||||
}
|
||||
|
||||
// Up to the caller to call unfork()!
|
||||
// TODO Canvas doesn't understand this change, so things like text drawing that use
|
||||
// map_to_screen will just be confusing.
|
||||
pub fn fork(&mut self, top_left: Pt2D, zoom: f64) -> Uniforms {
|
||||
let mut camera = CameraState::new();
|
||||
// TODO setup camera based on values above
|
||||
let mut uniforms = uniform! {
|
||||
persp_matrix: camera.get_perspective(),
|
||||
view_matrix: camera.get_view(),
|
||||
};
|
||||
|
||||
mem::swap(&mut self.uniforms, &mut uniforms);
|
||||
uniforms
|
||||
}
|
||||
|
||||
pub fn fork_screenspace(&mut self) -> Uniforms {
|
||||
self.fork(Pt2D::new(0.0, 0.0), 1.0)
|
||||
}
|
||||
|
||||
pub fn unfork(&mut self, old_uniforms: Uniforms<'a>) {
|
||||
// TODO What do we need to do to re-upload?
|
||||
self.uniforms = old_uniforms;
|
||||
}
|
||||
|
||||
pub fn clear(&mut self, color: Color) {
|
||||
self.target
|
||||
.clear_color_and_depth((color.0[0], color.0[1], color.0[2], color.0[3]), 1.0);
|
||||
}
|
||||
|
||||
// Use graphics::Line internally for now, but make it easy to switch to something else by
|
||||
// picking this API now.
|
||||
pub fn draw_line(&mut self, color: Color, thickness: f64, line: &geom::Line) {
|
||||
self.draw_polygon(color, &line.to_polyline().make_polygons(thickness));
|
||||
}
|
||||
|
||||
pub fn draw_rounded_line(&mut self, color: Color, thickness: f64, line: &geom::Line) {
|
||||
self.draw_line(color, thickness, line);
|
||||
self.draw_circle(color, &geom::Circle::new(line.pt1(), thickness / 2.0));
|
||||
self.draw_circle(color, &geom::Circle::new(line.pt2(), thickness / 2.0));
|
||||
}
|
||||
|
||||
pub fn draw_arrow(&mut self, color: Color, thickness: f64, line: &geom::Line) {
|
||||
// TODO Raw method doesn't work yet in all cases...
|
||||
/*graphics::Line::new_round(color.0, thickness).draw_arrow(
|
||||
[
|
||||
line.pt1().x(),
|
||||
line.pt1().y(),
|
||||
line.pt2().x(),
|
||||
line.pt2().y(),
|
||||
],
|
||||
2.0 * thickness,
|
||||
&self.ctx.draw_state,
|
||||
self.ctx.transform,
|
||||
self.gfx,
|
||||
);*/
|
||||
|
||||
/*use dimensioned::si;
|
||||
let head_size = 2.0 * thickness;
|
||||
let angle = line.angle();
|
||||
let triangle_height = (head_size / 2.0).sqrt() * si::M;
|
||||
self.draw_polygon(
|
||||
color,
|
||||
&geom::Polygon::new(&vec![
|
||||
//line.pt2(),
|
||||
//line.pt2().project_away(head_size, angle.rotate_degs(-135.0)),
|
||||
line.reverse()
|
||||
.dist_along(triangle_height)
|
||||
.project_away(thickness / 2.0, angle.rotate_degs(90.0)),
|
||||
line.pt1()
|
||||
.project_away(thickness / 2.0, angle.rotate_degs(90.0)),
|
||||
line.pt1()
|
||||
.project_away(thickness / 2.0, angle.rotate_degs(-90.0)),
|
||||
line.reverse()
|
||||
.dist_along(triangle_height)
|
||||
.project_away(thickness / 2.0, angle.rotate_degs(-90.0)),
|
||||
//line.pt2().project_away(head_size, angle.rotate_degs(135.0)),
|
||||
]),
|
||||
);
|
||||
self.draw_polygon(
|
||||
color,
|
||||
&geom::Polygon::new(&vec![
|
||||
line.pt2(),
|
||||
line.pt2()
|
||||
.project_away(head_size, angle.rotate_degs(-135.0)),
|
||||
line.pt2().project_away(head_size, angle.rotate_degs(135.0)),
|
||||
]),
|
||||
);*/
|
||||
}
|
||||
|
||||
pub fn draw_polygon(&mut self, color: Color, poly: &geom::Polygon) {
|
||||
for tri in &poly.triangles {
|
||||
let vb = glium::VertexBuffer::new(
|
||||
self.display,
|
||||
&[
|
||||
Vertex {
|
||||
position: [tri.pt1.x() as f32, tri.pt1.y() as f32],
|
||||
color: color.0,
|
||||
},
|
||||
Vertex {
|
||||
position: [tri.pt2.x() as f32, tri.pt2.y() as f32],
|
||||
color: color.0,
|
||||
},
|
||||
Vertex {
|
||||
position: [tri.pt3.x() as f32, tri.pt3.y() as f32],
|
||||
color: color.0,
|
||||
},
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
let indices = glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);
|
||||
|
||||
self.target
|
||||
.draw(&vb, &indices, &self.program, &self.uniforms, &self.params)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_circle(&mut self, color: Color, circle: &geom::Circle) {
|
||||
/*graphics::Ellipse::new(color.0).draw(
|
||||
[
|
||||
circle.center.x() - circle.radius,
|
||||
circle.center.y() - circle.radius,
|
||||
2.0 * circle.radius,
|
||||
2.0 * circle.radius,
|
||||
],
|
||||
&self.ctx.draw_state,
|
||||
self.ctx.transform,
|
||||
self.gfx,
|
||||
);*/
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,14 @@
|
||||
use crate::input::{ContextMenu, ModalMenuState};
|
||||
use crate::{Canvas, Event, GfxCtx, ModalMenu, TopMenu, UserInput};
|
||||
use crate::{Canvas, Event, GfxCtx, ModalMenu, NewGfxCtx, TopMenu, UserInput};
|
||||
use abstutil::Timer;
|
||||
use glium::glutin;
|
||||
use glutin_window::GlutinWindow;
|
||||
use opengl_graphics::{GlGraphics, OpenGL};
|
||||
use piston::event_loop::{EventLoop, EventSettings, Events};
|
||||
use piston::window::WindowSettings;
|
||||
use std::io::Write;
|
||||
use std::{env, fs, panic, process};
|
||||
use std::time::{Duration, Instant};
|
||||
use std::{env, fs, panic, process, thread};
|
||||
|
||||
pub trait GUI<T> {
|
||||
// Called once
|
||||
@ -172,6 +174,13 @@ impl<T, G: GUI<T>> State<T, G> {
|
||||
self
|
||||
}
|
||||
|
||||
fn new_draw(&mut self, display: &glium::Display, program: &glium::Program) {
|
||||
let mut target = display.draw();
|
||||
// TODO call draw
|
||||
NewGfxCtx::new(&display, &mut target, program);
|
||||
target.finish().unwrap();
|
||||
}
|
||||
|
||||
fn draw(&mut self, g: &mut GfxCtx) {
|
||||
// If the very first event is render, then just wait.
|
||||
if let Some(ref data) = self.last_data {
|
||||
@ -309,3 +318,67 @@ impl ScreenCaptureState {
|
||||
writeln!(file, "rm -f combine.sh").unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_run<T, G: GUI<T>>(mut gui: G, window_title: &str) {
|
||||
// DPI is broken on my system; force the old behavior.
|
||||
env::set_var("WINIT_HIDPI_FACTOR", "1.0");
|
||||
|
||||
let mut events_loop = glutin::EventsLoop::new();
|
||||
let window = glutin::WindowBuilder::new()
|
||||
.with_title(window_title)
|
||||
.with_dimensions(glutin::dpi::LogicalSize::new(
|
||||
gui.get_mut_canvas().window_width,
|
||||
gui.get_mut_canvas().window_height,
|
||||
));
|
||||
let context = glutin::ContextBuilder::new().with_depth_buffer(24);
|
||||
let display = glium::Display::new(window, context, &events_loop).unwrap();
|
||||
let program = glium::Program::from_source(
|
||||
&display,
|
||||
include_str!("vertex.glsl"),
|
||||
include_str!("fragment.glsl"),
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut state = State {
|
||||
last_event_mode: EventLoopMode::InputOnly,
|
||||
context_menu: ContextMenu::Inactive,
|
||||
top_menu: gui.top_menu(),
|
||||
modal_state: ModalMenuState::new(G::modal_menus()),
|
||||
last_data: None,
|
||||
screen_cap: None,
|
||||
gui,
|
||||
};
|
||||
|
||||
let mut accumulator = Duration::new(0, 0);
|
||||
let mut previous_clock = Instant::now();
|
||||
loop {
|
||||
state.new_draw(&display, &program);
|
||||
state.after_render();
|
||||
|
||||
events_loop.poll_events(|event| {
|
||||
if let glutin::Event::WindowEvent { event, .. } = event {
|
||||
if event == glutin::WindowEvent::CloseRequested {
|
||||
state.gui.before_quit();
|
||||
process::exit(0);
|
||||
}
|
||||
if state.screen_cap.is_none() {
|
||||
// TODO manage laziness differently
|
||||
//state = state.event(event, &mut events);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let now = Instant::now();
|
||||
accumulator += now - previous_clock;
|
||||
previous_clock = now;
|
||||
|
||||
let fixed_time_stamp = Duration::new(0, 16_666_667);
|
||||
while accumulator >= fixed_time_stamp {
|
||||
accumulator -= fixed_time_stamp;
|
||||
// TODO send off an update event
|
||||
}
|
||||
|
||||
thread::sleep(fixed_time_stamp - accumulator);
|
||||
}
|
||||
}
|
||||
|
15
ezgui/src/vertex.glsl
Normal file
15
ezgui/src/vertex.glsl
Normal file
@ -0,0 +1,15 @@
|
||||
#version 140
|
||||
|
||||
uniform mat4 persp_matrix;
|
||||
uniform mat4 view_matrix;
|
||||
|
||||
in vec2 position;
|
||||
in vec4 color;
|
||||
out vec4 pass_color;
|
||||
|
||||
void main() {
|
||||
pass_color = color;
|
||||
|
||||
gl_Position = vec4(position, 0.0, 1.0);
|
||||
gl_Position = persp_matrix * view_matrix * vec4(position, 0.0, 1.0);
|
||||
}
|
Loading…
Reference in New Issue
Block a user