From c5ccd0f6e02b7e06d71f141a4a674faf75e436e6 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 10 Apr 2019 14:42:24 -0700 Subject: [PATCH] Add partial support for transparent background colors. --- demo/common/src/lib.rs | 45 +++++++-- demo/common/src/ui.rs | 124 ++++++++++++++++++++----- demo/native/src/main.rs | 5 +- resources/textures/demo-background.png | Bin 0 -> 954 bytes resources/textures/demo-bg-dark.png | Bin 780 -> 0 bytes resources/textures/demo-bg-light.png | Bin 448 -> 0 bytes ui/src/lib.rs | 2 +- 7 files changed, 145 insertions(+), 31 deletions(-) create mode 100644 resources/textures/demo-background.png delete mode 100644 resources/textures/demo-bg-dark.png delete mode 100644 resources/textures/demo-bg-light.png diff --git a/demo/common/src/lib.rs b/demo/common/src/lib.rs index 6af92428..41689815 100644 --- a/demo/common/src/lib.rs +++ b/demo/common/src/lib.rs @@ -11,7 +11,7 @@ //! A demo app for Pathfinder. use crate::device::{GroundLineVertexArray, GroundProgram, GroundSolidVertexArray}; -use crate::ui::{DemoUI, UIAction}; +use crate::ui::{BackgroundColor, DemoUI, UIAction}; use crate::window::{Event, Keycode, SVGPath, Window, WindowSize}; use clap::{App, Arg}; use image::ColorType; @@ -60,10 +60,12 @@ 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 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 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 APPROX_FONT_SIZE: f32 = 16.0; @@ -90,7 +92,7 @@ pub struct DemoApp where W: Window { frame_counter: u32, pending_screenshot_path: Option, mouselook_enabled: bool, - dirty: bool, + pub dirty: bool, expire_message_event_id: u32, message_epoch: u32, last_mouse_position: Point2DI32, @@ -185,6 +187,9 @@ impl DemoApp where W: Window { } pub fn prepare_frame(&mut self, events: Vec) -> u32 { + // Clear dirty flag. + self.dirty = false; + // Handle events. let ui_events = self.handle_events(events); @@ -595,6 +600,7 @@ impl DemoApp where W: Window { fn handle_ui_action(&mut self, ui_action: &mut UIAction) { match ui_action { UIAction::None => {} + UIAction::ModelChanged => self.dirty = true, UIAction::TakeScreenshot(ref path) => { self.pending_screenshot_path = Some((*path).clone()); self.dirty = true; @@ -643,7 +649,11 @@ impl DemoApp where W: Window { } fn background_color(&self) -> ColorU { - if self.ui.dark_background_enabled { DARK_BG_COLOR } else { LIGHT_BG_COLOR } + match self.ui.background_color { + BackgroundColor::Light => LIGHT_BG_COLOR, + BackgroundColor::Dark => DARK_BG_COLOR, + BackgroundColor::Transparent => TRANSPARENT_BG_COLOR, + } } } @@ -813,6 +823,7 @@ pub struct Options { pub mode: Mode, pub input_path: SVGPath, pub ui: UIVisibility, + pub background_color: BackgroundColor, hidden_field_for_future_proofing: (), } @@ -823,6 +834,7 @@ impl Default for Options { mode: Mode::TwoD, input_path: SVGPath::Default, ui: UIVisibility::All, + background_color: BackgroundColor::Light, hidden_field_for_future_proofing: (), } } @@ -849,6 +861,14 @@ impl Options { .possible_values(&["none", "stats", "all"]) .help("How much UI to show"), ) + .arg( + Arg::with_name("background") + .short("b") + .long("background") + .takes_value(true) + .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)) .get_matches(); @@ -870,12 +890,21 @@ impl Options { }; } + if let Some(background_color) = matches.value_of("background") { + self.background_color = match background_color { + "light" => BackgroundColor::Light, + "dark" => BackgroundColor::Dark, + _ => BackgroundColor::Transparent, + }; + } + if let Some(path) = matches.value_of("INPUT") { self.input_path = SVGPath::Path(PathBuf::from(path)); }; } - 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); } diff --git a/demo/common/src/ui.rs b/demo/common/src/ui.rs index 706a75ac..da065389 100644 --- a/demo/common/src/ui.rs +++ b/demo/common/src/ui.rs @@ -29,6 +29,9 @@ const SLIDER_KNOB_HEIGHT: i32 = 48; const EFFECTS_PANEL_WIDTH: i32 = 550; const EFFECTS_PANEL_HEIGHT: i32 = BUTTON_HEIGHT * 3 + PADDING * 4; +const BACKGROUND_PANEL_WIDTH: i32 = 250; +const BACKGROUND_PANEL_HEIGHT: i32 = BUTTON_HEIGHT * 3; + const ROTATE_PANEL_WIDTH: i32 = SLIDER_WIDTH + PADDING * 2; const ROTATE_PANEL_HEIGHT: i32 = PADDING * 2 + SLIDER_HEIGHT; @@ -37,8 +40,7 @@ static OPEN_PNG_NAME: &'static str = "demo-open"; static ROTATE_PNG_NAME: &'static str = "demo-rotate"; static ZOOM_IN_PNG_NAME: &'static str = "demo-zoom-in"; static ZOOM_OUT_PNG_NAME: &'static str = "demo-zoom-out"; -static BG_LIGHT_PNG_NAME: &'static str = "demo-bg-light"; -static BG_DARK_PNG_NAME: &'static str = "demo-bg-dark"; +static BACKGROUND_PNG_NAME: &'static str = "demo-background"; static SCREENSHOT_PNG_NAME: &'static str = "demo-screenshot"; pub struct DemoUI where D: Device { @@ -47,17 +49,17 @@ pub struct DemoUI where D: Device { rotate_texture: D::Texture, zoom_in_texture: D::Texture, zoom_out_texture: D::Texture, - bg_light_texture: D::Texture, - bg_dark_texture: D::Texture, + background_texture: D::Texture, screenshot_texture: D::Texture, effects_panel_visible: bool, + background_panel_visible: bool, rotate_panel_visible: bool, // FIXME(pcwalton): Factor the below out into a model class. pub mode: Mode, - pub dark_background_enabled: bool, + pub background_color: BackgroundColor, pub gamma_correction_effect_enabled: bool, pub stem_darkening_effect_enabled: bool, pub subpixel_aa_effect_enabled: bool, @@ -73,8 +75,7 @@ impl DemoUI where D: Device { let rotate_texture = device.create_texture_from_png(resources, ROTATE_PNG_NAME); let zoom_in_texture = device.create_texture_from_png(resources, ZOOM_IN_PNG_NAME); let zoom_out_texture = device.create_texture_from_png(resources, ZOOM_OUT_PNG_NAME); - let bg_light_texture = device.create_texture_from_png(resources, BG_LIGHT_PNG_NAME); - let bg_dark_texture = device.create_texture_from_png(resources, BG_DARK_PNG_NAME); + let background_texture = device.create_texture_from_png(resources, BACKGROUND_PNG_NAME); let screenshot_texture = device.create_texture_from_png(resources, SCREENSHOT_PNG_NAME); DemoUI { @@ -83,15 +84,15 @@ impl DemoUI where D: Device { rotate_texture, zoom_in_texture, zoom_out_texture, - bg_light_texture, - bg_dark_texture, + background_texture, screenshot_texture, effects_panel_visible: false, + background_panel_visible: false, rotate_panel_visible: false, mode: options.mode, - dark_background_enabled: false, + background_color: options.background_color, gamma_correction_effect_enabled: false, stem_darkening_effect_enabled: false, subpixel_aa_effect_enabled: false, @@ -166,7 +167,9 @@ impl DemoUI where D: Device { 1 => Mode::ThreeD, _ => Mode::VR, }; + *action = UIAction::ModelChanged; } + 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, @@ -175,17 +178,18 @@ impl DemoUI where D: Device { position += Point2DI32::new(mode_switch_width + PADDING, 0); // Draw background switch. - self.dark_background_enabled = debug_ui.ui.draw_image_switch(device, - position, - &self.bg_light_texture, - &self.bg_dark_texture, - self.dark_background_enabled); - let background_color_switch_width = debug_ui.ui.measure_switch(2); - let background_color_switch_size = Point2DI32::new(background_color_switch_width, - BUTTON_HEIGHT); - let background_color_switch_rect = RectI32::new(position, background_color_switch_size); - debug_ui.ui.draw_tooltip(device, "Background Color", background_color_switch_rect); - position += Point2DI32::new(background_color_switch_width + PADDING, 0); + 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, + "Background Color", + RectI32::new(position, button_size)); + } + + // Draw background panel, if necessary. + self.draw_background_panel(device, debug_ui, position.x(), action); + position += Point2DI32::new(button_size.x() + PADDING, 0); // Draw effects panel, if necessary. self.draw_effects_panel(device, debug_ui); @@ -268,7 +272,41 @@ impl DemoUI where D: Device { 2, effects_panel_y, self.subpixel_aa_effect_enabled); + } + fn draw_background_panel(&mut self, + device: &D, + debug_ui: &mut DebugUI, + panel_x: i32, + action: &mut UIAction) { + if !self.background_panel_visible { + return; + } + + 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); + + self.draw_background_menu_item(device, + debug_ui, + BackgroundColor::Light, + panel_position, + action); + self.draw_background_menu_item(device, + debug_ui, + BackgroundColor::Dark, + panel_position, + action); + self.draw_background_menu_item(device, + debug_ui, + BackgroundColor::Transparent, + panel_position, + action); } fn draw_rotate_panel(&mut self, @@ -312,6 +350,32 @@ impl DemoUI where D: Device { debug_ui.ui.draw_solid_rect(device, slider_knob_rect, TEXT_COLOR); } + fn draw_background_menu_item(&mut self, + device: &D, + debug_ui: &mut DebugUI, + color: BackgroundColor, + panel_position: Point2DI32, + action: &mut UIAction) { + let (text, index) = (color.as_str(), color as i32); + + let widget_size = Point2DI32::new(BACKGROUND_PANEL_WIDTH, BUTTON_HEIGHT); + let widget_origin = panel_position + Point2DI32::new(0, widget_size.y() * index); + 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); + } + + 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); + + 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, device: &D, debug_ui: &mut DebugUI, @@ -335,8 +399,26 @@ impl DemoUI where D: Device { #[derive(Clone, Debug, PartialEq)] pub enum UIAction { None, + ModelChanged, TakeScreenshot(PathBuf), ZoomIn, ZoomOut, Rotate(f32), } + +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum BackgroundColor { + Light = 0, + Dark = 1, + Transparent = 2, +} + +impl BackgroundColor { + fn as_str(&self) -> &'static str { + match *self { + BackgroundColor::Light => "Light", + BackgroundColor::Dark => "Dark", + BackgroundColor::Transparent => "Transparent", + } + } +} diff --git a/demo/native/src/main.rs b/demo/native/src/main.rs index a1264142..94b1f255 100644 --- a/demo/native/src/main.rs +++ b/demo/native/src/main.rs @@ -39,7 +39,10 @@ fn main() { let mut app = DemoApp::new(window, window_size, options); while !app.should_exit { - let mut events = vec![app.window.get_event()]; + let mut events = vec![]; + if !app.dirty { + events.push(app.window.get_event()); + } while let Some(event) = app.window.try_get_event() { events.push(event); } diff --git a/resources/textures/demo-background.png b/resources/textures/demo-background.png new file mode 100644 index 0000000000000000000000000000000000000000..c1d067373e75454da19d85fbff55aa5438cb2d30 GIT binary patch literal 954 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4mJh`hH$2z?F!lvNA9* zFct^7J29*~C-ahlfk7eJBgmJ5p-PQ`p`nF=;THn~L&FOOhEf9thF1v;3|2E37{m+a z>1xpl9F;t3RPwL=53|= za>WwnNoC$r-Rn0ht<=v9ykzZpUUjeG=B*3fH3mMg`7rCzmqtAUIj=t~A1*roFj##+ zHsSVup?genAqq7!@(;}1b@V;MGvTxkQWyIA{cPIY??@Fa_WQ`qdB}=$<6NOahV84w z?t9Jn$@sSAM_K0%#_-rJxkX`n)SFmOaV}jGAr9Bf)wruQHeRM6mnj`1q zJf=l<^RH`#Kfb@oTX6RgUgNn-FBb8{OfY$E%Y5}i2yGo-uGCqM{hmYpz?ot!qzi0 zBOl#8_lt9FOW5ANxLch%%<)dE`+lmtT-o3Fec{yOF@~G3D4jFU$g=U-|Y z`ZK!4yCe^k?w^!(=y|DUq*&wTbyDud=k8xU#u_X8XTq1zOM8~6PpV4$wtCW;0~{x% zE9K*u+8fWB`k#nb^9xg`m`G4e({_MqVZEbB_Kbaq$e}6!Jf}kY>1A}UbYeY#( zVo9o1a#3nxNh*VpfuW_Yfr+l6L5Puom8p@Hk+HUcft7(l?A^LKC>nC}Q!>*kacj_N zIHthBz@P!Lp|~vFDk-rzRkyS#lOZiLC)G+{U%w=`KtDGzJu^95H!0oGsmdZMyhEmS QHYn?Oy85}Sb4q9e06FB6S^xk5 literal 0 HcmV?d00001 diff --git a/resources/textures/demo-bg-dark.png b/resources/textures/demo-bg-dark.png deleted file mode 100644 index 82275e929ac1631ce0416f4eeef444ed82abb47e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 780 zcmV+n1M~ceP)Ep5f;a8z5-1KoOyrtWXFE;J3(A-#ze2im2|k+Jm50zH0+rmsST2_$ z19%KX6sV{lSG6RoV}-1h4oksqu%<$ehBU5pg9vBApXq3@7@jyYW z$G~OjOWHqii0yEH678ZiL2g*jC;YuuqNzFc(!`^gdblqsmzXcFVDA9vHHe zXD3!MRui`J7J)LkE?~6ED~1u1*A%c%F8g=j)pzoUW5nf^0#0a6?JThLt@2Wtwzf=4 zUVXrMWi_n;uP#~2s!1J`4yJ14(E-B}!iA8Jk2HW}Nhv_tF8tzgWymZ%VG z9Ed5WX%5F^e6I?K1L-p5)c(Pmhu6-0TD`p@vR!^v8K6^n_QiR;mVcCA7x1E99=nrI z@j5A=@Dwl>l~?)M-(He)Q+{7#q@wZ*f0elR*Bp*h+Mo+#tX`WO_y^-BZDilYc+puZ zpW>E9j9-eiNl8DB$ykMQ%A5bgF;uDmMcufThGWM+DUN)6q~Dm56WB8qrJCc|W5xO;aZT0RA8_3hh8Rs`@XXPi$iyDO^{^2cUYizo!70 zbA$?j4k&-10jSV?+*QEDr+}R&Kpztm>o0$6_?9dd$!yRp?)`}-iwz3Dc+gl%j~fLM zFss{1&+lC@GJ4f5-3xd7JYKiHfp113ZGzo!#Hk6rh9^h(M}u1!gobC3?ST z<_{W3%C5CbNdwXqm|KB&8i)q`Xu5tlZ%hFi6GesoNS80;`x2XRoo8@w6|vnCU9uWtSSsf2M-WIVzpQ q*t_84{%ZRJ Option { + pub fn handle_mouse_down_in_rect(&mut self, rect: RectI32) -> Option { let (mut remaining_events, mut result) = (vec![], None); for event in self.events.drain(..) { match event {