mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-25 07:25:47 +03:00
FancyColor -> Fill (#334)
This commit is contained in:
parent
16ed4ca457
commit
cb84b729f6
@ -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
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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];
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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};
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user