use rand::Rng;
use winit::{
event::*,
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
};
use bufro::Color;
use cgmath::VectorSpace;
fn main() {
env_logger::init();
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_inner_size(winit::dpi::PhysicalSize::new(500, 500))
.build(&event_loop)
.unwrap();
let mut painter = pollster::block_on(bufro::Painter::new_from_window(&window, (500, 500), bufro::Backends::all()));
let font = bufro::Font::new(include_bytes!("Roboto-Regular.ttf")).unwrap();
let mut cursor_position = cgmath::vec2(0.0, 0.0);
let mut mouse_down = false;
let mut canvas_translation = cgmath::vec2(0.0, 0.0);
let mut canvas_translation_lerped = cgmath::vec2(0.0, 0.0);
let mut canvas_scale = cgmath::vec1(1.);
let mut canvas_scale_lerped = cgmath::vec1(1.);
let mut frame = 0;
let mut circles = std::collections::HashMap::new();
let mut rng = rand::thread_rng();
event_loop.run(move |event, _, control_flow| {
let text = "Bufro v0.1.7";
match event {
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
match event {
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::CursorMoved { position, .. } => {
let rel_x = cursor_position.x - position.x;
let rel_y = cursor_position.y - position.y;
if mouse_down {
canvas_translation.x -= rel_x / canvas_scale_lerped.x as f64;
canvas_translation.y -= rel_y / canvas_scale_lerped.x as f64;
}
cursor_position = cgmath::vec2(position.x, position.y)
}
WindowEvent::MouseInput { state, .. } => match state {
winit::event::ElementState::Pressed => mouse_down = true,
winit::event::ElementState::Released => mouse_down = false,
},
WindowEvent::MouseWheel { delta, .. } => match delta {
winit::event::MouseScrollDelta::LineDelta(x, y) => {
canvas_scale.x += y / 10.;
}
_ => {}
},
WindowEvent::KeyboardInput {
input:
winit::event::KeyboardInput {
virtual_keycode: Some(keycode),
..
},
..
} => match keycode {
VirtualKeyCode::Escape => *control_flow = ControlFlow::Exit,
VirtualKeyCode::Space => {}
_ => {}
},
WindowEvent::Resized(physical_size) => {
painter.resize((physical_size.width, physical_size.height));
}
WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
painter.resize((new_inner_size.width, new_inner_size.height));
}
_ => {}
}
}
Event::RedrawRequested(_) => {
frame += 1;
let size = window.inner_size();
painter.rectangle(
0.,
0.,
size.width as f32,
size.height as f32,
Color::from_f(0.2, 0.2, 0.2, 1.0),
);
canvas_translation_lerped = canvas_translation_lerped.lerp(canvas_translation, 0.2);
canvas_scale_lerped = canvas_scale_lerped.lerp(canvas_scale, 0.2);
painter.translate(size.width as f32 / 2., size.height as f32 / 2.);
painter.scale(canvas_scale_lerped.x, canvas_scale_lerped.x);
painter.translate(
-(size.width as f32) / 2. + canvas_translation_lerped.x as f32,
-(size.height as f32) / 2. + canvas_translation_lerped.y as f32,
);
painter.rectangle(50., 50., 100., 100., Color::from_8(220, 220, 40, 100));
painter.rectangle(75., 75., 100., 100., Color::from_8(30, 90, 200, 100));
painter.rectangle(225., 225., 100., 100., Color::from_8(30, 90, 200, 100));
painter.rectangle(200., 200., 100., 100., Color::from_8(220, 220, 40, 100));
painter.save();
painter.translate(500., 500.);
painter.save();
painter.translate(-75., 0.);
painter.circle(0., 0., 100., Color::from_8(0, 0, 255, 100));
painter.restore();
painter.save();
painter.translate(75., 0.);
painter.circle(0., 0., 100., Color::from_8(0, 255, 0, 100));
painter.restore();
painter.save();
painter.translate(0., -75.);
painter.circle(0., 0., 100., Color::from_8(255, 0, 0, 100));
painter.restore();
painter.restore();
painter.save();
painter.translate(700., 100.);
let mut path = bufro::PathBuilder::new();
path.move_to(0., 0.);
path.quad_to(100., 100., 200., 0.);
path.quad_to(100., 100., 200., 200.);
path.quad_to(100., 100., 0., 200.);
path.quad_to(100., 100., 0., 0.);
path.close();
let path = path.build();
painter.fill_path(&path, Color::from_8(200, 200, 200, 255));
painter.stroke_path(
&path,
Color::from_8(255, 255, 255, 255),
bufro::StrokeOptions::default()
.with_line_width(10.)
.with_line_join(bufro::LineJoin::Round),
);
painter.translate(300., 0.);
let mut path = bufro::PathBuilder::new();
path.move_to(0., 0.);
path.curve_to(100., 100., 100., -100., 200., 0.);
path.curve_to(100., 100., 300., 100., 200., 200.);
path.curve_to(100., 100., 100., 300., 0., 200.);
path.curve_to(100., 100., -100., 100., 0., 0.);
path.close();
let path = path.build();
painter.fill_path(&path, Color::from_8(200, 200, 200, 255));
painter.stroke_path(
&path,
Color::from_8(255, 255, 255, 255),
bufro::StrokeOptions::default()
.with_line_width(10.)
.with_line_join(bufro::LineJoin::Round),
);
painter.restore();
if circles.len() < 10000 {
circles.insert(
frame,
(
rng.gen_range(0.0..10000.0),
rng.gen_range(0.0..10000.0),
rng.gen_range(10.0..50.0),
),
);
}
let time_start = std::time::Instant::now();
for (_, circle) in circles.iter_mut() {
painter.save();
painter.translate(circle.0, circle.1);
painter.circle(0.0, 0.0, circle.2, Color::from_8(214, 73, 5, 255));
painter.restore();
}
println!("Elapsed: {:?}", time_start.elapsed());
painter.circle(
0.,
0.,
(frame % 60 + 1) as f32,
Color::from_8(255, 255, 255, 255),
);
painter.reset();
painter.fill_text(
&font,
&painter.get_buffer_info(),
0.,
0.,
15.5,
Color::from_8(0xFF, 0xFF, 0xFF, 0xFF),
Some(150),
);
match painter.flush() {
Ok(_) => {}
Err(wgpu::SurfaceError::Lost) => {
painter.clear();
painter.regen()
}
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(e) => {
painter.clear();
eprintln!("{:?}", e)
}
}
}
Event::MainEventsCleared => {
window.request_redraw();
}
_ => {}
}
});
}