From 22fe63503feef6119d68cfd4e87447556a40dc7d Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 12 Feb 2019 12:40:24 -0800 Subject: [PATCH] Implement 2D rotation --- demo/src/main.rs | 16 +++---- demo/src/ui.rs | 113 ++++++++++++++++++++++++++++++++++++++--------- gl/src/debug.rs | 2 +- 3 files changed, 99 insertions(+), 32 deletions(-) diff --git a/demo/src/main.rs b/demo/src/main.rs index f9621593..c5b5c68d 100644 --- a/demo/src/main.rs +++ b/demo/src/main.rs @@ -164,7 +164,7 @@ impl DemoApp { let (drawable_width, drawable_height) = self.window.drawable_size(); let drawable_size = Size2D::new(drawable_width, drawable_height); - let perspective = if self.ui.threed_enabled { + let render_transform = if self.ui.threed_enabled { let rotation = Transform3DF32::from_rotation(-self.camera_yaw, -self.camera_pitch, 0.0); @@ -189,15 +189,16 @@ impl DemoApp { translation.y(), translation.z())); - Some(Perspective::new(&transform, &drawable_size)) + RenderTransform::Perspective(Perspective::new(&transform, &drawable_size)) } else { - None + let transform = Transform2DF32::from_rotation(self.ui.rotation()); + RenderTransform::Transform2D(transform) }; let count = if self.frame_counter == 0 { 2 } else { 1 }; for _ in 0..count { self.scene_thread_proxy.sender.send(MainToSceneMsg::Build(BuildOptions { - perspective, + render_transform: render_transform.clone(), stem_darkening_font_size: if self.ui.stem_darkening_effect_enabled { Some(APPROX_FONT_SIZE * self.scale_factor) } else { @@ -397,7 +398,7 @@ enum MainToSceneMsg { } struct BuildOptions { - perspective: Option, + render_transform: RenderTransform, stem_darkening_font_size: Option, } @@ -465,10 +466,7 @@ fn build_scene(scene: &Scene, build_options: BuildOptions, jobs: Option) let z_buffer = ZBuffer::new(scene.view_box); let render_options = RenderOptions { - transform: match build_options.perspective { - None => RenderTransform::Transform2D(Transform2DF32::default()), - Some(perspective) => RenderTransform::Perspective(perspective), - }, + transform: build_options.render_transform, dilation: match build_options.stem_darkening_font_size { None => Point2DF32::default(), Some(font_size) => { diff --git a/demo/src/ui.rs b/demo/src/ui.rs index ce149f19..5cd40997 100644 --- a/demo/src/ui.rs +++ b/demo/src/ui.rs @@ -15,53 +15,77 @@ use pathfinder_geometry::basic::rect::RectI32; use pathfinder_gl::debug::{BUTTON_HEIGHT, BUTTON_TEXT_OFFSET, BUTTON_WIDTH, DebugUI, PADDING}; use pathfinder_gl::debug::{TEXT_COLOR, WINDOW_COLOR}; use pathfinder_gl::device::Texture; +use std::f32::consts::PI; use std::path::PathBuf; const SWITCH_SIZE: i32 = SWITCH_HALF_SIZE * 2 + 1; const SWITCH_HALF_SIZE: i32 = 96; -const EFFECTS_WINDOW_WIDTH: i32 = 550; -const EFFECTS_WINDOW_HEIGHT: i32 = BUTTON_HEIGHT * 3 + PADDING * 4; +const SLIDER_WIDTH: i32 = 360; +const SLIDER_HEIGHT: i32 = 48; +const SLIDER_TRACK_HEIGHT: i32 = 24; +const SLIDER_KNOB_WIDTH: i32 = 12; +const SLIDER_KNOB_HEIGHT: i32 = 48; + +const EFFECTS_PANEL_WIDTH: i32 = 550; +const EFFECTS_PANEL_HEIGHT: i32 = BUTTON_HEIGHT * 3 + PADDING * 4; + +const ROTATE_PANEL_X: i32 = PADDING + (BUTTON_WIDTH + PADDING) * 2 + PADDING + SWITCH_SIZE; +const ROTATE_PANEL_WIDTH: i32 = SLIDER_WIDTH + PADDING * 2; +const ROTATE_PANEL_HEIGHT: i32 = PADDING * 2 + SLIDER_HEIGHT; static EFFECTS_PNG_NAME: &'static str = "demo-effects"; static OPEN_PNG_NAME: &'static str = "demo-open"; +static ROTATE_PNG_NAME: &'static str = "demo-rotate"; pub struct DemoUI { effects_texture: Texture, open_texture: Texture, + rotate_texture: Texture, + + effects_panel_visible: bool, + rotate_panel_visible: bool, - effects_window_visible: bool, pub threed_enabled: bool, pub gamma_correction_effect_enabled: bool, pub stem_darkening_effect_enabled: bool, pub subpixel_aa_effect_enabled: bool, pub file_to_open: Option, + pub rotation: i32, } impl DemoUI { pub fn new(options: Options) -> DemoUI { let effects_texture = Texture::from_png(EFFECTS_PNG_NAME); let open_texture = Texture::from_png(OPEN_PNG_NAME); + let rotate_texture = Texture::from_png(ROTATE_PNG_NAME); DemoUI { effects_texture, open_texture, + rotate_texture, threed_enabled: options.threed, - effects_window_visible: false, + effects_panel_visible: false, + rotate_panel_visible: true, gamma_correction_effect_enabled: false, stem_darkening_effect_enabled: false, subpixel_aa_effect_enabled: false, file_to_open: None, + rotation: SLIDER_WIDTH / 2, } } + pub fn rotation(&self) -> f32 { + (self.rotation as f32 / SLIDER_WIDTH as f32 * 2.0 - 1.0) * PI + } + pub fn update(&mut self, debug_ui: &mut DebugUI, event: &mut UIEvent) { let bottom = debug_ui.framebuffer_size().height as i32 - PADDING; // Draw effects button. let effects_button_position = Point2DI32::new(PADDING, bottom - BUTTON_HEIGHT); if self.draw_button(debug_ui, event, effects_button_position, &self.effects_texture) { - self.effects_window_visible = !self.effects_window_visible; + self.effects_panel_visible = !self.effects_panel_visible; } // Draw open button. @@ -87,20 +111,32 @@ impl DemoUI { "3D", self.threed_enabled); - // Draw effects window, if necessary. - self.draw_effects_window(debug_ui, event); + // Draw rotate button, if applicable. + if !self.threed_enabled { + let rotate_button_y = bottom - BUTTON_HEIGHT; + let rotate_button_position = Point2DI32::new(ROTATE_PANEL_X, rotate_button_y); + if self.draw_button(debug_ui, event, rotate_button_position, &self.rotate_texture) { + self.rotate_panel_visible = !self.rotate_panel_visible; + } + } + + // Draw effects panel, if necessary. + self.draw_effects_panel(debug_ui, event); + + // Draw rotate panel, if necessary. + self.draw_rotate_panel(debug_ui, event); } - fn draw_effects_window(&mut self, debug_ui: &mut DebugUI, event: &mut UIEvent) { - if !self.effects_window_visible { + fn draw_effects_panel(&mut self, debug_ui: &mut DebugUI, event: &mut UIEvent) { + if !self.effects_panel_visible { return; } let bottom = debug_ui.framebuffer_size().height as i32 - PADDING; - let effects_window_y = bottom - (BUTTON_HEIGHT + PADDING + EFFECTS_WINDOW_HEIGHT); - debug_ui.draw_solid_rect(RectI32::new(Point2DI32::new(PADDING, effects_window_y), - Point2DI32::new(EFFECTS_WINDOW_WIDTH, - EFFECTS_WINDOW_HEIGHT)), + let effects_panel_y = bottom - (BUTTON_HEIGHT + PADDING + EFFECTS_PANEL_HEIGHT); + debug_ui.draw_solid_rect(RectI32::new(Point2DI32::new(PADDING, effects_panel_y), + Point2DI32::new(EFFECTS_PANEL_WIDTH, + EFFECTS_PANEL_HEIGHT)), WINDOW_COLOR); self.gamma_correction_effect_enabled = @@ -108,25 +144,58 @@ impl DemoUI { event, "Gamma Correction", 0, - effects_window_y, + effects_panel_y, self.gamma_correction_effect_enabled); self.stem_darkening_effect_enabled = self.draw_effects_switch(debug_ui, event, "Stem Darkening", 1, - effects_window_y, + effects_panel_y, self.stem_darkening_effect_enabled); self.subpixel_aa_effect_enabled = self.draw_effects_switch(debug_ui, event, "Subpixel AA", 2, - effects_window_y, + effects_panel_y, self.subpixel_aa_effect_enabled); } + fn draw_rotate_panel(&mut self, debug_ui: &mut DebugUI, event: &mut UIEvent) { + if !self.rotate_panel_visible { + return; + } + + let bottom = debug_ui.framebuffer_size().height as i32 - PADDING; + let rotate_panel_y = bottom - (BUTTON_HEIGHT + PADDING + ROTATE_PANEL_HEIGHT); + debug_ui.draw_solid_rect(RectI32::new(Point2DI32::new(ROTATE_PANEL_X, rotate_panel_y), + Point2DI32::new(ROTATE_PANEL_WIDTH, + ROTATE_PANEL_HEIGHT)), + 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) = event.handle_mouse_down_in_rect(widget_rect) { + self.rotation = position.x(); + } + + 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.draw_rect_outline(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.draw_solid_rect(slider_knob_rect, TEXT_COLOR); + } + fn draw_button(&self, debug_ui: &mut DebugUI, event: &mut UIEvent, @@ -137,7 +206,7 @@ impl DemoUI { debug_ui.draw_solid_rect(button_rect, WINDOW_COLOR); debug_ui.draw_rect_outline(button_rect, TEXT_COLOR); debug_ui.draw_texture(origin + Point2DI32::new(PADDING, PADDING), texture, TEXT_COLOR); - event.handle_mouse_down_in_rect(button_rect) + event.handle_mouse_down_in_rect(button_rect).is_some() } fn draw_effects_switch(&self, @@ -152,7 +221,7 @@ impl DemoUI { let text_y = window_y + PADDING + BUTTON_TEXT_OFFSET + (BUTTON_HEIGHT + PADDING) * index; debug_ui.draw_text(text, Point2DI32::new(text_x, text_y), false); - let switch_x = PADDING + EFFECTS_WINDOW_WIDTH - (SWITCH_SIZE + PADDING); + let switch_x = PADDING + EFFECTS_PANEL_WIDTH - (SWITCH_SIZE + PADDING); let switch_y = window_y + PADDING + (BUTTON_HEIGHT + PADDING) * index; self.draw_switch(debug_ui, event, Point2DI32::new(switch_x, switch_y), "Off", "On", value) } @@ -166,7 +235,7 @@ impl DemoUI { mut value: bool) -> bool { let widget_rect = RectI32::new(origin, Point2DI32::new(SWITCH_SIZE, BUTTON_HEIGHT)); - if event.handle_mouse_down_in_rect(widget_rect) { + if event.handle_mouse_down_in_rect(widget_rect).is_some() { value = !value; } @@ -205,13 +274,13 @@ impl UIEvent { match *self { UIEvent::None => true, _ => false } } - fn handle_mouse_down_in_rect(&mut self, rect: RectI32) -> bool { + fn handle_mouse_down_in_rect(&mut self, rect: RectI32) -> Option { if let UIEvent::MouseDown(point) = *self { if rect.contains_point(point) { *self = UIEvent::None; - return true; + return Some(point - rect.origin()); } } - false + None } } diff --git a/gl/src/debug.rs b/gl/src/debug.rs index 02be3128..74f22220 100644 --- a/gl/src/debug.rs +++ b/gl/src/debug.rs @@ -40,7 +40,7 @@ pub const BUTTON_HEIGHT: i32 = PADDING * 2 + ICON_SIZE; pub const BUTTON_TEXT_OFFSET: i32 = PADDING + 36; pub static TEXT_COLOR: ColorU = ColorU { r: 255, g: 255, b: 255, a: 255 }; -pub static WINDOW_COLOR: ColorU = ColorU { r: 30, g: 30, b: 30, a: 255 - 30 }; +pub static WINDOW_COLOR: ColorU = ColorU { r: 0, g: 0, b: 0, a: 255 - 90 }; const PERF_WINDOW_WIDTH: i32 = 300; const PERF_WINDOW_HEIGHT: i32 = LINE_HEIGHT * 2 + PADDING + 2;