Move UI event code and widgets to the `pathfinder_ui` crate
This commit is contained in:
parent
ad0691c146
commit
33aa6f905d
|
@ -568,7 +568,6 @@ dependencies = [
|
||||||
"quickcheck 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"quickcheck 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
//! A demo app for Pathfinder.
|
//! A demo app for Pathfinder.
|
||||||
|
|
||||||
use crate::device::{GroundLineVertexArray, GroundProgram, GroundSolidVertexArray};
|
use crate::device::{GroundLineVertexArray, GroundProgram, GroundSolidVertexArray};
|
||||||
use crate::ui::{DemoUI, UIAction, UIEvent};
|
use crate::ui::{DemoUI, UIAction};
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
use image::ColorType;
|
use image::ColorType;
|
||||||
use jemallocator;
|
use jemallocator;
|
||||||
|
@ -30,6 +30,7 @@ use pathfinder_renderer::post::{DEFRINGING_KERNEL_CORE_GRAPHICS, STEM_DARKENING_
|
||||||
use pathfinder_renderer::scene::Scene;
|
use pathfinder_renderer::scene::Scene;
|
||||||
use pathfinder_renderer::z_buffer::ZBuffer;
|
use pathfinder_renderer::z_buffer::ZBuffer;
|
||||||
use pathfinder_svg::SceneExt;
|
use pathfinder_svg::SceneExt;
|
||||||
|
use pathfinder_ui::UIEvent;
|
||||||
use rayon::ThreadPoolBuilder;
|
use rayon::ThreadPoolBuilder;
|
||||||
use sdl2::{EventPump, Sdl, VideoSubsystem};
|
use sdl2::{EventPump, Sdl, VideoSubsystem};
|
||||||
use sdl2::event::{Event, WindowEvent};
|
use sdl2::event::{Event, WindowEvent};
|
||||||
|
|
|
@ -12,22 +12,13 @@ use crate::Options;
|
||||||
use nfd::Response;
|
use nfd::Response;
|
||||||
use pathfinder_geometry::basic::point::Point2DI32;
|
use pathfinder_geometry::basic::point::Point2DI32;
|
||||||
use pathfinder_geometry::basic::rect::RectI32;
|
use pathfinder_geometry::basic::rect::RectI32;
|
||||||
use pathfinder_geometry::color::ColorU;
|
|
||||||
use pathfinder_gpu::{Device, Resources};
|
use pathfinder_gpu::{Device, Resources};
|
||||||
use pathfinder_renderer::gpu::debug::DebugUI;
|
use pathfinder_renderer::gpu::debug::DebugUI;
|
||||||
use pathfinder_ui::{PADDING, TEXT_COLOR, WINDOW_COLOR};
|
use pathfinder_ui::{BUTTON_HEIGHT, BUTTON_TEXT_OFFSET, BUTTON_WIDTH, PADDING, SWITCH_SIZE};
|
||||||
|
use pathfinder_ui::{TEXT_COLOR, UIEvent, WINDOW_COLOR};
|
||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
const ICON_SIZE: i32 = 48;
|
|
||||||
|
|
||||||
const BUTTON_WIDTH: i32 = PADDING * 2 + ICON_SIZE;
|
|
||||||
const BUTTON_HEIGHT: i32 = PADDING * 2 + ICON_SIZE;
|
|
||||||
const BUTTON_TEXT_OFFSET: i32 = PADDING + 36;
|
|
||||||
|
|
||||||
const SWITCH_SIZE: i32 = SWITCH_HALF_SIZE * 2 + 1;
|
|
||||||
const SWITCH_HALF_SIZE: i32 = 96;
|
|
||||||
|
|
||||||
const SLIDER_WIDTH: i32 = 360;
|
const SLIDER_WIDTH: i32 = 360;
|
||||||
const SLIDER_HEIGHT: i32 = 48;
|
const SLIDER_HEIGHT: i32 = 48;
|
||||||
const SLIDER_TRACK_HEIGHT: i32 = 24;
|
const SLIDER_TRACK_HEIGHT: i32 = 24;
|
||||||
|
@ -46,9 +37,6 @@ const ROTATE_PANEL_X: i32 = PADDING + (BUTTON_WIDTH + PADDING) * 3 + (PADDING +
|
||||||
const ROTATE_PANEL_WIDTH: i32 = SLIDER_WIDTH + PADDING * 2;
|
const ROTATE_PANEL_WIDTH: i32 = SLIDER_WIDTH + PADDING * 2;
|
||||||
const ROTATE_PANEL_HEIGHT: i32 = PADDING * 2 + SLIDER_HEIGHT;
|
const ROTATE_PANEL_HEIGHT: i32 = PADDING * 2 + SLIDER_HEIGHT;
|
||||||
|
|
||||||
static BUTTON_ICON_COLOR: ColorU = ColorU { r: 255, g: 255, b: 255, a: 255 };
|
|
||||||
static OUTLINE_COLOR: ColorU = ColorU { r: 255, g: 255, b: 255, a: 192 };
|
|
||||||
|
|
||||||
static EFFECTS_PNG_NAME: &'static str = "demo-effects";
|
static EFFECTS_PNG_NAME: &'static str = "demo-effects";
|
||||||
static OPEN_PNG_NAME: &'static str = "demo-open";
|
static OPEN_PNG_NAME: &'static str = "demo-open";
|
||||||
static ROTATE_PNG_NAME: &'static str = "demo-rotate";
|
static ROTATE_PNG_NAME: &'static str = "demo-rotate";
|
||||||
|
@ -125,18 +113,14 @@ impl<D> DemoUI<D> where D: Device {
|
||||||
|
|
||||||
// Draw effects button.
|
// Draw effects button.
|
||||||
let effects_button_position = Point2DI32::new(PADDING, bottom - BUTTON_HEIGHT);
|
let effects_button_position = Point2DI32::new(PADDING, bottom - BUTTON_HEIGHT);
|
||||||
if self.draw_button(device,
|
if debug_ui.ui.draw_button(device, event, effects_button_position, &self.effects_texture) {
|
||||||
debug_ui,
|
|
||||||
event,
|
|
||||||
effects_button_position,
|
|
||||||
&self.effects_texture) {
|
|
||||||
self.effects_panel_visible = !self.effects_panel_visible;
|
self.effects_panel_visible = !self.effects_panel_visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw open button.
|
// Draw open button.
|
||||||
let lower_button_y = bottom - BUTTON_HEIGHT;
|
let lower_button_y = bottom - BUTTON_HEIGHT;
|
||||||
let open_button_position = Point2DI32::new(OPEN_BUTTON_X, lower_button_y);
|
let open_button_position = Point2DI32::new(OPEN_BUTTON_X, lower_button_y);
|
||||||
if self.draw_button(device, debug_ui, event, open_button_position, &self.open_texture) {
|
if debug_ui.ui.draw_button(device, event, open_button_position, &self.open_texture) {
|
||||||
if let Ok(Response::Okay(file)) = nfd::open_file_dialog(Some("svg"), None) {
|
if let Ok(Response::Okay(file)) = nfd::open_file_dialog(Some("svg"), None) {
|
||||||
*action = UIAction::OpenFile(PathBuf::from(file));
|
*action = UIAction::OpenFile(PathBuf::from(file));
|
||||||
}
|
}
|
||||||
|
@ -144,11 +128,10 @@ impl<D> DemoUI<D> where D: Device {
|
||||||
|
|
||||||
// Draw screenshot button.
|
// Draw screenshot button.
|
||||||
let screenshot_button_position = Point2DI32::new(SCREENSHOT_BUTTON_X, lower_button_y);
|
let screenshot_button_position = Point2DI32::new(SCREENSHOT_BUTTON_X, lower_button_y);
|
||||||
if self.draw_button(device,
|
if debug_ui.ui.draw_button(device,
|
||||||
debug_ui,
|
event,
|
||||||
event,
|
screenshot_button_position,
|
||||||
screenshot_button_position,
|
&self.screenshot_texture) {
|
||||||
&self.screenshot_texture) {
|
|
||||||
if let Ok(Response::Okay(file)) = nfd::open_save_dialog(Some("png"), None) {
|
if let Ok(Response::Okay(file)) = nfd::open_save_dialog(Some("png"), None) {
|
||||||
*action = UIAction::TakeScreenshot(PathBuf::from(file));
|
*action = UIAction::TakeScreenshot(PathBuf::from(file));
|
||||||
}
|
}
|
||||||
|
@ -156,53 +139,48 @@ impl<D> DemoUI<D> where D: Device {
|
||||||
|
|
||||||
// Draw 3D switch.
|
// Draw 3D switch.
|
||||||
let three_d_switch_origin = Point2DI32::new(THREE_D_SWITCH_X, lower_button_y);
|
let three_d_switch_origin = Point2DI32::new(THREE_D_SWITCH_X, lower_button_y);
|
||||||
self.three_d_enabled = self.draw_text_switch(device,
|
self.three_d_enabled = debug_ui.ui.draw_text_switch(device,
|
||||||
debug_ui,
|
event,
|
||||||
event,
|
three_d_switch_origin,
|
||||||
three_d_switch_origin,
|
"2D",
|
||||||
"2D",
|
"3D",
|
||||||
"3D",
|
self.three_d_enabled);
|
||||||
self.three_d_enabled);
|
|
||||||
|
|
||||||
// Draw background switch.
|
// Draw background switch.
|
||||||
let background_switch_origin = Point2DI32::new(BACKGROUND_SWITCH_X, lower_button_y);
|
let background_switch_origin = Point2DI32::new(BACKGROUND_SWITCH_X, lower_button_y);
|
||||||
self.dark_background_enabled = self.draw_image_switch(device,
|
self.dark_background_enabled = debug_ui.ui.draw_image_switch(device,
|
||||||
debug_ui,
|
event,
|
||||||
event,
|
background_switch_origin,
|
||||||
background_switch_origin,
|
&self.bg_light_texture,
|
||||||
&self.bg_light_texture,
|
&self.bg_dark_texture,
|
||||||
&self.bg_dark_texture,
|
self.dark_background_enabled);
|
||||||
self.dark_background_enabled);
|
|
||||||
|
|
||||||
// Draw rotate and zoom buttons, if applicable.
|
// Draw rotate and zoom buttons, if applicable.
|
||||||
if !self.three_d_enabled {
|
if !self.three_d_enabled {
|
||||||
let rotate_button_y = bottom - BUTTON_HEIGHT;
|
let rotate_button_y = bottom - BUTTON_HEIGHT;
|
||||||
let rotate_button_position = Point2DI32::new(ROTATE_PANEL_X, rotate_button_y);
|
let rotate_button_position = Point2DI32::new(ROTATE_PANEL_X, rotate_button_y);
|
||||||
if self.draw_button(device,
|
if debug_ui.ui.draw_button(device,
|
||||||
debug_ui,
|
event,
|
||||||
event,
|
rotate_button_position,
|
||||||
rotate_button_position,
|
&self.rotate_texture) {
|
||||||
&self.rotate_texture) {
|
|
||||||
self.rotate_panel_visible = !self.rotate_panel_visible;
|
self.rotate_panel_visible = !self.rotate_panel_visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
let zoom_in_button_x = ROTATE_PANEL_X + BUTTON_WIDTH + PADDING;
|
let zoom_in_button_x = ROTATE_PANEL_X + BUTTON_WIDTH + PADDING;
|
||||||
let zoom_in_button_position = Point2DI32::new(zoom_in_button_x, rotate_button_y);
|
let zoom_in_button_position = Point2DI32::new(zoom_in_button_x, rotate_button_y);
|
||||||
if self.draw_button(device,
|
if debug_ui.ui.draw_button(device,
|
||||||
debug_ui,
|
event,
|
||||||
event,
|
zoom_in_button_position,
|
||||||
zoom_in_button_position,
|
&self.zoom_in_texture) {
|
||||||
&self.zoom_in_texture) {
|
|
||||||
*action = UIAction::ZoomIn;
|
*action = UIAction::ZoomIn;
|
||||||
}
|
}
|
||||||
|
|
||||||
let zoom_out_button_x = ROTATE_PANEL_X + (BUTTON_WIDTH + PADDING) * 2;
|
let zoom_out_button_x = ROTATE_PANEL_X + (BUTTON_WIDTH + PADDING) * 2;
|
||||||
let zoom_out_button_position = Point2DI32::new(zoom_out_button_x, rotate_button_y);
|
let zoom_out_button_position = Point2DI32::new(zoom_out_button_x, rotate_button_y);
|
||||||
if self.draw_button(device,
|
if debug_ui.ui.draw_button(device,
|
||||||
debug_ui,
|
event,
|
||||||
event,
|
zoom_out_button_position,
|
||||||
zoom_out_button_position,
|
&self.zoom_out_texture) {
|
||||||
&self.zoom_out_texture) {
|
|
||||||
*action = UIAction::ZoomOut;
|
*action = UIAction::ZoomOut;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -293,23 +271,6 @@ impl<D> DemoUI<D> where D: Device {
|
||||||
debug_ui.ui.draw_solid_rect(device, slider_knob_rect, TEXT_COLOR);
|
debug_ui.ui.draw_solid_rect(device, slider_knob_rect, TEXT_COLOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_button(&self,
|
|
||||||
device: &D,
|
|
||||||
debug_ui: &mut DebugUI<D>,
|
|
||||||
event: &mut UIEvent,
|
|
||||||
origin: Point2DI32,
|
|
||||||
texture: &D::Texture)
|
|
||||||
-> bool {
|
|
||||||
let button_rect = RectI32::new(origin, Point2DI32::new(BUTTON_WIDTH, BUTTON_HEIGHT));
|
|
||||||
debug_ui.ui.draw_solid_rounded_rect(device, button_rect, WINDOW_COLOR);
|
|
||||||
debug_ui.ui.draw_rounded_rect_outline(device, button_rect, OUTLINE_COLOR);
|
|
||||||
debug_ui.ui.draw_texture(device,
|
|
||||||
origin + Point2DI32::new(PADDING, PADDING),
|
|
||||||
texture,
|
|
||||||
BUTTON_ICON_COLOR);
|
|
||||||
event.handle_mouse_down_in_rect(button_rect).is_some()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn draw_effects_switch(&self,
|
fn draw_effects_switch(&self,
|
||||||
device: &D,
|
device: &D,
|
||||||
debug_ui: &mut DebugUI<D>,
|
debug_ui: &mut DebugUI<D>,
|
||||||
|
@ -325,103 +286,12 @@ impl<D> DemoUI<D> where D: Device {
|
||||||
|
|
||||||
let switch_x = PADDING + EFFECTS_PANEL_WIDTH - (SWITCH_SIZE + PADDING);
|
let switch_x = PADDING + EFFECTS_PANEL_WIDTH - (SWITCH_SIZE + PADDING);
|
||||||
let switch_y = window_y + PADDING + (BUTTON_HEIGHT + PADDING) * index;
|
let switch_y = window_y + PADDING + (BUTTON_HEIGHT + PADDING) * index;
|
||||||
self.draw_text_switch(device,
|
debug_ui.ui.draw_text_switch(device,
|
||||||
debug_ui,
|
event,
|
||||||
event,
|
Point2DI32::new(switch_x, switch_y),
|
||||||
Point2DI32::new(switch_x, switch_y),
|
"Off",
|
||||||
"Off",
|
"On",
|
||||||
"On",
|
value)
|
||||||
value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn draw_text_switch(&self,
|
|
||||||
device: &D,
|
|
||||||
debug_ui: &mut DebugUI<D>,
|
|
||||||
event: &mut UIEvent,
|
|
||||||
origin: Point2DI32,
|
|
||||||
off_text: &str,
|
|
||||||
on_text: &str,
|
|
||||||
mut value: bool)
|
|
||||||
-> bool {
|
|
||||||
value = self.draw_switch(device, debug_ui, event, origin, value);
|
|
||||||
|
|
||||||
let off_size = debug_ui.ui.measure_text(off_text);
|
|
||||||
let on_size = debug_ui.ui.measure_text(on_text);
|
|
||||||
let off_offset = SWITCH_HALF_SIZE / 2 - off_size / 2;
|
|
||||||
let on_offset = SWITCH_HALF_SIZE + SWITCH_HALF_SIZE / 2 - on_size / 2;
|
|
||||||
let text_top = BUTTON_TEXT_OFFSET;
|
|
||||||
|
|
||||||
debug_ui.ui.draw_text(device,
|
|
||||||
off_text,
|
|
||||||
origin + Point2DI32::new(off_offset, text_top),
|
|
||||||
!value);
|
|
||||||
debug_ui.ui.draw_text(device,
|
|
||||||
on_text,
|
|
||||||
origin + Point2DI32::new(on_offset, text_top),
|
|
||||||
value);
|
|
||||||
|
|
||||||
value
|
|
||||||
}
|
|
||||||
|
|
||||||
fn draw_image_switch(&self,
|
|
||||||
device: &D,
|
|
||||||
debug_ui: &mut DebugUI<D>,
|
|
||||||
event: &mut UIEvent,
|
|
||||||
origin: Point2DI32,
|
|
||||||
off_texture: &D::Texture,
|
|
||||||
on_texture: &D::Texture,
|
|
||||||
mut value: bool)
|
|
||||||
-> bool {
|
|
||||||
value = self.draw_switch(device, debug_ui, event, origin, value);
|
|
||||||
|
|
||||||
let off_offset = SWITCH_HALF_SIZE / 2 - device.texture_size(off_texture).x() / 2;
|
|
||||||
let on_offset = SWITCH_HALF_SIZE + SWITCH_HALF_SIZE / 2 -
|
|
||||||
device.texture_size(on_texture).x() / 2;
|
|
||||||
|
|
||||||
let off_color = if !value { WINDOW_COLOR } else { TEXT_COLOR };
|
|
||||||
let on_color = if value { WINDOW_COLOR } else { TEXT_COLOR };
|
|
||||||
|
|
||||||
debug_ui.ui.draw_texture(device,
|
|
||||||
origin + Point2DI32::new(off_offset, PADDING),
|
|
||||||
off_texture,
|
|
||||||
off_color);
|
|
||||||
debug_ui.ui.draw_texture(device,
|
|
||||||
origin + Point2DI32::new(on_offset, PADDING),
|
|
||||||
on_texture,
|
|
||||||
on_color);
|
|
||||||
|
|
||||||
value
|
|
||||||
}
|
|
||||||
|
|
||||||
fn draw_switch(&self,
|
|
||||||
device: &D,
|
|
||||||
debug_ui: &mut DebugUI<D>,
|
|
||||||
event: &mut UIEvent,
|
|
||||||
origin: Point2DI32,
|
|
||||||
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).is_some() {
|
|
||||||
value = !value;
|
|
||||||
}
|
|
||||||
|
|
||||||
debug_ui.ui.draw_solid_rounded_rect(device, widget_rect, WINDOW_COLOR);
|
|
||||||
debug_ui.ui.draw_rounded_rect_outline(device, widget_rect, OUTLINE_COLOR);
|
|
||||||
|
|
||||||
let highlight_size = Point2DI32::new(SWITCH_HALF_SIZE, BUTTON_HEIGHT);
|
|
||||||
if !value {
|
|
||||||
debug_ui.ui.draw_solid_rounded_rect(device,
|
|
||||||
RectI32::new(origin, highlight_size),
|
|
||||||
TEXT_COLOR);
|
|
||||||
} else {
|
|
||||||
let x_offset = SWITCH_HALF_SIZE + 1;
|
|
||||||
debug_ui.ui.draw_solid_rounded_rect(device,
|
|
||||||
RectI32::new(origin + Point2DI32::new(x_offset, 0),
|
|
||||||
highlight_size),
|
|
||||||
TEXT_COLOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
value
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -434,39 +304,3 @@ pub enum UIAction {
|
||||||
ZoomOut,
|
ZoomOut,
|
||||||
Rotate(f32),
|
Rotate(f32),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum UIEvent {
|
|
||||||
None,
|
|
||||||
MouseDown(Point2DI32),
|
|
||||||
MouseDragged {
|
|
||||||
absolute_position: Point2DI32,
|
|
||||||
relative_position: Point2DI32,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UIEvent {
|
|
||||||
pub fn is_none(&self) -> bool {
|
|
||||||
match *self { UIEvent::None => true, _ => false }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_mouse_down_in_rect(&mut self, rect: RectI32) -> Option<Point2DI32> {
|
|
||||||
if let UIEvent::MouseDown(point) = *self {
|
|
||||||
if rect.contains_point(point) {
|
|
||||||
*self = UIEvent::None;
|
|
||||||
return Some(point - rect.origin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_mouse_down_or_dragged_in_rect(&mut self, rect: RectI32) -> Option<Point2DI32> {
|
|
||||||
match *self {
|
|
||||||
UIEvent::MouseDown(point) | UIEvent::MouseDragged { absolute_position: point, .. }
|
|
||||||
if rect.contains_point(point) => {
|
|
||||||
*self = UIEvent::None;
|
|
||||||
Some(point - rect.origin())
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ fixedbitset = "0.1"
|
||||||
hashbrown = "0.1"
|
hashbrown = "0.1"
|
||||||
rayon = "1.0"
|
rayon = "1.0"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_derive = "1.0"
|
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
smallvec = "0.6"
|
smallvec = "0.6"
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,6 @@
|
||||||
|
|
||||||
//! The CPU portion of Pathfinder's renderer.
|
//! The CPU portion of Pathfinder's renderer.
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate serde_derive;
|
|
||||||
|
|
||||||
pub mod builder;
|
pub mod builder;
|
||||||
pub mod gpu;
|
pub mod gpu;
|
||||||
pub mod gpu_data;
|
pub mod gpu_data;
|
||||||
|
|
142
ui/src/lib.rs
142
ui/src/lib.rs
|
@ -27,14 +27,27 @@ use serde_json;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
|
|
||||||
|
pub const PADDING: i32 = 12;
|
||||||
|
|
||||||
|
pub const BUTTON_WIDTH: i32 = PADDING * 2 + ICON_SIZE;
|
||||||
|
pub const BUTTON_HEIGHT: i32 = PADDING * 2 + ICON_SIZE;
|
||||||
|
pub const BUTTON_TEXT_OFFSET: i32 = PADDING + 36;
|
||||||
|
|
||||||
|
pub const SWITCH_SIZE: i32 = SWITCH_HALF_SIZE * 2 + 1;
|
||||||
|
|
||||||
const DEBUG_TEXTURE_VERTEX_SIZE: usize = 8;
|
const DEBUG_TEXTURE_VERTEX_SIZE: usize = 8;
|
||||||
const DEBUG_SOLID_VERTEX_SIZE: usize = 4;
|
const DEBUG_SOLID_VERTEX_SIZE: usize = 4;
|
||||||
|
|
||||||
pub const PADDING: i32 = 12;
|
const ICON_SIZE: i32 = 48;
|
||||||
|
|
||||||
|
const SWITCH_HALF_SIZE: i32 = 96;
|
||||||
|
|
||||||
pub static TEXT_COLOR: ColorU = ColorU { r: 255, g: 255, b: 255, a: 255 };
|
pub static TEXT_COLOR: ColorU = ColorU { r: 255, g: 255, b: 255, a: 255 };
|
||||||
pub static WINDOW_COLOR: ColorU = ColorU { r: 0, g: 0, b: 0, a: 255 - 90 };
|
pub static WINDOW_COLOR: ColorU = ColorU { r: 0, g: 0, b: 0, a: 255 - 90 };
|
||||||
|
|
||||||
|
static BUTTON_ICON_COLOR: ColorU = ColorU { r: 255, g: 255, b: 255, a: 255 };
|
||||||
|
static OUTLINE_COLOR: ColorU = ColorU { r: 255, g: 255, b: 255, a: 192 };
|
||||||
|
|
||||||
static INVERTED_TEXT_COLOR: ColorU = ColorU { r: 0, g: 0, b: 0, a: 255 };
|
static INVERTED_TEXT_COLOR: ColorU = ColorU { r: 0, g: 0, b: 0, a: 255 };
|
||||||
|
|
||||||
static FONT_JSON_FILENAME: &'static str = "debug-font.json";
|
static FONT_JSON_FILENAME: &'static str = "debug-font.json";
|
||||||
|
@ -409,6 +422,97 @@ impl<D> UI<D> where D: Device {
|
||||||
..RenderState::default()
|
..RenderState::default()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn draw_button(&self,
|
||||||
|
device: &D,
|
||||||
|
event: &mut UIEvent,
|
||||||
|
origin: Point2DI32,
|
||||||
|
texture: &D::Texture)
|
||||||
|
-> bool {
|
||||||
|
let button_rect = RectI32::new(origin, Point2DI32::new(BUTTON_WIDTH, BUTTON_HEIGHT));
|
||||||
|
self.draw_solid_rounded_rect(device, button_rect, WINDOW_COLOR);
|
||||||
|
self.draw_rounded_rect_outline(device, button_rect, OUTLINE_COLOR);
|
||||||
|
self.draw_texture(device,
|
||||||
|
origin + Point2DI32::new(PADDING, PADDING),
|
||||||
|
texture,
|
||||||
|
BUTTON_ICON_COLOR);
|
||||||
|
event.handle_mouse_down_in_rect(button_rect).is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_text_switch(&self,
|
||||||
|
device: &D,
|
||||||
|
event: &mut UIEvent,
|
||||||
|
origin: Point2DI32,
|
||||||
|
off_text: &str,
|
||||||
|
on_text: &str,
|
||||||
|
mut value: bool)
|
||||||
|
-> bool {
|
||||||
|
value = self.draw_switch(device, event, origin, value);
|
||||||
|
|
||||||
|
let off_size = self.measure_text(off_text);
|
||||||
|
let on_size = self.measure_text(on_text);
|
||||||
|
let off_offset = SWITCH_HALF_SIZE / 2 - off_size / 2;
|
||||||
|
let on_offset = SWITCH_HALF_SIZE + SWITCH_HALF_SIZE / 2 - on_size / 2;
|
||||||
|
let text_top = BUTTON_TEXT_OFFSET;
|
||||||
|
|
||||||
|
self.draw_text(device, off_text, origin + Point2DI32::new(off_offset, text_top), !value);
|
||||||
|
self.draw_text(device, on_text, origin + Point2DI32::new(on_offset, text_top), value);
|
||||||
|
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_image_switch(&self,
|
||||||
|
device: &D,
|
||||||
|
event: &mut UIEvent,
|
||||||
|
origin: Point2DI32,
|
||||||
|
off_texture: &D::Texture,
|
||||||
|
on_texture: &D::Texture,
|
||||||
|
mut value: bool)
|
||||||
|
-> bool {
|
||||||
|
value = self.draw_switch(device, event, origin, value);
|
||||||
|
|
||||||
|
let off_offset = SWITCH_HALF_SIZE / 2 - device.texture_size(off_texture).x() / 2;
|
||||||
|
let on_offset = SWITCH_HALF_SIZE + SWITCH_HALF_SIZE / 2 -
|
||||||
|
device.texture_size(on_texture).x() / 2;
|
||||||
|
|
||||||
|
let off_color = if !value { WINDOW_COLOR } else { TEXT_COLOR };
|
||||||
|
let on_color = if value { WINDOW_COLOR } else { TEXT_COLOR };
|
||||||
|
|
||||||
|
self.draw_texture(device,
|
||||||
|
origin + Point2DI32::new(off_offset, PADDING),
|
||||||
|
off_texture,
|
||||||
|
off_color);
|
||||||
|
self.draw_texture(device,
|
||||||
|
origin + Point2DI32::new(on_offset, PADDING),
|
||||||
|
on_texture,
|
||||||
|
on_color);
|
||||||
|
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_switch(&self, device: &D, event: &mut UIEvent, origin: Point2DI32, 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).is_some() {
|
||||||
|
value = !value;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.draw_solid_rounded_rect(device, widget_rect, WINDOW_COLOR);
|
||||||
|
self.draw_rounded_rect_outline(device, widget_rect, OUTLINE_COLOR);
|
||||||
|
|
||||||
|
let highlight_size = Point2DI32::new(SWITCH_HALF_SIZE, BUTTON_HEIGHT);
|
||||||
|
if !value {
|
||||||
|
self.draw_solid_rounded_rect(device, RectI32::new(origin, highlight_size), TEXT_COLOR);
|
||||||
|
} else {
|
||||||
|
let x_offset = SWITCH_HALF_SIZE + 1;
|
||||||
|
self.draw_solid_rounded_rect(device,
|
||||||
|
RectI32::new(origin + Point2DI32::new(x_offset, 0),
|
||||||
|
highlight_size),
|
||||||
|
TEXT_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DebugTextureProgram<D> where D: Device {
|
struct DebugTextureProgram<D> where D: Device {
|
||||||
|
@ -575,3 +679,39 @@ fn set_color_uniform<D>(device: &D, uniform: &D::Uniform, color: ColorU) where D
|
||||||
let color = F32x4::new(color.r as f32, color.g as f32, color.b as f32, color.a as f32);
|
let color = F32x4::new(color.r as f32, color.g as f32, color.b as f32, color.a as f32);
|
||||||
device.set_uniform(uniform, UniformData::Vec4(color * F32x4::splat(1.0 / 255.0)));
|
device.set_uniform(uniform, UniformData::Vec4(color * F32x4::splat(1.0 / 255.0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum UIEvent {
|
||||||
|
None,
|
||||||
|
MouseDown(Point2DI32),
|
||||||
|
MouseDragged {
|
||||||
|
absolute_position: Point2DI32,
|
||||||
|
relative_position: Point2DI32,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UIEvent {
|
||||||
|
pub fn is_none(&self) -> bool {
|
||||||
|
match *self { UIEvent::None => true, _ => false }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_mouse_down_in_rect(&mut self, rect: RectI32) -> Option<Point2DI32> {
|
||||||
|
if let UIEvent::MouseDown(point) = *self {
|
||||||
|
if rect.contains_point(point) {
|
||||||
|
*self = UIEvent::None;
|
||||||
|
return Some(point - rect.origin());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_mouse_down_or_dragged_in_rect(&mut self, rect: RectI32) -> Option<Point2DI32> {
|
||||||
|
match *self {
|
||||||
|
UIEvent::MouseDown(point) | UIEvent::MouseDragged { absolute_position: point, .. }
|
||||||
|
if rect.contains_point(point) => {
|
||||||
|
*self = UIEvent::None;
|
||||||
|
Some(point - rect.origin())
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue