FancyColor -> Fill (#334)

This commit is contained in:
Michael Kirk 2020-09-17 23:34:25 -07:00 committed by GitHub
parent 16ed4ca457
commit cb84b729f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 52 additions and 59 deletions

View File

@ -3,9 +3,7 @@ use abstutil::Counter;
use geom::{Circle, Distance, Line, Polygon, Pt2D}; use geom::{Circle, Distance, Line, Polygon, Pt2D};
use map_model::{BuildingID, BusStopID, IntersectionID, LaneID, Map, ParkingLotID, RoadID}; use map_model::{BuildingID, BusStopID, IntersectionID, LaneID, Map, ParkingLotID, RoadID};
use std::collections::HashMap; use std::collections::HashMap;
use widgetry::{ use widgetry::{Color, Drawable, EventCtx, Fill, GeomBatch, Line, LinearGradient, Text, Widget};
Color, Drawable, EventCtx, FancyColor, GeomBatch, Line, LinearGradient, Text, Widget,
};
pub struct ColorDiscrete<'a> { pub struct ColorDiscrete<'a> {
map: &'a Map, map: &'a Map,
@ -120,8 +118,8 @@ impl ColorLegend {
let n = scale.0.len(); let n = scale.0.len();
let mut batch = GeomBatch::new(); let mut batch = GeomBatch::new();
let width_each = width / ((n - 1) as f64); let width_each = width / ((n - 1) as f64);
batch.fancy_push( batch.push(
FancyColor::LinearGradient(LinearGradient { Fill::LinearGradient(LinearGradient {
line: Line::must_new(Pt2D::new(0.0, 0.0), Pt2D::new(width, 0.0)), line: Line::must_new(Pt2D::new(0.0, 0.0), Pt2D::new(width, 0.0)),
stops: scale stops: scale
.0 .0

View File

@ -10,7 +10,7 @@ use rand::SeedableRng;
use rand_xorshift::XorShiftRng; use rand_xorshift::XorShiftRng;
use std::collections::HashSet; use std::collections::HashSet;
use widgetry::{ use widgetry::{
hotkey, lctrl, Btn, Checkbox, Color, Drawable, EventCtx, FancyColor, GeomBatch, GfxCtx, hotkey, lctrl, Btn, Checkbox, Color, Drawable, EventCtx, Fill, GeomBatch, GfxCtx,
HorizontalAlignment, Key, Line, LinePlot, Outcome, Panel, PlotOptions, Series, Text, TextExt, HorizontalAlignment, Key, Line, LinePlot, Outcome, Panel, PlotOptions, Series, Text, TextExt,
Texture, UpdateType, VerticalAlignment, Widget, GUI, Texture, UpdateType, VerticalAlignment, Widget, GUI,
}; };
@ -216,7 +216,7 @@ fn setup_texture_demo(ctx: &mut EventCtx) -> Drawable {
rect = rect.translate(200.0, 900.0); rect = rect.translate(200.0, 900.0);
// Texture::NOOP should always be pure white, since all "non-textured" colors are multiplied by // Texture::NOOP should always be pure white, since all "non-textured" colors are multiplied by
// Texture::NOOP (Texture::NOOP.0 == 0) // Texture::NOOP (Texture::NOOP.0 == 0)
batch.fancy_push(FancyColor::Texture(Texture::NOOP), rect); batch.push(Texture::NOOP, rect);
let triangle = geom::Triangle { let triangle = geom::Triangle {
pt1: Pt2D::new(0.0, 100.0), pt1: Pt2D::new(0.0, 100.0),
@ -225,19 +225,16 @@ fn setup_texture_demo(ctx: &mut EventCtx) -> Drawable {
}; };
let mut triangle_poly = Polygon::from_triangle(&triangle); let mut triangle_poly = Polygon::from_triangle(&triangle);
triangle_poly = triangle_poly.translate(400.0, 900.0); triangle_poly = triangle_poly.translate(400.0, 900.0);
batch.fancy_push(FancyColor::Texture(Texture::SAND), triangle_poly); batch.push(Texture::SAND, triangle_poly);
let circle = geom::Circle::new(Pt2D::new(50.0, 50.0), geom::Distance::meters(50.0)); let circle = geom::Circle::new(Pt2D::new(50.0, 50.0), geom::Distance::meters(50.0));
let mut circle_poly = circle.to_polygon(); let mut circle_poly = circle.to_polygon();
circle_poly = circle_poly.translate(600.0, 900.0); circle_poly = circle_poly.translate(600.0, 900.0);
batch.fancy_push( batch.push(
FancyColor::ColoredTexture(Color::RED, Texture::SAND), Fill::ColoredTexture(Color::RED, Texture::SAND),
circle_poly.clone(),
);
batch.fancy_push(
FancyColor::Texture(Texture::SNOW_PERSON),
circle_poly.clone(), circle_poly.clone(),
); );
batch.push(Texture::SNOW_PERSON, circle_poly.clone());
batch.upload(ctx) batch.upload(ctx)
} }

View File

@ -92,7 +92,7 @@ impl WindowAdapter {
} }
} }
/// Uploads a sprite sheet of textures to the GPU so they can be used by FancyColor::Texture and /// Uploads a sprite sheet of textures to the GPU so they can be used by Fill::Texture and
/// friends to paint shapes. /// friends to paint shapes.
/// ///
/// `path` - image file which is a grid of images. /// `path` - image file which is a grid of images.
@ -169,7 +169,7 @@ fn load_textures(
); );
// In order to avoid branching in our shader logic, all shapes are rendered with a texture. // In order to avoid branching in our shader logic, all shapes are rendered with a texture.
// Even "non-textured" styles like FancyColor::RGBA, use a "default" no-op (pure white) texture, // Even "non-textured" styles like Fill::Color, use a "default" no-op (pure white) texture,
// which we generate here. // which we generate here.
let mut formatted_pixels: Vec<image::Rgba<u8>> = let mut formatted_pixels: Vec<image::Rgba<u8>> =
vec![image::Rgba([255; 4]); (sprite_length * sprite_length) as usize]; vec![image::Rgba([255; 4]); (sprite_length * sprite_length) as usize];

View File

@ -20,10 +20,9 @@ impl fmt::Display for Color {
} }
} }
// TODO Maybe needs a better name
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum FancyColor { pub enum Fill {
RGBA(Color), Color(Color),
LinearGradient(LinearGradient), LinearGradient(LinearGradient),
/// Once uploaded, textures are addressed by their id, starting from 1, from left to right, top /// Once uploaded, textures are addressed by their id, starting from 1, from left to right, top
@ -45,7 +44,7 @@ pub enum FancyColor {
ColoredTexture(Color, Texture), ColoredTexture(Color, Texture),
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq)]
pub struct Texture(u32); pub struct Texture(u32);
#[allow(dead_code)] #[allow(dead_code)]
@ -149,7 +148,7 @@ pub struct LinearGradient {
} }
impl LinearGradient { impl LinearGradient {
pub(crate) fn new(lg: &usvg::LinearGradient) -> FancyColor { pub(crate) fn new(lg: &usvg::LinearGradient) -> Fill {
let line = Line::must_new(Pt2D::new(lg.x1, lg.y1), Pt2D::new(lg.x2, lg.y2)); let line = Line::must_new(Pt2D::new(lg.x1, lg.y1), Pt2D::new(lg.x2, lg.y2));
let mut stops = Vec::new(); let mut stops = Vec::new();
for stop in &lg.stops { for stop in &lg.stops {
@ -161,7 +160,7 @@ impl LinearGradient {
); );
stops.push((stop.offset.value(), color)); stops.push((stop.offset.value(), color));
} }
FancyColor::LinearGradient(LinearGradient { line, stops }) Fill::LinearGradient(LinearGradient { line, stops })
} }
fn interp(&self, pt: Pt2D) -> Color { fn interp(&self, pt: Pt2D) -> Color {
@ -196,18 +195,30 @@ fn lerp(pct: f64, (x1, x2): (f32, f32)) -> f32 {
x1 + (pct as f32) * (x2 - x1) x1 + (pct as f32) * (x2 - x1)
} }
impl FancyColor { impl Fill {
pub(crate) fn shader_style(&self, pt: Pt2D) -> [f32; 5] { pub(crate) fn shader_style(&self, pt: Pt2D) -> [f32; 5] {
match self { match self {
FancyColor::RGBA(c) => [c.r, c.g, c.b, c.a, 0.0], Fill::Color(c) => [c.r, c.g, c.b, c.a, 0.0],
FancyColor::LinearGradient(ref lg) => { Fill::LinearGradient(ref lg) => {
let c = lg.interp(pt); let c = lg.interp(pt);
[c.r, c.g, c.b, c.a, 0.0] [c.r, c.g, c.b, c.a, 0.0]
} }
FancyColor::Texture(texture) => [1.0, 1.0, 1.0, 1.0, texture.0 as f32], Fill::Texture(texture) => [1.0, 1.0, 1.0, 1.0, texture.0 as f32],
FancyColor::ColoredTexture(color, texture) => { Fill::ColoredTexture(color, texture) => {
[color.r, color.g, color.b, color.a, texture.0 as f32] [color.r, color.g, color.b, color.a, texture.0 as f32]
} }
} }
} }
} }
impl std::convert::From<Color> for Fill {
fn from(color: Color) -> Fill {
Fill::Color(color)
}
}
impl std::convert::From<Texture> for Fill {
fn from(texture: Texture) -> Fill {
Fill::Texture(texture)
}
}

View File

@ -1,14 +1,13 @@
use crate::widgets::button::BtnBuilder; use crate::widgets::button::BtnBuilder;
use crate::{ use crate::{
svg, Btn, Color, DeferDraw, Drawable, EventCtx, FancyColor, GfxCtx, Prerender, ScreenDims, svg, Btn, Color, DeferDraw, Drawable, EventCtx, Fill, GfxCtx, Prerender, ScreenDims, Widget,
Widget,
}; };
use geom::{Angle, Bounds, Polygon, Pt2D}; use geom::{Angle, Bounds, Polygon, Pt2D};
/// A mutable builder for a group of colored polygons. /// A mutable builder for a group of colored polygons.
#[derive(Clone)] #[derive(Clone)]
pub struct GeomBatch { pub struct GeomBatch {
pub(crate) list: Vec<(FancyColor, Polygon)>, pub(crate) list: Vec<(Fill, Polygon)>,
pub autocrop_dims: bool, pub autocrop_dims: bool,
} }
@ -24,33 +23,21 @@ impl GeomBatch {
/// Creates a batch of colored polygons. /// Creates a batch of colored polygons.
pub fn from(list: Vec<(Color, Polygon)>) -> GeomBatch { pub fn from(list: Vec<(Color, Polygon)>) -> GeomBatch {
GeomBatch { GeomBatch {
list: list list: list.into_iter().map(|(c, p)| (Fill::Color(c), p)).collect(),
.into_iter()
.map(|(c, p)| (FancyColor::RGBA(c), p))
.collect(),
autocrop_dims: true, autocrop_dims: true,
} }
} }
/// Adds a single colored polygon. // Adds a single polygon, painted according to `Fill`
pub fn push(&mut self, color: Color, p: Polygon) { pub fn push<F: Into<Fill>>(&mut self, fill: F, p: Polygon) {
self.list.push((FancyColor::RGBA(color), p)); self.list.push((fill.into(), p));
}
// TODO Not sure about this
pub fn fancy_push(&mut self, color: FancyColor, p: Polygon) {
self.list.push((color, p));
} }
/// Applies one color to many polygons. /// Applies one Fill to many polygons.
pub fn extend(&mut self, color: Color, polys: Vec<Polygon>) { pub fn extend<F: Into<Fill>>(&mut self, fill: F, polys: Vec<Polygon>) {
let fill = fill.into();
for p in polys { for p in polys {
self.list.push((FancyColor::RGBA(color), p)); self.list.push((fill.clone(), p));
}
}
pub fn fancy_extend(&mut self, color: FancyColor, polys: Vec<Polygon>) {
for p in polys {
self.list.push((color.clone(), p));
} }
} }
@ -60,7 +47,7 @@ impl GeomBatch {
} }
/// Returns the colored polygons in this batch, destroying the batch. /// Returns the colored polygons in this batch, destroying the batch.
pub fn consume(self) -> Vec<(FancyColor, Polygon)> { pub fn consume(self) -> Vec<(Fill, Polygon)> {
self.list self.list
} }
@ -155,7 +142,7 @@ impl GeomBatch {
/// Transforms all colors in a batch. /// Transforms all colors in a batch.
pub fn color(mut self, transformation: RewriteColor) -> GeomBatch { pub fn color(mut self, transformation: RewriteColor) -> GeomBatch {
for (fancy, _) in &mut self.list { for (fancy, _) in &mut self.list {
if let FancyColor::RGBA(ref mut c) = fancy { if let Fill::Color(ref mut c) = fancy {
*c = transformation.apply(*c); *c = transformation.apply(*c);
} }
} }

View File

@ -56,7 +56,7 @@ mod backend {
pub use crate::backend::Drawable; pub use crate::backend::Drawable;
pub use crate::canvas::{Canvas, HorizontalAlignment, VerticalAlignment}; pub use crate::canvas::{Canvas, HorizontalAlignment, VerticalAlignment};
pub use crate::color::{Color, FancyColor, LinearGradient, Texture}; pub use crate::color::{Color, Fill, LinearGradient, Texture};
pub use crate::drawing::{GfxCtx, Prerender}; pub use crate::drawing::{GfxCtx, Prerender};
pub use crate::event::{hotkey, hotkeys, lctrl, Event, Key, MultiKey}; pub use crate::event::{hotkey, hotkeys, lctrl, Event, Key, MultiKey};
pub use crate::event_ctx::{EventCtx, UpdateType}; pub use crate::event_ctx::{EventCtx, UpdateType};

View File

@ -1,4 +1,4 @@
use crate::{Color, FancyColor, GeomBatch, LinearGradient, Prerender}; use crate::{Color, Fill, GeomBatch, LinearGradient, Prerender};
use abstutil::VecMap; use abstutil::VecMap;
use geom::{Bounds, Polygon, Pt2D}; use geom::{Bounds, Polygon, Pt2D};
use lyon::math::Point; use lyon::math::Point;
@ -47,7 +47,7 @@ pub fn add_svg_inner(
let mut fill_tess = tessellation::FillTessellator::new(); let mut fill_tess = tessellation::FillTessellator::new();
let mut stroke_tess = tessellation::StrokeTessellator::new(); let mut stroke_tess = tessellation::StrokeTessellator::new();
// TODO This breaks on start.svg; the order there matters. color1, color2, then color1 again. // TODO This breaks on start.svg; the order there matters. color1, color2, then color1 again.
let mut mesh_per_color: VecMap<FancyColor, VertexBuffers<_, u16>> = VecMap::new(); let mut mesh_per_color: VecMap<Fill, VertexBuffers<_, u16>> = VecMap::new();
for node in svg_tree.root().descendants() { for node in svg_tree.root().descendants() {
if let usvg::NodeKind::Path(ref p) = *node.borrow() { if let usvg::NodeKind::Path(ref p) = *node.borrow() {
@ -79,7 +79,7 @@ pub fn add_svg_inner(
} }
for (color, mesh) in mesh_per_color.consume() { for (color, mesh) in mesh_per_color.consume() {
batch.fancy_push( batch.push(
color, color,
Polygon::precomputed( Polygon::precomputed(
mesh.vertices mesh.vertices
@ -204,7 +204,7 @@ fn convert_stroke(
s: &usvg::Stroke, s: &usvg::Stroke,
tolerance: f32, tolerance: f32,
tree: &usvg::Tree, tree: &usvg::Tree,
) -> (FancyColor, tessellation::StrokeOptions) { ) -> (Fill, tessellation::StrokeOptions) {
let color = convert_color(&s.paint, s.opacity.value(), tree); let color = convert_color(&s.paint, s.opacity.value(), tree);
let linecap = match s.linecap { let linecap = match s.linecap {
usvg::LineCap::Butt => tessellation::LineCap::Butt, usvg::LineCap::Butt => tessellation::LineCap::Butt,
@ -225,9 +225,9 @@ fn convert_stroke(
(color, opt) (color, opt)
} }
fn convert_color(paint: &usvg::Paint, opacity: f64, tree: &usvg::Tree) -> FancyColor { fn convert_color(paint: &usvg::Paint, opacity: f64, tree: &usvg::Tree) -> Fill {
match paint { match paint {
usvg::Paint::Color(c) => FancyColor::RGBA(Color::rgba( usvg::Paint::Color(c) => Fill::Color(Color::rgba(
c.red as usize, c.red as usize,
c.green as usize, c.green as usize,
c.blue as usize, c.blue as usize,