Run `rustfmt` on the demos

This commit is contained in:
Patrick Walton 2019-04-29 16:52:37 -07:00
parent 0da11ffe01
commit 60b951409c
6 changed files with 923 additions and 513 deletions

View File

@ -11,11 +11,11 @@
#[macro_use]
extern crate lazy_static;
use jni::{JNIEnv, JavaVM};
use jni::objects::{GlobalRef, JByteBuffer, JClass, JObject, JString, JValue};
use jni::{JNIEnv, JavaVM};
use pathfinder_demo::window::{Event, SVGPath, View, Window, WindowSize};
use pathfinder_demo::DemoApp;
use pathfinder_demo::Options;
use pathfinder_demo::window::{Event, SVGPath, View, Window, WindowSize};
use pathfinder_geometry::basic::point::Point2DI32;
use pathfinder_geometry::basic::rect::RectI32;
use pathfinder_gl::GLVersion;
@ -40,15 +40,19 @@ thread_local! {
static RESOURCE_LOADER: AndroidResourceLoader = AndroidResourceLoader;
#[no_mangle]
pub unsafe extern "system" fn
Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_init(env: JNIEnv,
pub unsafe extern "system" fn Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_init(
env: JNIEnv,
class: JClass,
activity: JObject,
loader: JObject,
width: i32,
height: i32) {
height: i32,
) {
let logical_size = Point2DI32::new(width, height);
let window_size = WindowSize { logical_size, backing_scale_factor: 1.0 };
let window_size = WindowSize {
logical_size,
backing_scale_factor: 1.0,
};
let window = WindowImpl { size: logical_size };
let options = Options::default();
@ -65,10 +69,10 @@ pub unsafe extern "system" fn
}
#[no_mangle]
pub unsafe extern "system" fn
Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_prepareFrame(env: JNIEnv,
class: JClass)
-> i32 {
pub unsafe extern "system" fn Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_prepareFrame(
env: JNIEnv,
class: JClass,
) -> i32 {
DEMO_APP.with(|demo_app| {
let mut event_queue = EVENT_QUEUE.lock().unwrap();
match *demo_app.borrow_mut() {
@ -81,10 +85,10 @@ pub unsafe extern "system" fn
}
#[no_mangle]
pub unsafe extern "system" fn
Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_drawScene(
pub unsafe extern "system" fn Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_drawScene(
env: JNIEnv,
class: JClass) {
class: JClass,
) {
DEMO_APP.with(|demo_app| {
if let Some(ref mut demo_app) = *demo_app.borrow_mut() {
demo_app.draw_scene()
@ -93,10 +97,10 @@ pub unsafe extern "system" fn
}
#[no_mangle]
pub unsafe extern "system" fn
Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_finishDrawingFrame(
pub unsafe extern "system" fn Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_finishDrawingFrame(
env: JNIEnv,
class: JClass) {
class: JClass,
) {
DEMO_APP.with(|demo_app| {
if let Some(ref mut demo_app) = *demo_app.borrow_mut() {
demo_app.finish_drawing_frame()
@ -105,67 +109,82 @@ pub unsafe extern "system" fn
}
#[no_mangle]
pub unsafe extern "system" fn
Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_pushWindowResizedEvent(
pub unsafe extern "system" fn Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_pushWindowResizedEvent(
env: JNIEnv,
class: JClass,
width: i32,
height: i32) {
EVENT_QUEUE.lock().unwrap().push(Event::WindowResized(WindowSize {
height: i32,
) {
EVENT_QUEUE
.lock()
.unwrap()
.push(Event::WindowResized(WindowSize {
logical_size: Point2DI32::new(width, height),
backing_scale_factor: 1.0,
}))
}
#[no_mangle]
pub unsafe extern "system" fn
Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_pushMouseDownEvent(
pub unsafe extern "system" fn Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_pushMouseDownEvent(
_: JNIEnv,
_: JClass,
x: i32,
y: i32) {
EVENT_QUEUE.lock().unwrap().push(Event::MouseDown(Point2DI32::new(x, y)))
y: i32,
) {
EVENT_QUEUE
.lock()
.unwrap()
.push(Event::MouseDown(Point2DI32::new(x, y)))
}
#[no_mangle]
pub unsafe extern "system" fn
Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_pushMouseDraggedEvent(
pub unsafe extern "system" fn Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_pushMouseDraggedEvent(
_: JNIEnv,
_: JClass,
x: i32,
y: i32) {
EVENT_QUEUE.lock().unwrap().push(Event::MouseDragged(Point2DI32::new(x, y)))
y: i32,
) {
EVENT_QUEUE
.lock()
.unwrap()
.push(Event::MouseDragged(Point2DI32::new(x, y)))
}
#[no_mangle]
pub unsafe extern "system" fn
Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_pushZoomEvent(
pub unsafe extern "system" fn Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_pushZoomEvent(
_: JNIEnv,
_: JClass,
factor: f32,
center_x: i32,
center_y: i32) {
EVENT_QUEUE.lock().unwrap().push(Event::Zoom(factor, Point2DI32::new(center_x, center_y)))
center_y: i32,
) {
EVENT_QUEUE
.lock()
.unwrap()
.push(Event::Zoom(factor, Point2DI32::new(center_x, center_y)))
}
#[no_mangle]
pub unsafe extern "system" fn
Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_pushLookEvent(
pub unsafe extern "system" fn Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_pushLookEvent(
_: JNIEnv,
_: JClass,
pitch: f32,
yaw: f32) {
yaw: f32,
) {
EVENT_QUEUE.lock().unwrap().push(Event::Look { pitch, yaw })
}
#[no_mangle]
pub unsafe extern "system" fn
Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_pushOpenSVGEvent(
pub unsafe extern "system" fn Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_pushOpenSVGEvent(
env: JNIEnv,
_: JClass,
string: JObject) {
string: JObject,
) {
let string: String = env.get_string(JString::from(string)).unwrap().into();
EVENT_QUEUE.lock().unwrap().push(Event::OpenSVG(SVGPath::Resource(string)))
EVENT_QUEUE
.lock()
.unwrap()
.push(Event::OpenSVG(SVGPath::Resource(string)))
}
struct WindowImpl {
@ -202,18 +221,20 @@ impl Window for WindowImpl {
0
}
fn push_user_event(message_type: u32, message_data: u32) {
}
fn push_user_event(message_type: u32, message_data: u32) {}
fn present_open_svg_dialog(&mut self) {
JAVA_ACTIVITY.with(|java_activity| {
let mut java_activity = java_activity.borrow_mut();
let java_activity = java_activity.as_mut().unwrap();
let env = java_activity.vm.get_env().unwrap();
env.call_method(java_activity.activity.as_obj(),
env.call_method(
java_activity.activity.as_obj(),
"presentOpenSVGDialog",
"()V",
&[]).unwrap();
&[],
)
.unwrap();
});
}
@ -232,13 +253,20 @@ impl ResourceLoader for AndroidResourceLoader {
let java_resource_loader = java_resource_loader.as_ref().unwrap();
let loader = java_resource_loader.loader.as_obj();
let env = java_resource_loader.vm.get_env().unwrap();
match env.call_method(loader,
match env
.call_method(
loader,
"slurp",
"(Ljava/lang/String;)Ljava/nio/ByteBuffer;",
&[JValue::Object(*env.new_string(path).unwrap())]).unwrap() {
&[JValue::Object(*env.new_string(path).unwrap())],
)
.unwrap()
{
JValue::Object(object) => {
let byte_buffer = JByteBuffer::from(object);
Ok(Vec::from(env.get_direct_buffer_address(byte_buffer).unwrap()))
Ok(Vec::from(
env.get_direct_buffer_address(byte_buffer).unwrap(),
))
}
_ => panic!("Unexpected return value!"),
}

View File

@ -14,30 +14,47 @@ use crate::GRIDLINE_COUNT;
use pathfinder_gpu::resources::ResourceLoader;
use pathfinder_gpu::{BufferData, BufferTarget, BufferUploadMode, Device, VertexAttrType};
pub struct GroundProgram<D> where D: Device {
pub struct GroundProgram<D>
where
D: Device,
{
pub program: D::Program,
pub transform_uniform: D::Uniform,
pub color_uniform: D::Uniform,
}
impl<D> GroundProgram<D> where D: Device {
impl<D> GroundProgram<D>
where
D: Device,
{
pub fn new(device: &D, resources: &dyn ResourceLoader) -> GroundProgram<D> {
let program = device.create_program(resources, "demo_ground");
let transform_uniform = device.get_uniform(&program, "Transform");
let color_uniform = device.get_uniform(&program, "Color");
GroundProgram { program, transform_uniform, color_uniform }
GroundProgram {
program,
transform_uniform,
color_uniform,
}
}
}
pub struct GroundSolidVertexArray<D> where D: Device {
pub struct GroundSolidVertexArray<D>
where
D: Device,
{
pub vertex_array: D::VertexArray,
}
impl<D> GroundSolidVertexArray<D> where D: Device {
pub fn new(device: &D,
impl<D> GroundSolidVertexArray<D>
where
D: Device,
{
pub fn new(
device: &D,
ground_program: &GroundProgram<D>,
quad_vertex_positions_buffer: &D::Buffer)
-> GroundSolidVertexArray<D> {
quad_vertex_positions_buffer: &D::Buffer,
) -> GroundSolidVertexArray<D> {
let vertex_array = device.create_vertex_array();
let position_attr = device.get_vertex_attr(&ground_program.program, "Position");
@ -51,19 +68,27 @@ impl<D> GroundSolidVertexArray<D> where D: Device {
}
}
pub struct GroundLineVertexArray<D> where D: Device {
pub struct GroundLineVertexArray<D>
where
D: Device,
{
pub vertex_array: D::VertexArray,
#[allow(dead_code)]
grid_vertex_positions_buffer: D::Buffer,
}
impl<D> GroundLineVertexArray<D> where D: Device {
impl<D> GroundLineVertexArray<D>
where
D: Device,
{
pub fn new(device: &D, ground_program: &GroundProgram<D>) -> GroundLineVertexArray<D> {
let grid_vertex_positions_buffer = device.create_buffer();
device.allocate_buffer(&grid_vertex_positions_buffer,
device.allocate_buffer(
&grid_vertex_positions_buffer,
BufferData::Memory(&create_grid_vertex_positions()),
BufferTarget::Vertex,
BufferUploadMode::Static);
BufferUploadMode::Static,
);
let vertex_array = device.create_vertex_array();
@ -74,7 +99,10 @@ impl<D> GroundLineVertexArray<D> where D: Device {
device.bind_buffer(&grid_vertex_positions_buffer, BufferTarget::Vertex);
device.configure_float_vertex_attr(&position_attr, 2, VertexAttrType::U8, false, 0, 0, 0);
GroundLineVertexArray { vertex_array, grid_vertex_positions_buffer }
GroundLineVertexArray {
vertex_array,
grid_vertex_positions_buffer,
}
}
}
@ -82,8 +110,10 @@ fn create_grid_vertex_positions() -> Vec<(u8, u8)> {
let mut positions = vec![];
for index in 0..(GRIDLINE_COUNT + 1) {
positions.extend_from_slice(&[
(0, index), (GRIDLINE_COUNT, index),
(index, 0), (index, GRIDLINE_COUNT),
(0, index),
(GRIDLINE_COUNT, index),
(index, 0),
(index, GRIDLINE_COUNT),
]);
}
positions

View File

@ -60,12 +60,37 @@ const CAMERA_ZOOM_AMOUNT_2D: f32 = 0.1;
const NEAR_CLIP_PLANE: f32 = 0.01;
const FAR_CLIP_PLANE: f32 = 10.0;
const LIGHT_BG_COLOR: ColorU = ColorU { r: 248, g: 248, b: 248, a: 255 };
const DARK_BG_COLOR: ColorU = ColorU { r: 32, g: 32, b: 32, a: 255 };
const TRANSPARENT_BG_COLOR: ColorU = ColorU { r: 0, g: 0, b: 0, a: 0 };
const LIGHT_BG_COLOR: ColorU = ColorU {
r: 248,
g: 248,
b: 248,
a: 255,
};
const DARK_BG_COLOR: ColorU = ColorU {
r: 32,
g: 32,
b: 32,
a: 255,
};
const TRANSPARENT_BG_COLOR: ColorU = ColorU {
r: 0,
g: 0,
b: 0,
a: 0,
};
const GROUND_SOLID_COLOR: ColorU = ColorU { r: 80, g: 80, b: 80, a: 255 };
const GROUND_LINE_COLOR: ColorU = ColorU { r: 127, g: 127, b: 127, a: 255 };
const GROUND_SOLID_COLOR: ColorU = ColorU {
r: 80,
g: 80,
b: 80,
a: 255,
};
const GROUND_LINE_COLOR: ColorU = ColorU {
r: 127,
g: 127,
b: 127,
a: 255,
};
const APPROX_FONT_SIZE: f32 = 16.0;
@ -83,7 +108,10 @@ pub mod window;
mod device;
mod ui;
pub struct DemoApp<W> where W: Window {
pub struct DemoApp<W>
where
W: Window,
{
pub window: W,
pub should_exit: bool,
pub options: Options,
@ -115,7 +143,10 @@ pub struct DemoApp<W> where W: Window {
ground_line_vertex_array: GroundLineVertexArray<GLDevice>,
}
impl<W> DemoApp<W> where W: Window {
impl<W> DemoApp<W>
where
W: Window,
{
pub fn new(window: W, window_size: WindowSize, mut options: Options) -> DemoApp<W> {
let expire_message_event_id = window.create_user_event_id();
@ -148,16 +179,22 @@ impl<W> DemoApp<W> where W: Window {
let camera = Camera::new(options.mode, scene_view_box, viewport.size());
let ground_program = GroundProgram::new(&renderer.device, resources);
let ground_solid_vertex_array =
GroundSolidVertexArray::new(&renderer.device,
let ground_solid_vertex_array = GroundSolidVertexArray::new(
&renderer.device,
&ground_program,
&renderer.quad_vertex_positions_buffer());
let ground_line_vertex_array = GroundLineVertexArray::new(&renderer.device,
&ground_program);
&renderer.quad_vertex_positions_buffer(),
);
let ground_line_vertex_array =
GroundLineVertexArray::new(&renderer.device, &ground_program);
let mut ui = DemoUI::new(&renderer.device, resources, options.clone());
let mut message_epoch = 0;
emit_message::<W>(&mut ui, &mut message_epoch, expire_message_event_id, message);
emit_message::<W>(
&mut ui,
&mut message_epoch,
expire_message_event_id,
message,
);
DemoApp {
window,
@ -218,28 +255,30 @@ impl<W> DemoApp<W> where W: Window {
let scene_count = match self.camera.mode() {
Mode::VR => {
let viewport = self.window.viewport(View::Stereo(0));
if self.scene_framebuffer.is_none() ||
self.renderer
if self.scene_framebuffer.is_none()
|| self.renderer.device.texture_size(
&self
.renderer
.device
.texture_size(&self.renderer
.framebuffer_texture(self.scene_framebuffer.as_ref().unwrap()),
) != viewport.size()
{
let scene_texture = self
.renderer
.device
.framebuffer_texture(self.scene_framebuffer
.as_ref()
.unwrap())) !=
viewport.size() {
let scene_texture = self.renderer.device.create_texture(TextureFormat::RGBA8,
viewport.size());
.create_texture(TextureFormat::RGBA8, viewport.size());
self.scene_framebuffer =
Some(self.renderer.device.create_framebuffer(scene_texture));
}
self.renderer
.replace_dest_framebuffer(DestFramebuffer::Other(self.scene_framebuffer
.take()
.unwrap()));
.replace_dest_framebuffer(DestFramebuffer::Other(
self.scene_framebuffer.take().unwrap(),
));
2
}
_ => {
self.renderer.replace_dest_framebuffer(DestFramebuffer::Default {
self.renderer
.replace_dest_framebuffer(DestFramebuffer::Default {
viewport: self.window.viewport(View::Mono),
window_size,
});
@ -277,7 +316,8 @@ impl<W> DemoApp<W> where W: Window {
if modelview_transform.offset(*velocity) {
self.dirty = true;
}
let perspective = scene_transform.perspective
let perspective = scene_transform
.perspective
.post_mul(&scene_transform.modelview_to_eye)
.post_mul(&modelview_transform.to_transform());
RenderTransform::Perspective(perspective)
@ -285,7 +325,9 @@ impl<W> DemoApp<W> where W: Window {
Camera::TwoD(transform) => RenderTransform::Transform2D(transform),
};
self.scene_thread_proxy.sender.send(MainToSceneMsg::Build(BuildOptions {
self.scene_thread_proxy
.sender
.send(MainToSceneMsg::Build(BuildOptions {
render_transform,
stem_darkening_font_size: if self.ui.stem_darkening_effect_enabled {
Some(APPROX_FONT_SIZE * self.window_size.backing_scale_factor)
@ -293,7 +335,8 @@ impl<W> DemoApp<W> where W: Window {
None
},
subpixel_aa_enabled: self.ui.subpixel_aa_effect_enabled,
})).unwrap();
}))
.unwrap();
}
fn handle_events(&mut self, events: Vec<Event>) -> Vec<UIEvent> {
@ -302,8 +345,7 @@ impl<W> DemoApp<W> where W: Window {
for event in events {
match event {
Event::Quit { .. } |
Event::KeyDown(Keycode::Escape) => {
Event::Quit { .. } | Event::KeyDown(Keycode::Escape) => {
self.should_exit = true;
self.dirty = true;
}
@ -311,7 +353,8 @@ impl<W> DemoApp<W> where W: Window {
self.window_size = new_size;
let viewport = self.window.viewport(self.ui.mode.view(0));
self.scene_thread_proxy.set_drawable_size(viewport.size());
self.renderer.set_main_framebuffer_size(self.window_size.device_size());
self.renderer
.set_main_framebuffer_size(self.window_size.device_size());
self.dirty = true;
}
Event::MouseDown(new_position) => {
@ -320,8 +363,13 @@ impl<W> DemoApp<W> where W: Window {
}
Event::MouseMoved(new_position) if self.mouselook_enabled => {
let mouse_position = self.process_mouse_position(new_position);
if let Camera::ThreeD { ref mut modelview_transform, .. } = self.camera {
let rotation = mouse_position.relative
if let Camera::ThreeD {
ref mut modelview_transform,
..
} = self.camera
{
let rotation = mouse_position
.relative
.to_f32()
.scale(MOUSELOOK_ROTATION_SPEED);
modelview_transform.yaw += rotation.x();
@ -345,54 +393,80 @@ impl<W> DemoApp<W> where W: Window {
}
}
Event::Look { pitch, yaw } => {
if let Camera::ThreeD { ref mut modelview_transform, .. } = self.camera {
if let Camera::ThreeD {
ref mut modelview_transform,
..
} = self.camera
{
modelview_transform.pitch += pitch;
modelview_transform.yaw += yaw;
}
}
Event::SetEyeTransforms(new_eye_transforms) => {
if let Camera::ThreeD { ref mut eye_transforms, .. } = self.camera {
if let Camera::ThreeD {
ref mut eye_transforms,
..
} = self.camera
{
*eye_transforms = new_eye_transforms;
}
}
Event::KeyDown(Keycode::Alphanumeric(b'w')) => {
if let Camera::ThreeD { ref mut velocity, .. } = self.camera {
if let Camera::ThreeD {
ref mut velocity, ..
} = self.camera
{
let scale_factor = scale_factor_for_view_box(self.scene_view_box);
velocity.set_z(-CAMERA_VELOCITY / scale_factor);
self.dirty = true;
}
}
Event::KeyDown(Keycode::Alphanumeric(b's')) => {
if let Camera::ThreeD { ref mut velocity, .. } = self.camera {
if let Camera::ThreeD {
ref mut velocity, ..
} = self.camera
{
let scale_factor = scale_factor_for_view_box(self.scene_view_box);
velocity.set_z(CAMERA_VELOCITY / scale_factor);
self.dirty = true;
}
}
Event::KeyDown(Keycode::Alphanumeric(b'a')) => {
if let Camera::ThreeD { ref mut velocity, .. } = self.camera {
if let Camera::ThreeD {
ref mut velocity, ..
} = self.camera
{
let scale_factor = scale_factor_for_view_box(self.scene_view_box);
velocity.set_x(-CAMERA_VELOCITY / scale_factor);
self.dirty = true;
}
}
Event::KeyDown(Keycode::Alphanumeric(b'd')) => {
if let Camera::ThreeD { ref mut velocity, .. } = self.camera {
if let Camera::ThreeD {
ref mut velocity, ..
} = self.camera
{
let scale_factor = scale_factor_for_view_box(self.scene_view_box);
velocity.set_x(CAMERA_VELOCITY / scale_factor);
self.dirty = true;
}
}
Event::KeyUp(Keycode::Alphanumeric(b'w')) |
Event::KeyUp(Keycode::Alphanumeric(b's')) => {
if let Camera::ThreeD { ref mut velocity, .. } = self.camera {
Event::KeyUp(Keycode::Alphanumeric(b'w'))
| Event::KeyUp(Keycode::Alphanumeric(b's')) => {
if let Camera::ThreeD {
ref mut velocity, ..
} = self.camera
{
velocity.set_z(0.0);
self.dirty = true;
}
}
Event::KeyUp(Keycode::Alphanumeric(b'a')) |
Event::KeyUp(Keycode::Alphanumeric(b'd')) => {
if let Camera::ThreeD { ref mut velocity, .. } = self.camera {
Event::KeyUp(Keycode::Alphanumeric(b'a'))
| Event::KeyUp(Keycode::Alphanumeric(b'd')) => {
if let Camera::ThreeD {
ref mut velocity, ..
} = self.camera
{
velocity.set_x(0.0);
self.dirty = true;
}
@ -412,12 +486,16 @@ impl<W> DemoApp<W> where W: Window {
self.scene_view_box = built_svg.scene.view_box;
self.monochrome_scene_color = built_svg.scene.monochrome_color();
self.camera = Camera::new(self.ui.mode, self.scene_view_box, viewport_size);
self.scene_thread_proxy.load_scene(built_svg.scene, viewport_size);
self.scene_thread_proxy
.load_scene(built_svg.scene, viewport_size);
self.dirty = true;
}
Event::User { message_type: event_id, message_data: expected_epoch } if
event_id == self.expire_message_event_id &&
expected_epoch as u32 == self.message_epoch => {
Event::User {
message_type: event_id,
message_data: expected_epoch,
} if event_id == self.expire_message_event_id
&& expected_epoch as u32 == self.message_epoch =>
{
self.ui.message = String::new();
self.dirty = true;
}
@ -451,10 +529,12 @@ impl<W> DemoApp<W> where W: Window {
}
if let DestFramebuffer::Other(scene_framebuffer) =
self.renderer.replace_dest_framebuffer(DestFramebuffer::Default {
self.renderer
.replace_dest_framebuffer(DestFramebuffer::Default {
viewport: self.window.viewport(View::Mono),
window_size: self.window_size.device_size(),
}) {
})
{
self.scene_framebuffer = Some(scene_framebuffer);
}
}
@ -466,18 +546,23 @@ impl<W> DemoApp<W> where W: Window {
ref scene_transform,
ref modelview_transform,
..
} if eye_transforms.len() > 1 => {
(eye_transforms, scene_transform, modelview_transform)
}
} if eye_transforms.len() > 1 => (eye_transforms, scene_transform, modelview_transform),
_ => return,
};
debug!("scene_transform.perspective={:?}", scene_transform.perspective);
debug!("scene_transform.modelview_to_eye={:?}", scene_transform.modelview_to_eye);
debug!(
"scene_transform.perspective={:?}",
scene_transform.perspective
);
debug!(
"scene_transform.modelview_to_eye={:?}",
scene_transform.modelview_to_eye
);
debug!("modelview transform={:?}", modelview_transform);
let viewport = self.window.viewport(View::Stereo(render_scene_index));
self.renderer.replace_dest_framebuffer(DestFramebuffer::Default {
self.renderer
.replace_dest_framebuffer(DestFramebuffer::Default {
viewport,
window_size: self.window_size.device_size(),
});
@ -495,35 +580,49 @@ impl<W> DemoApp<W> where W: Window {
let scene_framebuffer = self.scene_framebuffer.as_ref().unwrap();
let scene_texture = self.renderer.device.framebuffer_texture(scene_framebuffer);
let quad_scale_transform = Transform3DF32::from_scale(self.scene_view_box.size().x(),
let quad_scale_transform = Transform3DF32::from_scale(
self.scene_view_box.size().x(),
self.scene_view_box.size().y(),
1.0);
1.0,
);
let scene_transform_matrix = scene_transform.perspective
let scene_transform_matrix = scene_transform
.perspective
.post_mul(&scene_transform.modelview_to_eye)
.post_mul(&modelview_transform.to_transform())
.post_mul(&quad_scale_transform);
let eye_transform = &eye_transforms[render_scene_index as usize];
let eye_transform_matrix = eye_transform.perspective
let eye_transform_matrix = eye_transform
.perspective
.post_mul(&eye_transform.modelview_to_eye)
.post_mul(&modelview_transform.to_transform())
.post_mul(&quad_scale_transform);
debug!("eye transform({}).modelview_to_eye={:?}",
render_scene_index,
eye_transform.modelview_to_eye);
debug!("eye transform_matrix({})={:?}", render_scene_index, eye_transform_matrix);
debug!(
"eye transform({}).modelview_to_eye={:?}",
render_scene_index, eye_transform.modelview_to_eye
);
debug!(
"eye transform_matrix({})={:?}",
render_scene_index, eye_transform_matrix
);
debug!("---");
self.renderer.reproject_texture(scene_texture,
self.renderer.reproject_texture(
scene_texture,
&scene_transform_matrix.transform,
&eye_transform_matrix.transform);
&eye_transform_matrix.transform,
);
}
pub fn finish_drawing_frame(&mut self) {
if let Some(rendering_time) = self.renderer.shift_timer_query() {
self.current_frame.as_mut().unwrap().scene_rendering_times.push(rendering_time);
self.current_frame
.as_mut()
.unwrap()
.scene_rendering_times
.push(rendering_time);
}
let tile_time = match self.scene_thread_proxy.receiver.recv().unwrap() {
@ -544,15 +643,23 @@ impl<W> DemoApp<W> where W: Window {
None
} else {
let zero = Duration::new(0, 0);
Some(frame.scene_rendering_times.iter().fold(zero, |sum, item| sum + *item))
Some(
frame
.scene_rendering_times
.iter()
.fold(zero, |sum, item| sum + *item),
)
};
self.renderer.debug_ui.add_sample(aggregate_stats, tile_time, total_rendering_time);
self.renderer
.debug_ui
.add_sample(aggregate_stats, tile_time, total_rendering_time);
}
if self.options.ui != UIVisibility::None {
let viewport = self.window.viewport(View::Mono);
self.window.make_current(View::Mono);
self.renderer.replace_dest_framebuffer(DestFramebuffer::Default {
self.renderer
.replace_dest_framebuffer(DestFramebuffer::Default {
viewport,
window_size: self.window_size.device_size(),
});
@ -564,16 +671,20 @@ impl<W> DemoApp<W> where W: Window {
self.renderer.debug_ui.ui.event_queue.push(*ui_event);
}
self.renderer.debug_ui.ui.mouse_position =
self.last_mouse_position.to_f32().scale(self.window_size.backing_scale_factor);
self.renderer.debug_ui.ui.mouse_position = self
.last_mouse_position
.to_f32()
.scale(self.window_size.backing_scale_factor);
self.ui.show_text_effects = self.monochrome_scene_color.is_some();
let mut ui_action = UIAction::None;
if self.options.ui == UIVisibility::All {
self.ui.update(&self.renderer.device,
self.ui.update(
&self.renderer.device,
&mut self.window,
&mut self.renderer.debug_ui,
&mut ui_action);
&mut ui_action,
);
}
frame.ui_events = self.renderer.debug_ui.ui.event_queue.drain();
self.handle_ui_action(&mut ui_action);
@ -625,26 +736,36 @@ impl<W> DemoApp<W> where W: Window {
base_transform = base_transform.post_mul(&Transform3DF32::from_translation(
-0.5 * self.scene_view_box.max_x(),
self.scene_view_box.max_y(),
-0.5 * ground_scale));
-0.5 * ground_scale,
));
// Draw gridlines. Use the stencil buffer to avoid Z-fighting.
let mut transform = base_transform;
let gridline_scale = ground_scale / GRIDLINE_COUNT as f32;
transform =
transform.post_mul(&Transform3DF32::from_scale(gridline_scale, 1.0, gridline_scale));
transform = transform.post_mul(&Transform3DF32::from_scale(
gridline_scale,
1.0,
gridline_scale,
));
let device = &self.renderer.device;
device.bind_vertex_array(&self.ground_line_vertex_array.vertex_array);
device.use_program(&self.ground_program.program);
device.set_uniform(&self.ground_program.transform_uniform, UniformData::Mat4([
transform.c0,
transform.c1,
transform.c2,
transform.c3,
]));
device.set_uniform(&self.ground_program.color_uniform,
UniformData::Vec4(GROUND_LINE_COLOR.to_f32().0));
device.draw_arrays(Primitive::Lines, (GRIDLINE_COUNT as u32 + 1) * 4, &RenderState {
depth: Some(DepthState { func: DepthFunc::Always, write: true }),
device.set_uniform(
&self.ground_program.transform_uniform,
UniformData::Mat4([transform.c0, transform.c1, transform.c2, transform.c3]),
);
device.set_uniform(
&self.ground_program.color_uniform,
UniformData::Vec4(GROUND_LINE_COLOR.to_f32().0),
);
device.draw_arrays(
Primitive::Lines,
(GRIDLINE_COUNT as u32 + 1) * 4,
&RenderState {
depth: Some(DepthState {
func: DepthFunc::Always,
write: true,
}),
stencil: Some(StencilState {
func: StencilFunc::Always,
reference: 2,
@ -652,7 +773,8 @@ impl<W> DemoApp<W> where W: Window {
write: true,
}),
..RenderState::default()
});
},
);
// Fill ground.
let mut transform = base_transform;
@ -660,12 +782,22 @@ impl<W> DemoApp<W> where W: Window {
transform.post_mul(&Transform3DF32::from_scale(ground_scale, 1.0, ground_scale));
device.bind_vertex_array(&self.ground_solid_vertex_array.vertex_array);
device.use_program(&self.ground_program.program);
device.set_uniform(&self.ground_program.transform_uniform,
UniformData::from_transform_3d(&transform));
device.set_uniform(&self.ground_program.color_uniform,
UniformData::Vec4(GROUND_SOLID_COLOR.to_f32().0));
device.draw_arrays(Primitive::TriangleFan, 4, &RenderState {
depth: Some(DepthState { func: DepthFunc::Less, write: true }),
device.set_uniform(
&self.ground_program.transform_uniform,
UniformData::from_transform_3d(&transform),
);
device.set_uniform(
&self.ground_program.color_uniform,
UniformData::Vec4(GROUND_SOLID_COLOR.to_f32().0),
);
device.draw_arrays(
Primitive::TriangleFan,
4,
&RenderState {
depth: Some(DepthState {
func: DepthFunc::Less,
write: true,
}),
stencil: Some(StencilState {
func: StencilFunc::NotEqual,
reference: 2,
@ -673,7 +805,8 @@ impl<W> DemoApp<W> where W: Window {
write: false,
}),
..RenderState::default()
});
},
);
}
fn render_vector_scene(&mut self) {
@ -694,7 +827,7 @@ impl<W> DemoApp<W> where W: Window {
Some(DEFRINGING_KERNEL_CORE_GRAPHICS)
} else {
None
}
},
})
}
}
@ -715,7 +848,11 @@ impl<W> DemoApp<W> where W: Window {
}
}
self.current_frame.as_mut().unwrap().scene_stats.push(self.renderer.stats);
self.current_frame
.as_mut()
.unwrap()
.scene_stats
.push(self.renderer.stats);
self.renderer.end_scene();
}
@ -731,7 +868,8 @@ impl<W> DemoApp<W> where W: Window {
if let Camera::TwoD(ref mut transform) = self.camera {
let scale = Point2DF32::splat(1.0 + CAMERA_ZOOM_AMOUNT_2D);
let center = center_of_window(&self.window_size);
*transform = transform.post_translate(-center)
*transform = transform
.post_translate(-center)
.post_scale(scale)
.post_translate(center);
self.dirty = true;
@ -741,7 +879,8 @@ impl<W> DemoApp<W> where W: Window {
if let Camera::TwoD(ref mut transform) = self.camera {
let scale = Point2DF32::splat(1.0 - CAMERA_ZOOM_AMOUNT_2D);
let center = center_of_window(&self.window_size);
*transform = transform.post_translate(-center)
*transform = transform
.post_translate(-center)
.post_scale(scale)
.post_translate(center);
self.dirty = true;
@ -751,7 +890,8 @@ impl<W> DemoApp<W> where W: Window {
if let Camera::TwoD(ref mut transform) = self.camera {
let old_rotation = transform.rotation();
let center = center_of_window(&self.window_size);
*transform = transform.post_translate(-center)
*transform = transform
.post_translate(-center)
.post_rotate(*theta - old_rotation)
.post_translate(center);
}
@ -762,12 +902,18 @@ impl<W> DemoApp<W> where W: Window {
fn take_screenshot(&mut self) {
let screenshot_path = self.pending_screenshot_path.take().unwrap();
let drawable_size = self.window_size.device_size();
let pixels = self.renderer.device.read_pixels_from_default_framebuffer(drawable_size);
image::save_buffer(screenshot_path,
let pixels = self
.renderer
.device
.read_pixels_from_default_framebuffer(drawable_size);
image::save_buffer(
screenshot_path,
&pixels,
drawable_size.x() as u32,
drawable_size.y() as u32,
ColorType::RGBA(8)).unwrap();
ColorType::RGBA(8),
)
.unwrap();
}
fn background_color(&self) -> ColorU {
@ -790,15 +936,25 @@ impl SceneThreadProxy {
let (scene_to_main_sender, scene_to_main_receiver) =
mpsc::sync_channel(MAX_MESSAGES_IN_FLIGHT);
SceneThread::new(scene, scene_to_main_sender, main_to_scene_receiver, options);
SceneThreadProxy { sender: main_to_scene_sender, receiver: scene_to_main_receiver }
SceneThreadProxy {
sender: main_to_scene_sender,
receiver: scene_to_main_receiver,
}
}
fn load_scene(&self, scene: Scene, view_box_size: Point2DI32) {
self.sender.send(MainToSceneMsg::LoadScene { scene, view_box_size }).unwrap();
self.sender
.send(MainToSceneMsg::LoadScene {
scene,
view_box_size,
})
.unwrap();
}
fn set_drawable_size(&self, drawable_size: Point2DI32) {
self.sender.send(MainToSceneMsg::SetDrawableSize(drawable_size)).unwrap();
self.sender
.send(MainToSceneMsg::SetDrawableSize(drawable_size))
.unwrap();
}
}
@ -810,32 +966,54 @@ struct SceneThread {
}
impl SceneThread {
fn new(scene: Scene,
fn new(
scene: Scene,
sender: SyncSender<SceneToMainMsg>,
receiver: Receiver<MainToSceneMsg>,
options: Options) {
thread::spawn(move || (SceneThread { scene, sender, receiver, options }).run());
options: Options,
) {
thread::spawn(move || {
(SceneThread {
scene,
sender,
receiver,
options,
})
.run()
});
}
fn run(mut self) {
while let Ok(msg) = self.receiver.recv() {
match msg {
MainToSceneMsg::LoadScene { scene, view_box_size } => {
MainToSceneMsg::LoadScene {
scene,
view_box_size,
} => {
self.scene = scene;
self.scene.view_box = RectF32::new(Point2DF32::default(),
view_box_size.to_f32());
self.scene.view_box =
RectF32::new(Point2DF32::default(), view_box_size.to_f32());
}
MainToSceneMsg::SetDrawableSize(size) => {
self.scene.view_box = RectF32::new(Point2DF32::default(), size.to_f32());
}
MainToSceneMsg::Build(build_options) => {
self.sender.send(SceneToMainMsg::BeginFrame {
self.sender
.send(SceneToMainMsg::BeginFrame {
transform: build_options.render_transform.clone(),
}).unwrap();
})
.unwrap();
let start_time = Instant::now();
build_scene(&self.scene, &build_options, self.options.jobs, &mut self.sender);
build_scene(
&self.scene,
&build_options,
self.options.jobs,
&mut self.sender,
);
let tile_time = Instant::now() - start_time;
self.sender.send(SceneToMainMsg::EndFrame { tile_time }).unwrap();
self.sender
.send(SceneToMainMsg::EndFrame { tile_time })
.unwrap();
}
}
}
@ -844,7 +1022,10 @@ impl SceneThread {
#[derive(Clone)]
enum MainToSceneMsg {
LoadScene { scene: Scene, view_box_size: Point2DI32 },
LoadScene {
scene: Scene,
view_box_size: Point2DI32,
},
SetDrawableSize(Point2DI32),
Build(BuildOptions),
}
@ -877,10 +1058,12 @@ impl Debug for SceneToMainMsg {
}
}
fn build_scene(scene: &Scene,
fn build_scene(
scene: &Scene,
build_options: &BuildOptions,
jobs: Option<usize>,
sink: &mut SyncSender<SceneToMainMsg>) {
sink: &mut SyncSender<SceneToMainMsg>,
) {
let render_options = RenderOptions {
transform: build_options.render_transform.clone(),
dilation: match build_options.stem_darkening_font_size {
@ -894,14 +1077,16 @@ fn build_scene(scene: &Scene,
};
let built_options = render_options.prepare(scene.bounds);
sink.send(SceneToMainMsg::BeginRenderScene(scene.build_descriptor(&built_options))).unwrap();
sink.send(SceneToMainMsg::BeginRenderScene(
scene.build_descriptor(&built_options),
))
.unwrap();
let inner_sink = AssertUnwindSafe(sink.clone());
let result = panic::catch_unwind(move || {
let sink = (*inner_sink).clone();
let listener = Box::new(move |command| {
sink.send(SceneToMainMsg::Execute(command)).unwrap()
});
let listener =
Box::new(move |command| sink.send(SceneToMainMsg::Execute(command)).unwrap());
let mut scene_builder = SceneBuilder::new(scene, &built_options, listener);
match jobs {
@ -953,8 +1138,20 @@ impl Options {
.takes_value(true)
.help("Number of threads to use"),
)
.arg(Arg::with_name("3d").short("3").long("3d").help("Run in 3D").conflicts_with("vr"))
.arg(Arg::with_name("vr").short("V").long("vr").help("Run in VR").conflicts_with("3d"))
.arg(
Arg::with_name("3d")
.short("3")
.long("3d")
.help("Run in 3D")
.conflicts_with("vr"),
)
.arg(
Arg::with_name("vr")
.short("V")
.long("vr")
.help("Run in VR")
.conflicts_with("3d"),
)
.arg(
Arg::with_name("ui")
.short("u")
@ -971,7 +1168,11 @@ impl Options {
.possible_values(&["light", "dark", "transparent"])
.help("The background color to use"),
)
.arg(Arg::with_name("INPUT").help("Path to the SVG file to render").index(1))
.arg(
Arg::with_name("INPUT")
.help("Path to the SVG file to render")
.index(1),
)
.get_matches();
if let Some(jobs) = matches.value_of("jobs") {
@ -1005,8 +1206,10 @@ impl Options {
};
}
fn adjust_thread_pool_settings(&self, mut thread_pool_builder: ThreadPoolBuilder)
-> ThreadPoolBuilder {
fn adjust_thread_pool_settings(
&self,
mut thread_pool_builder: ThreadPoolBuilder,
) -> ThreadPoolBuilder {
if let Some(jobs) = self.jobs {
thread_pool_builder = thread_pool_builder.num_threads(jobs);
}
@ -1023,11 +1226,17 @@ pub enum Mode {
impl Mode {
pub fn viewport_count(self) -> usize {
match self { Mode::TwoD | Mode::ThreeD => 1, Mode::VR => 2 }
match self {
Mode::TwoD | Mode::ThreeD => 1,
Mode::VR => 2,
}
}
pub fn view(self, viewport: u32) -> View {
match self { Mode::TwoD | Mode::ThreeD => View::Mono, Mode::VR => View::Stereo(viewport) }
match self {
Mode::TwoD | Mode::ThreeD => View::Mono,
Mode::VR => View::Stereo(viewport),
}
}
}
@ -1083,8 +1292,8 @@ impl Camera {
}
fn new_2d(view_box: RectF32, viewport_size: Point2DI32) -> Camera {
let scale = i32::min(viewport_size.x(), viewport_size.y()) as f32 *
scale_factor_for_view_box(view_box);
let scale = i32::min(viewport_size.x(), viewport_size.y()) as f32
* scale_factor_for_view_box(view_box);
let origin = viewport_size.to_f32().scale(0.5) - view_box.size().scale(scale * 0.5);
Camera::TwoD(Transform2DF32::from_scale(&Point2DF32::splat(scale)).post_translate(origin))
}
@ -1094,10 +1303,8 @@ impl Camera {
let fov_y = FRAC_PI_4;
let aspect = viewport_size.x() as f32 / viewport_size.y() as f32;
let projection = Transform3DF32::from_perspective(fov_y,
aspect,
NEAR_CLIP_PLANE,
FAR_CLIP_PLANE);
let projection =
Transform3DF32::from_perspective(fov_y, aspect, NEAR_CLIP_PLANE, FAR_CLIP_PLANE);
let perspective = Perspective::new(&projection, viewport_size);
// Create a scene transform by moving the camera back from the center of the eyes so that
@ -1110,13 +1317,19 @@ impl Camera {
// For now, initialize the eye transforms as copies of the scene transform.
let eye_offset = DEFAULT_EYE_OFFSET;
let eye_transforms = (0..viewport_count).map(|viewport_index| {
let this_eye_offset = if viewport_index == 0 { eye_offset } else { -eye_offset };
let eye_transforms = (0..viewport_count)
.map(|viewport_index| {
let this_eye_offset = if viewport_index == 0 {
eye_offset
} else {
-eye_offset
};
OcularTransform {
perspective,
modelview_to_eye: Transform3DF32::from_translation(this_eye_offset, 0.0, 0.0),
}
}).collect();
})
.collect();
Camera::ThreeD {
scene_transform,
@ -1127,12 +1340,17 @@ impl Camera {
}
fn is_3d(&self) -> bool {
match *self { Camera::ThreeD { .. } => true, Camera::TwoD { .. } => false }
match *self {
Camera::ThreeD { .. } => true,
Camera::TwoD { .. } => false,
}
}
fn mode(&self) -> Mode {
match *self {
Camera::ThreeD { ref eye_transforms, .. } if eye_transforms.len() >= 2 => Mode::VR,
Camera::ThreeD {
ref eye_transforms, ..
} if eye_transforms.len() >= 2 => Mode::VR,
Camera::ThreeD { .. } => Mode::ThreeD,
Camera::TwoD { .. } => Mode::TwoD,
}
@ -1151,10 +1369,12 @@ impl CameraTransform3D {
fn new(view_box: RectF32) -> CameraTransform3D {
let scale = scale_factor_for_view_box(view_box);
CameraTransform3D {
position: Point3DF32::new(0.5 * view_box.max_x(),
position: Point3DF32::new(
0.5 * view_box.max_x(),
-0.5 * view_box.max_y(),
1.5 / scale,
1.0),
1.0,
),
yaw: 0.0,
pitch: 0.0,
scale,
@ -1173,9 +1393,11 @@ impl CameraTransform3D {
fn to_transform(&self) -> Transform3DF32 {
let mut transform = Transform3DF32::from_rotation(self.yaw, self.pitch, 0.0);
transform = transform.post_mul(&Transform3DF32::from_uniform_scale(2.0 * self.scale));
transform = transform.post_mul(&Transform3DF32::from_translation(-self.position.x(),
transform = transform.post_mul(&Transform3DF32::from_translation(
-self.position.x(),
-self.position.y(),
-self.position.z()));
-self.position.z(),
));
// Flip Y.
transform = transform.post_mul(&Transform3DF32::from_scale(1.0, -1.0, 1.0));
@ -1192,14 +1414,20 @@ fn get_svg_building_message(built_svg: &BuiltSVG) -> String {
if built_svg.result_flags.is_empty() {
return String::new();
}
format!("Warning: These features in the SVG are unsupported: {}.", built_svg.result_flags)
format!(
"Warning: These features in the SVG are unsupported: {}.",
built_svg.result_flags
)
}
fn emit_message<W>(ui: &mut DemoUI<GLDevice>,
fn emit_message<W>(
ui: &mut DemoUI<GLDevice>,
message_epoch: &mut u32,
expire_message_event_id: u32,
message: String)
where W: Window {
message: String,
) where
W: Window,
{
if message.is_empty() {
return;
}
@ -1222,7 +1450,12 @@ struct Frame {
impl Frame {
fn new(transform: RenderTransform, ui_events: Vec<UIEvent>) -> Frame {
Frame { transform, ui_events, scene_rendering_times: vec![], scene_stats: vec![] }
Frame {
transform,
ui_events,
scene_rendering_times: vec![],
scene_stats: vec![],
}
}
}

View File

@ -8,12 +8,12 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use crate::{BackgroundColor, Mode, Options};
use crate::window::Window;
use crate::{BackgroundColor, Mode, Options};
use pathfinder_geometry::basic::point::Point2DI32;
use pathfinder_geometry::basic::rect::RectI32;
use pathfinder_gpu::Device;
use pathfinder_gpu::resources::ResourceLoader;
use pathfinder_gpu::Device;
use pathfinder_renderer::gpu::debug::DebugUI;
use pathfinder_ui::{BUTTON_HEIGHT, BUTTON_TEXT_OFFSET, BUTTON_WIDTH, FONT_ASCENT, PADDING};
use pathfinder_ui::{TEXT_COLOR, TOOLTIP_HEIGHT, WINDOW_COLOR};
@ -43,7 +43,10 @@ static ZOOM_OUT_PNG_NAME: &'static str = "demo-zoom-out";
static BACKGROUND_PNG_NAME: &'static str = "demo-background";
static SCREENSHOT_PNG_NAME: &'static str = "demo-screenshot";
pub struct DemoUI<D> where D: Device {
pub struct DemoUI<D>
where
D: Device,
{
effects_texture: D::Texture,
open_texture: D::Texture,
rotate_texture: D::Texture,
@ -57,7 +60,6 @@ pub struct DemoUI<D> where D: Device {
rotate_panel_visible: bool,
// FIXME(pcwalton): Factor the below out into a model class.
pub mode: Mode,
pub background_color: BackgroundColor,
pub gamma_correction_effect_enabled: bool,
@ -68,7 +70,10 @@ pub struct DemoUI<D> where D: Device {
pub show_text_effects: bool,
}
impl<D> DemoUI<D> where D: Device {
impl<D> DemoUI<D>
where
D: Device,
{
pub fn new(device: &D, resources: &dyn ResourceLoader, options: Options) -> DemoUI<D> {
let effects_texture = device.create_texture_from_png(resources, EFFECTS_PNG_NAME);
let open_texture = device.create_texture_from_png(resources, OPEN_PNG_NAME);
@ -106,12 +111,15 @@ impl<D> DemoUI<D> where D: Device {
(self.rotation as f32 / SLIDER_WIDTH as f32 * 2.0 - 1.0) * PI
}
pub fn update<W>(&mut self,
pub fn update<W>(
&mut self,
device: &D,
window: &mut W,
debug_ui: &mut DebugUI<D>,
action: &mut UIAction)
where W: Window {
action: &mut UIAction,
) where
W: Window,
{
// Draw message text.
self.draw_message_text(device, debug_ui);
@ -125,42 +133,59 @@ impl<D> DemoUI<D> where D: Device {
// Draw text effects button.
if self.show_text_effects {
if debug_ui.ui.draw_button(device, position, &self.effects_texture) {
if debug_ui
.ui
.draw_button(device, position, &self.effects_texture)
{
self.effects_panel_visible = !self.effects_panel_visible;
}
if !self.effects_panel_visible {
debug_ui.ui.draw_tooltip(device,
debug_ui.ui.draw_tooltip(
device,
"Text Effects",
RectI32::new(position, button_size));
RectI32::new(position, button_size),
);
}
position += Point2DI32::new(button_size.x() + PADDING, 0);
}
// Draw open button.
if debug_ui.ui.draw_button(device, position, &self.open_texture) {
if debug_ui
.ui
.draw_button(device, position, &self.open_texture)
{
// FIXME(pcwalton): This is not sufficient for Android, where we will need to take in
// the contents of the file.
window.present_open_svg_dialog();
}
debug_ui.ui.draw_tooltip(device, "Open SVG", RectI32::new(position, button_size));
debug_ui
.ui
.draw_tooltip(device, "Open SVG", RectI32::new(position, button_size));
position += Point2DI32::new(BUTTON_WIDTH + PADDING, 0);
// Draw screenshot button.
if debug_ui.ui.draw_button(device, position, &self.screenshot_texture) {
if debug_ui
.ui
.draw_button(device, position, &self.screenshot_texture)
{
// FIXME(pcwalton): This is not sufficient for Android, where we will need to take in
// the contents of the file.
if let Ok(file) = window.run_save_dialog("png") {
*action = UIAction::TakeScreenshot(file);
}
}
debug_ui.ui.draw_tooltip(device, "Take Screenshot", RectI32::new(position, button_size));
debug_ui.ui.draw_tooltip(
device,
"Take Screenshot",
RectI32::new(position, button_size),
);
position += Point2DI32::new(BUTTON_WIDTH + PADDING, 0);
// Draw mode switch.
let new_mode = debug_ui.ui.draw_text_switch(device,
position,
&["2D", "3D", "VR"],
self.mode as u8);
let new_mode =
debug_ui
.ui
.draw_text_switch(device, position, &["2D", "3D", "VR"], self.mode as u8);
if new_mode != self.mode as u8 {
self.mode = match new_mode {
0 => Mode::TwoD,
@ -172,19 +197,26 @@ impl<D> DemoUI<D> where D: Device {
let mode_switch_width = debug_ui.ui.measure_switch(3);
let mode_switch_size = Point2DI32::new(mode_switch_width, BUTTON_HEIGHT);
debug_ui.ui.draw_tooltip(device,
debug_ui.ui.draw_tooltip(
device,
"2D/3D/VR Mode",
RectI32::new(position, mode_switch_size));
RectI32::new(position, mode_switch_size),
);
position += Point2DI32::new(mode_switch_width + PADDING, 0);
// Draw background switch.
if debug_ui.ui.draw_button(device, position, &self.background_texture) {
if debug_ui
.ui
.draw_button(device, position, &self.background_texture)
{
self.background_panel_visible = !self.background_panel_visible;
}
if !self.background_panel_visible {
debug_ui.ui.draw_tooltip(device,
debug_ui.ui.draw_tooltip(
device,
"Background Color",
RectI32::new(position, button_size));
RectI32::new(position, button_size),
);
}
// Draw background panel, if necessary.
@ -199,25 +231,40 @@ impl<D> DemoUI<D> where D: Device {
return;
}
if debug_ui.ui.draw_button(device, position, &self.rotate_texture) {
if debug_ui
.ui
.draw_button(device, position, &self.rotate_texture)
{
self.rotate_panel_visible = !self.rotate_panel_visible;
}
if !self.rotate_panel_visible {
debug_ui.ui.draw_tooltip(device, "Rotate", RectI32::new(position, button_size));
debug_ui
.ui
.draw_tooltip(device, "Rotate", RectI32::new(position, button_size));
}
self.draw_rotate_panel(device, debug_ui, position.x(), action);
position += Point2DI32::new(BUTTON_WIDTH + PADDING, 0);
if debug_ui.ui.draw_button(device, position, &self.zoom_in_texture) {
if debug_ui
.ui
.draw_button(device, position, &self.zoom_in_texture)
{
*action = UIAction::ZoomIn;
}
debug_ui.ui.draw_tooltip(device, "Zoom In", RectI32::new(position, button_size));
debug_ui
.ui
.draw_tooltip(device, "Zoom In", RectI32::new(position, button_size));
position += Point2DI32::new(BUTTON_WIDTH + PADDING, 0);
if debug_ui.ui.draw_button(device, position, &self.zoom_out_texture) {
if debug_ui
.ui
.draw_button(device, position, &self.zoom_out_texture)
{
*action = UIAction::ZoomOut;
}
debug_ui.ui.draw_tooltip(device, "Zoom Out", RectI32::new(position, button_size));
debug_ui
.ui
.draw_tooltip(device, "Zoom Out", RectI32::new(position, button_size));
position += Point2DI32::new(BUTTON_WIDTH + PADDING, 0);
}
@ -229,13 +276,17 @@ impl<D> DemoUI<D> where D: Device {
let message_size = debug_ui.ui.measure_text(&self.message);
let window_origin = Point2DI32::new(PADDING, PADDING);
let window_size = Point2DI32::new(PADDING * 2 + message_size, TOOLTIP_HEIGHT);
debug_ui.ui.draw_solid_rounded_rect(device,
debug_ui.ui.draw_solid_rounded_rect(
device,
RectI32::new(window_origin, window_size),
WINDOW_COLOR);
debug_ui.ui.draw_text(device,
WINDOW_COLOR,
);
debug_ui.ui.draw_text(
device,
&self.message,
window_origin + Point2DI32::new(PADDING, PADDING + FONT_ASCENT),
false);
false,
);
}
fn draw_effects_panel(&mut self, device: &D, debug_ui: &mut DebugUI<D>) {
@ -245,40 +296,48 @@ impl<D> DemoUI<D> where D: Device {
let bottom = debug_ui.ui.framebuffer_size().y() - PADDING;
let effects_panel_y = bottom - (BUTTON_HEIGHT + PADDING + EFFECTS_PANEL_HEIGHT);
debug_ui.ui.draw_solid_rounded_rect(device,
RectI32::new(Point2DI32::new(PADDING, effects_panel_y),
Point2DI32::new(EFFECTS_PANEL_WIDTH,
EFFECTS_PANEL_HEIGHT)),
WINDOW_COLOR);
debug_ui.ui.draw_solid_rounded_rect(
device,
RectI32::new(
Point2DI32::new(PADDING, effects_panel_y),
Point2DI32::new(EFFECTS_PANEL_WIDTH, EFFECTS_PANEL_HEIGHT),
),
WINDOW_COLOR,
);
self.gamma_correction_effect_enabled =
self.draw_effects_switch(device,
self.gamma_correction_effect_enabled = self.draw_effects_switch(
device,
debug_ui,
"Gamma Correction",
0,
effects_panel_y,
self.gamma_correction_effect_enabled);
self.stem_darkening_effect_enabled =
self.draw_effects_switch(device,
self.gamma_correction_effect_enabled,
);
self.stem_darkening_effect_enabled = self.draw_effects_switch(
device,
debug_ui,
"Stem Darkening",
1,
effects_panel_y,
self.stem_darkening_effect_enabled);
self.subpixel_aa_effect_enabled =
self.draw_effects_switch(device,
self.stem_darkening_effect_enabled,
);
self.subpixel_aa_effect_enabled = self.draw_effects_switch(
device,
debug_ui,
"Subpixel AA",
2,
effects_panel_y,
self.subpixel_aa_effect_enabled);
self.subpixel_aa_effect_enabled,
);
}
fn draw_background_panel(&mut self,
fn draw_background_panel(
&mut self,
device: &D,
debug_ui: &mut DebugUI<D>,
panel_x: i32,
action: &mut UIAction) {
action: &mut UIAction,
) {
if !self.background_panel_visible {
return;
}
@ -286,34 +345,45 @@ impl<D> DemoUI<D> where D: Device {
let bottom = debug_ui.ui.framebuffer_size().y() - PADDING;
let panel_y = bottom - (BUTTON_HEIGHT + PADDING + BACKGROUND_PANEL_HEIGHT);
let panel_position = Point2DI32::new(panel_x, panel_y);
debug_ui.ui.draw_solid_rounded_rect(device,
RectI32::new(panel_position,
Point2DI32::new(BACKGROUND_PANEL_WIDTH,
BACKGROUND_PANEL_HEIGHT)),
WINDOW_COLOR);
debug_ui.ui.draw_solid_rounded_rect(
device,
RectI32::new(
panel_position,
Point2DI32::new(BACKGROUND_PANEL_WIDTH, BACKGROUND_PANEL_HEIGHT),
),
WINDOW_COLOR,
);
self.draw_background_menu_item(device,
self.draw_background_menu_item(
device,
debug_ui,
BackgroundColor::Light,
panel_position,
action);
self.draw_background_menu_item(device,
action,
);
self.draw_background_menu_item(
device,
debug_ui,
BackgroundColor::Dark,
panel_position,
action);
self.draw_background_menu_item(device,
action,
);
self.draw_background_menu_item(
device,
debug_ui,
BackgroundColor::Transparent,
panel_position,
action);
action,
);
}
fn draw_rotate_panel(&mut self,
fn draw_rotate_panel(
&mut self,
device: &D,
debug_ui: &mut DebugUI<D>,
rotate_panel_x: i32,
action: &mut UIAction) {
action: &mut UIAction,
) {
if !self.rotate_panel_visible {
return;
}
@ -322,40 +392,54 @@ impl<D> DemoUI<D> where D: Device {
let rotate_panel_y = bottom - (BUTTON_HEIGHT + PADDING + ROTATE_PANEL_HEIGHT);
let rotate_panel_origin = Point2DI32::new(rotate_panel_x, rotate_panel_y);
let rotate_panel_size = Point2DI32::new(ROTATE_PANEL_WIDTH, ROTATE_PANEL_HEIGHT);
debug_ui.ui.draw_solid_rounded_rect(device,
debug_ui.ui.draw_solid_rounded_rect(
device,
RectI32::new(rotate_panel_origin, rotate_panel_size),
WINDOW_COLOR);
WINDOW_COLOR,
);
let (widget_x, widget_y) = (rotate_panel_x + PADDING, rotate_panel_y + PADDING);
let widget_rect = RectI32::new(Point2DI32::new(widget_x, widget_y),
Point2DI32::new(SLIDER_WIDTH, SLIDER_KNOB_HEIGHT));
if let Some(position) = debug_ui.ui
let widget_rect = RectI32::new(
Point2DI32::new(widget_x, widget_y),
Point2DI32::new(SLIDER_WIDTH, SLIDER_KNOB_HEIGHT),
);
if let Some(position) = debug_ui
.ui
.event_queue
.handle_mouse_down_or_dragged_in_rect(widget_rect) {
.handle_mouse_down_or_dragged_in_rect(widget_rect)
{
self.rotation = position.x();
*action = UIAction::Rotate(self.rotation());
}
let slider_track_y = rotate_panel_y + PADDING + SLIDER_KNOB_HEIGHT / 2 -
SLIDER_TRACK_HEIGHT / 2;
let slider_track_rect =
RectI32::new(Point2DI32::new(widget_x, slider_track_y),
Point2DI32::new(SLIDER_WIDTH, SLIDER_TRACK_HEIGHT));
debug_ui.ui.draw_rect_outline(device, slider_track_rect, TEXT_COLOR);
let slider_track_y =
rotate_panel_y + PADDING + SLIDER_KNOB_HEIGHT / 2 - SLIDER_TRACK_HEIGHT / 2;
let slider_track_rect = RectI32::new(
Point2DI32::new(widget_x, slider_track_y),
Point2DI32::new(SLIDER_WIDTH, SLIDER_TRACK_HEIGHT),
);
debug_ui
.ui
.draw_rect_outline(device, slider_track_rect, TEXT_COLOR);
let slider_knob_x = widget_x + self.rotation - SLIDER_KNOB_WIDTH / 2;
let slider_knob_rect =
RectI32::new(Point2DI32::new(slider_knob_x, widget_y),
Point2DI32::new(SLIDER_KNOB_WIDTH, SLIDER_KNOB_HEIGHT));
debug_ui.ui.draw_solid_rect(device, slider_knob_rect, TEXT_COLOR);
let slider_knob_rect = RectI32::new(
Point2DI32::new(slider_knob_x, widget_y),
Point2DI32::new(SLIDER_KNOB_WIDTH, SLIDER_KNOB_HEIGHT),
);
debug_ui
.ui
.draw_solid_rect(device, slider_knob_rect, TEXT_COLOR);
}
fn draw_background_menu_item(&mut self,
fn draw_background_menu_item(
&mut self,
device: &D,
debug_ui: &mut DebugUI<D>,
color: BackgroundColor,
panel_position: Point2DI32,
action: &mut UIAction) {
action: &mut UIAction,
) {
let (text, index) = (color.as_str(), color as i32);
let widget_size = Point2DI32::new(BACKGROUND_PANEL_WIDTH, BUTTON_HEIGHT);
@ -363,36 +447,50 @@ impl<D> DemoUI<D> where D: Device {
let widget_rect = RectI32::new(widget_origin, widget_size);
if color == self.background_color {
debug_ui.ui.draw_solid_rounded_rect(device, widget_rect, TEXT_COLOR);
debug_ui
.ui
.draw_solid_rounded_rect(device, widget_rect, TEXT_COLOR);
}
let (text_x, text_y) = (PADDING * 2, BUTTON_TEXT_OFFSET);
let text_position = widget_origin + Point2DI32::new(text_x, text_y);
debug_ui.ui.draw_text(device, text, text_position, color == self.background_color);
debug_ui
.ui
.draw_text(device, text, text_position, color == self.background_color);
if let Some(_) = debug_ui.ui.event_queue.handle_mouse_down_in_rect(widget_rect) {
if let Some(_) = debug_ui
.ui
.event_queue
.handle_mouse_down_in_rect(widget_rect)
{
self.background_color = color;
*action = UIAction::ModelChanged;
}
}
fn draw_effects_switch(&self,
fn draw_effects_switch(
&self,
device: &D,
debug_ui: &mut DebugUI<D>,
text: &str,
index: i32,
window_y: i32,
value: bool)
-> bool {
value: bool,
) -> bool {
let text_x = PADDING * 2;
let text_y = window_y + PADDING + BUTTON_TEXT_OFFSET + (BUTTON_HEIGHT + PADDING) * index;
debug_ui.ui.draw_text(device, text, Point2DI32::new(text_x, text_y), false);
debug_ui
.ui
.draw_text(device, text, Point2DI32::new(text_x, text_y), false);
let switch_width = debug_ui.ui.measure_switch(2);
let switch_x = PADDING + EFFECTS_PANEL_WIDTH - (switch_width + PADDING);
let switch_y = window_y + PADDING + (BUTTON_HEIGHT + PADDING) * index;
let switch_position = Point2DI32::new(switch_x, switch_y);
debug_ui.ui.draw_text_switch(device, switch_position, &["Off", "On"], value as u8) != 0
debug_ui
.ui
.draw_text_switch(device, switch_position, &["Off", "On"], value as u8)
!= 0
}
}

View File

@ -21,7 +21,9 @@ use std::path::PathBuf;
pub trait Window {
fn gl_version(&self) -> GLVersion;
fn gl_default_framebuffer(&self) -> GLuint { 0 }
fn gl_default_framebuffer(&self) -> GLuint {
0
}
fn viewport(&self, view: View) -> RectI32;
fn make_current(&mut self, view: View);
fn present(&mut self);
@ -31,7 +33,10 @@ pub trait Window {
fn present_open_svg_dialog(&mut self);
fn run_save_dialog(&self, extension: &str) -> Result<PathBuf, ()>;
fn adjust_thread_pool_settings(&self, thread_pool_builder: ThreadPoolBuilder) -> ThreadPoolBuilder {
fn adjust_thread_pool_settings(
&self,
thread_pool_builder: ThreadPoolBuilder,
) -> ThreadPoolBuilder {
thread_pool_builder
}
}
@ -45,10 +50,16 @@ pub enum Event {
MouseMoved(Point2DI32),
MouseDragged(Point2DI32),
Zoom(f32, Point2DI32),
Look { pitch: f32, yaw: f32 },
Look {
pitch: f32,
yaw: f32,
},
SetEyeTransforms(Vec<OcularTransform>),
OpenSVG(SVGPath),
User { message_type: u32, message_data: u32 },
User {
message_type: u32,
message_data: u32,
},
}
#[derive(Clone, Copy)]
@ -67,7 +78,10 @@ pub struct WindowSize {
impl WindowSize {
#[inline]
pub fn device_size(&self) -> Point2DI32 {
self.logical_size.to_f32().scale(self.backing_scale_factor).to_i32()
self.logical_size
.to_f32()
.scale(self.backing_scale_factor)
.to_i32()
}
}

View File

@ -12,17 +12,17 @@
use jemallocator;
use nfd::Response;
use pathfinder_demo::window::{Event, Keycode, SVGPath, View, Window, WindowSize};
use pathfinder_demo::DemoApp;
use pathfinder_demo::Options;
use pathfinder_demo::window::{Event, Keycode, SVGPath, View, Window, WindowSize};
use pathfinder_geometry::basic::point::Point2DI32;
use pathfinder_geometry::basic::rect::RectI32;
use pathfinder_gl::GLVersion;
use pathfinder_gpu::resources::{FilesystemResourceLoader, ResourceLoader};
use sdl2::{EventPump, EventSubsystem, Sdl, VideoSubsystem};
use sdl2::event::{Event as SDLEvent, WindowEvent};
use sdl2::keyboard::Keycode as SDLKeycode;
use sdl2::video::{GLContext, GLProfile, Window as SDLWindow};
use sdl2::{EventPump, EventSubsystem, Sdl, VideoSubsystem};
use sdl2_sys::{SDL_Event, SDL_UserEvent};
use std::path::PathBuf;
use std::ptr;
@ -150,9 +150,12 @@ impl WindowImpl {
gl_attributes.set_depth_size(24);
gl_attributes.set_stencil_size(8);
window = sdl_video.window("Pathfinder Demo",
window = sdl_video
.window(
"Pathfinder Demo",
DEFAULT_WINDOW_WIDTH,
DEFAULT_WINDOW_HEIGHT)
DEFAULT_WINDOW_HEIGHT,
)
.opengl()
.resizable()
.allow_highdpi()
@ -166,9 +169,7 @@ impl WindowImpl {
let resource_loader = FilesystemResourceLoader::locate();
let open_svg_message_type = unsafe {
sdl_event.register_event().unwrap()
};
let open_svg_message_type = unsafe { sdl_event.register_event().unwrap() };
WindowImpl {
window,
@ -211,16 +212,17 @@ impl WindowImpl {
fn convert_sdl_event(&self, sdl_event: SDLEvent) -> Option<Event> {
match sdl_event {
SDLEvent::User { type_, .. } if type_ == self.open_svg_message_type => {
Some(Event::OpenSVG(SVGPath::Path(self.selected_file.clone().unwrap())))
}
SDLEvent::User { type_, code, .. } => {
Some(Event::User { message_type: type_, message_data: code as u32 })
}
SDLEvent::MouseButtonDown { x, y, .. } => {
Some(Event::MouseDown(Point2DI32::new(x, y)))
}
SDLEvent::MouseMotion { x, y, mousestate, .. } => {
SDLEvent::User { type_, .. } if type_ == self.open_svg_message_type => Some(
Event::OpenSVG(SVGPath::Path(self.selected_file.clone().unwrap())),
),
SDLEvent::User { type_, code, .. } => Some(Event::User {
message_type: type_,
message_data: code as u32,
}),
SDLEvent::MouseButtonDown { x, y, .. } => Some(Event::MouseDown(Point2DI32::new(x, y))),
SDLEvent::MouseMotion {
x, y, mousestate, ..
} => {
let position = Point2DI32::new(x, y);
if mousestate.left() {
Some(Event::MouseDragged(position))
@ -229,15 +231,18 @@ impl WindowImpl {
}
}
SDLEvent::Quit { .. } => Some(Event::Quit),
SDLEvent::Window { win_event: WindowEvent::SizeChanged(..), .. } => {
Some(Event::WindowResized(self.size()))
}
SDLEvent::KeyDown { keycode: Some(sdl_keycode), .. } => {
self.convert_sdl_keycode(sdl_keycode).map(Event::KeyDown)
}
SDLEvent::KeyUp { keycode: Some(sdl_keycode), .. } => {
self.convert_sdl_keycode(sdl_keycode).map(Event::KeyUp)
}
SDLEvent::Window {
win_event: WindowEvent::SizeChanged(..),
..
} => Some(Event::WindowResized(self.size())),
SDLEvent::KeyDown {
keycode: Some(sdl_keycode),
..
} => self.convert_sdl_keycode(sdl_keycode).map(Event::KeyDown),
SDLEvent::KeyUp {
keycode: Some(sdl_keycode),
..
} => self.convert_sdl_keycode(sdl_keycode).map(Event::KeyUp),
SDLEvent::MultiGesture { d_dist, .. } => {
let mouse_state = self.event_pump.mouse_state();
let center = Point2DI32::new(mouse_state.x(), mouse_state.y());
@ -251,8 +256,10 @@ impl WindowImpl {
match sdl_keycode {
SDLKeycode::Escape => Some(Keycode::Escape),
SDLKeycode::Tab => Some(Keycode::Tab),
sdl_keycode if sdl_keycode as i32 >= SDLKeycode::A as i32 &&
sdl_keycode as i32 <= SDLKeycode::Z as i32 => {
sdl_keycode
if sdl_keycode as i32 >= SDLKeycode::A as i32
&& sdl_keycode as i32 <= SDLKeycode::Z as i32 =>
{
let offset = (sdl_keycode as i32 - SDLKeycode::A as i32) as u8;
Some(Keycode::Alphanumeric(offset + b'a'))
}