mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Add support for TextInput widget, rename widgets module to widget, update to glyph_brush 0.7.0
This commit is contained in:
parent
75adcb20e8
commit
e4bc035a62
154
Cargo.lock
generated
154
Cargo.lock
generated
@ -1,5 +1,15 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "ab_glyph"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26a685fe66654266f321a8b572660953f4df36a2135706503a4c89981d76e1a2"
|
||||
dependencies = [
|
||||
"ab_glyph_rasterizer",
|
||||
"owned_ttf_parser 0.8.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ab_glyph_rasterizer"
|
||||
version = "0.1.3"
|
||||
@ -117,6 +127,15 @@ dependencies = [
|
||||
"num-traits 0.2.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "approx"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f2a05fd1bd10b2527e20a2cd32d8873d115b8b39fe219ee25f42a8aca6ba278"
|
||||
dependencies = [
|
||||
"num-traits 0.2.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arc-swap"
|
||||
version = "0.4.7"
|
||||
@ -192,7 +211,7 @@ dependencies = [
|
||||
"async-task",
|
||||
"broadcaster",
|
||||
"crossbeam-channel 0.4.4",
|
||||
"crossbeam-deque",
|
||||
"crossbeam-deque 0.7.3",
|
||||
"crossbeam-utils 0.7.2",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
@ -717,6 +736,12 @@ dependencies = [
|
||||
"syn 1.0.42",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const_fn"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c478836e029dcef17fb47c89023448c64f781a046e0300e257ad8225ae59afab"
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.5"
|
||||
@ -943,7 +968,7 @@ checksum = "2d818a4990769aac0c7ff1360e233ef3a41adcb009ebb2036bf6915eb0f6b23c"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"crossbeam-channel 0.3.9",
|
||||
"crossbeam-deque",
|
||||
"crossbeam-deque 0.7.3",
|
||||
"crossbeam-epoch 0.7.2",
|
||||
"crossbeam-queue 0.1.2",
|
||||
"crossbeam-utils 0.6.6",
|
||||
@ -968,6 +993,16 @@ dependencies = [
|
||||
"maybe-uninit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"crossbeam-utils 0.8.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.7.3"
|
||||
@ -979,6 +1014,17 @@ dependencies = [
|
||||
"maybe-uninit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"crossbeam-epoch 0.9.0",
|
||||
"crossbeam-utils 0.8.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.7.2"
|
||||
@ -1008,6 +1054,20 @@ dependencies = [
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0f606a85340376eef0d6d8fec399e6d4a544d648386c6645eb6d0653b27d9f"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"const_fn",
|
||||
"crossbeam-utils 0.8.0",
|
||||
"lazy_static",
|
||||
"memoffset",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-queue"
|
||||
version = "0.1.2"
|
||||
@ -1049,6 +1109,18 @@ dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec91540d98355f690a86367e566ecad2e9e579f230230eb7c21398372be73ea5"
|
||||
dependencies = [
|
||||
"autocfg 1.0.1",
|
||||
"cfg-if 1.0.0",
|
||||
"const_fn",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossterm"
|
||||
version = "0.17.7"
|
||||
@ -1858,26 +1930,40 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "glyph_brush"
|
||||
version = "0.6.3"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fca6f9d679bff1322c76c9a1ad4b8553b30a94f3f75bea6936e19032c2f2ec3"
|
||||
checksum = "afd3e2cfd503a5218dd56172a8bf7c8655a4a7cf745737c606a6edfeea1b343f"
|
||||
dependencies = [
|
||||
"glyph_brush_draw_cache",
|
||||
"glyph_brush_layout",
|
||||
"log",
|
||||
"ordered-float 1.1.0",
|
||||
"rustc-hash",
|
||||
"rusttype 0.8.3",
|
||||
"twox-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glyph_brush_layout"
|
||||
version = "0.1.9"
|
||||
name = "glyph_brush_draw_cache"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b70adc570f1dc71b6b32e241cbcc2b42175f5aea71951fbf41e68b04aec24c7"
|
||||
checksum = "8cef969a091be5565c2c10b31fd2f115cbeed9f783a27c96ae240ff8ceee067c"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"rusttype 0.8.3",
|
||||
"ab_glyph",
|
||||
"crossbeam-channel 0.5.0",
|
||||
"crossbeam-deque 0.8.0",
|
||||
"linked-hash-map",
|
||||
"rayon",
|
||||
"rustc-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glyph_brush_layout"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10bc06d530bf20c1902f1b02799ab7372ff43f6119770c49b0bc3f21bd148820"
|
||||
dependencies = [
|
||||
"ab_glyph",
|
||||
"approx 0.4.0",
|
||||
"xi-unicode",
|
||||
]
|
||||
|
||||
@ -2066,12 +2152,12 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "iced_core"
|
||||
version = "0.2.1"
|
||||
source = "git+https://github.com/Imberflur/iced?branch=text-clone#0a775191abad5787af3aaa302d5599ef12060264"
|
||||
source = "git+https://github.com/Imberflur/iced#cf514910c2c0db8633377d2719b244e388774cee"
|
||||
|
||||
[[package]]
|
||||
name = "iced_futures"
|
||||
version = "0.1.2"
|
||||
source = "git+https://github.com/Imberflur/iced?branch=text-clone#0a775191abad5787af3aaa302d5599ef12060264"
|
||||
source = "git+https://github.com/Imberflur/iced#cf514910c2c0db8633377d2719b244e388774cee"
|
||||
dependencies = [
|
||||
"futures 0.3.5",
|
||||
"log",
|
||||
@ -2081,11 +2167,10 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "iced_native"
|
||||
version = "0.2.2"
|
||||
source = "git+https://github.com/Imberflur/iced?branch=text-clone#0a775191abad5787af3aaa302d5599ef12060264"
|
||||
source = "git+https://github.com/Imberflur/iced#cf514910c2c0db8633377d2719b244e388774cee"
|
||||
dependencies = [
|
||||
"iced_core",
|
||||
"iced_futures",
|
||||
"raw-window-handle",
|
||||
"twox-hash",
|
||||
"unicode-segmentation",
|
||||
]
|
||||
@ -3112,7 +3197,16 @@ version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f923fb806c46266c02ab4a5b239735c144bdeda724a50ed058e5226f594cde3"
|
||||
dependencies = [
|
||||
"ttf-parser",
|
||||
"ttf-parser 0.6.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "owned_ttf_parser"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb477c7fd2a3a6e04e1dc6ca2e4e9b04f2df702021dc5a5d1cf078c587dc59f7"
|
||||
dependencies = [
|
||||
"ttf-parser 0.8.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3627,7 +3721,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfd016f0c045ad38b5251be2c9c0ab806917f82da4d36b2a327e5166adad9270"
|
||||
dependencies = [
|
||||
"autocfg 1.0.1",
|
||||
"crossbeam-deque",
|
||||
"crossbeam-deque 0.7.3",
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
@ -3639,7 +3733,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8c4fec834fb6e6d2dd5eece3c7b432a52f0ba887cf40e595190c4107edc08bf"
|
||||
dependencies = [
|
||||
"crossbeam-channel 0.4.4",
|
||||
"crossbeam-deque",
|
||||
"crossbeam-deque 0.7.3",
|
||||
"crossbeam-utils 0.7.2",
|
||||
"lazy_static",
|
||||
"num_cpus",
|
||||
@ -3810,8 +3904,8 @@ version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f61411055101f7b60ecf1041d87fb74205fb20b0c7a723f07ef39174cf6b4c0"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"crossbeam-deque",
|
||||
"approx 0.3.2",
|
||||
"crossbeam-deque 0.7.3",
|
||||
"crossbeam-utils 0.7.2",
|
||||
"linked-hash-map",
|
||||
"num_cpus",
|
||||
@ -3827,7 +3921,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc7c727aded0be18c5b80c1640eae0ac8e396abf6fa8477d96cb37d18ee5ec59"
|
||||
dependencies = [
|
||||
"ab_glyph_rasterizer",
|
||||
"owned_ttf_parser",
|
||||
"owned_ttf_parser 0.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4590,7 +4684,7 @@ version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-deque 0.7.3",
|
||||
"crossbeam-queue 0.2.3",
|
||||
"crossbeam-utils 0.7.2",
|
||||
"futures 0.1.29",
|
||||
@ -4764,6 +4858,12 @@ version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e5d7cd7ab3e47dda6e56542f4bbf3824c15234958c6e1bd6aaa347e93499fdc"
|
||||
|
||||
[[package]]
|
||||
name = "ttf-parser"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d973cfa0e6124166b50a1105a67c85de40bbc625082f35c0f56f84cb1fb0a827"
|
||||
|
||||
[[package]]
|
||||
name = "tui"
|
||||
version = "0.10.0"
|
||||
@ -4788,7 +4888,7 @@ version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3bfd5b7557925ce778ff9b9ef90e3ade34c524b5ff10e239c69a42d546d2af56"
|
||||
dependencies = [
|
||||
"rand 0.4.6",
|
||||
"rand 0.7.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4936,7 +5036,7 @@ version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2657d8704e5e0be82b60157c8dbc71a269273ad766984508fdc54030a0690c4d"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"approx 0.3.2",
|
||||
"num-integer",
|
||||
"num-traits 0.2.12",
|
||||
"rustc_version",
|
||||
@ -4949,7 +5049,7 @@ name = "vek"
|
||||
version = "0.12.0"
|
||||
source = "git+https://gitlab.com/veloren/vek.git?branch=fix_intrinsics#237a78528b505f34f6dde5dc77db3b642388fe4a"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"approx 0.3.2",
|
||||
"num-integer",
|
||||
"num-traits 0.2.12",
|
||||
"rustc_version",
|
||||
@ -5301,7 +5401,7 @@ version = "0.4.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7866cab0aa01de1edf8b5d7936938a7e397ee50ce24119aef3e1eaa3b6171da"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
@ -5695,9 +5795,9 @@ checksum = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57"
|
||||
|
||||
[[package]]
|
||||
name = "xi-unicode"
|
||||
version = "0.2.1"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e71b85d8b1b8bfaf4b5c834187554d201a8cd621c2bbfa33efd41a3ecabd48b2"
|
||||
checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a"
|
||||
|
||||
[[package]]
|
||||
name = "xml-rs"
|
||||
|
@ -35,9 +35,9 @@ winit = {version = "0.22.2", features = ["serde"]}
|
||||
conrod_core = {git = "https://gitlab.com/veloren/conrod.git", branch="copypasta_0.7"}
|
||||
conrod_winit = {git = "https://gitlab.com/veloren/conrod.git", branch="copypasta_0.7"}
|
||||
euc = {git = "https://github.com/zesterer/euc.git"}
|
||||
iced = {package = "iced_native", git = "https://github.com/Imberflur/iced", branch = "text-clone"}
|
||||
iced = {package = "iced_native", git = "https://github.com/Imberflur/iced"}
|
||||
window_clipboard = "0.1.1"
|
||||
glyph_brush = "0.6.3"
|
||||
glyph_brush = "0.7.0"
|
||||
|
||||
# ECS
|
||||
specs = {git = "https://github.com/amethyst/specs.git", rev = "7a2e348ab2223818bad487695c66c43db88050a5"}
|
||||
|
@ -241,6 +241,7 @@ impl IcedState {
|
||||
.press_image(self.imgs.button_press)
|
||||
.text_color(TEXT_COLOR)
|
||||
.disabled_text_color(DISABLED_TEXT_COLOR);
|
||||
|
||||
let buttons = Column::with_children(vec![
|
||||
self.servers_button.view(
|
||||
i18n.get("common.servers"),
|
||||
@ -445,7 +446,7 @@ impl<'a> MainMenuUi {
|
||||
.unwrap()
|
||||
.read_to_end(&mut buf)
|
||||
.unwrap();
|
||||
glyph_brush::rusttype::Font::from_bytes(buf).unwrap()
|
||||
ui::ice::Font::try_from_vec(buf).unwrap()
|
||||
};
|
||||
|
||||
let mut ice_ui = IcedUi::new(window, ice_font).unwrap();
|
||||
|
@ -10,12 +10,12 @@ use vek::*;
|
||||
// Multiplied by current window size
|
||||
const GLYPH_CACHE_SIZE: u16 = 1;
|
||||
// Glyph cache tolerances
|
||||
const SCALE_TOLERANCE: f32 = 0.1;
|
||||
const SCALE_TOLERANCE: f32 = 0.5; // Note: Changed from 0.1 change back if not decent
|
||||
const POSITION_TOLERANCE: f32 = 0.1;
|
||||
|
||||
type GlyphBrush = glyph_brush::GlyphBrush<'static, (Aabr<f32>, Aabr<f32>)>;
|
||||
type GlyphBrush = glyph_brush::GlyphBrush<(Aabr<f32>, Aabr<f32>), ()>;
|
||||
|
||||
pub type Font = glyph_brush::rusttype::Font<'static>;
|
||||
pub type Font = glyph_brush::ab_glyph::FontArc;
|
||||
|
||||
pub struct Cache {
|
||||
glyph_brush: RefCell<GlyphBrush>,
|
||||
@ -35,8 +35,8 @@ impl Cache {
|
||||
|
||||
let glyph_brush = GlyphBrushBuilder::using_font(default_font)
|
||||
.initial_cache_size((glyph_cache_dims.x as u32, glyph_cache_dims.y as u32))
|
||||
.gpu_cache_scale_tolerance(SCALE_TOLERANCE)
|
||||
.gpu_cache_position_tolerance(POSITION_TOLERANCE)
|
||||
.draw_cache_scale_tolerance(SCALE_TOLERANCE)
|
||||
.draw_cache_position_tolerance(POSITION_TOLERANCE)
|
||||
.build();
|
||||
|
||||
Ok(Self {
|
||||
|
@ -1,14 +1,18 @@
|
||||
mod defaults;
|
||||
mod primitive;
|
||||
mod style;
|
||||
mod widgets;
|
||||
mod widget;
|
||||
|
||||
pub use defaults::Defaults;
|
||||
pub use style::ButtonStyle;
|
||||
|
||||
pub(self) use primitive::Primitive;
|
||||
|
||||
use super::{
|
||||
super::graphic::{self, Graphic, TexId},
|
||||
cache::Cache,
|
||||
widget, Font, Rotation,
|
||||
widget::image,
|
||||
Font, Rotation,
|
||||
};
|
||||
use crate::{
|
||||
render::{
|
||||
@ -52,36 +56,6 @@ enum State {
|
||||
Plain,
|
||||
}
|
||||
|
||||
pub enum Primitive {
|
||||
// Allocation :(
|
||||
Group {
|
||||
primitives: Vec<Primitive>,
|
||||
},
|
||||
Image {
|
||||
handle: (widget::image::Handle, Rotation),
|
||||
bounds: iced::Rectangle,
|
||||
color: Rgba<u8>,
|
||||
},
|
||||
Rectangle {
|
||||
bounds: iced::Rectangle,
|
||||
color: Rgba<u8>,
|
||||
},
|
||||
Text {
|
||||
glyphs: Vec<(
|
||||
glyph_brush::rusttype::PositionedGlyph<'static>,
|
||||
glyph_brush::Color,
|
||||
glyph_brush::FontId,
|
||||
)>,
|
||||
//size: f32,
|
||||
bounds: iced::Rectangle,
|
||||
linear_color: Rgba<f32>,
|
||||
/*font: iced::Font,
|
||||
*horizontal_alignment: iced::HorizontalAlignment,
|
||||
*vertical_alignment: iced::VerticalAlignment, */
|
||||
},
|
||||
Nothing,
|
||||
}
|
||||
|
||||
// Optimization idea inspired by what I think iced wgpu renderer may be doing:
|
||||
// Could have layers of things which don't intersect and thus can be reordered
|
||||
// arbitrarily
|
||||
@ -107,6 +81,8 @@ pub struct IcedRenderer {
|
||||
p_scale: f32,
|
||||
// Pretend dims :) (i.e. scaled)
|
||||
win_dims: Vec2<f32>,
|
||||
// Scissor for the whole window
|
||||
window_scissor: Aabr<u16>,
|
||||
|
||||
// Per-frame/update
|
||||
current_state: State,
|
||||
@ -145,6 +121,7 @@ impl IcedRenderer {
|
||||
align,
|
||||
p_scale,
|
||||
win_dims: scaled_dims,
|
||||
window_scissor: default_scissor(renderer),
|
||||
start: 0,
|
||||
//current_scissor: default_scissor(renderer),
|
||||
})
|
||||
@ -154,7 +131,7 @@ impl IcedRenderer {
|
||||
self.cache.add_graphic(graphic)
|
||||
}
|
||||
|
||||
fn image_dims(&self, handle: super::widget::image::Handle) -> (u32, u32) {
|
||||
fn image_dims(&self, handle: image::Handle) -> (u32, u32) {
|
||||
self
|
||||
.cache
|
||||
.graphic_cache()
|
||||
@ -218,7 +195,7 @@ impl IcedRenderer {
|
||||
|
||||
let brush_result = glyph_cache.process_queued(
|
||||
|rect, tex_data| {
|
||||
let offset = [rect.min.x as u16, rect.min.y as u16];
|
||||
let offset = [rect.min[0] as u16, rect.min[1] as u16];
|
||||
let size = [rect.width() as u16, rect.height() as u16];
|
||||
|
||||
let new_data = tex_data
|
||||
@ -377,6 +354,12 @@ impl IcedRenderer {
|
||||
bounds,
|
||||
color,
|
||||
} => {
|
||||
let color = srgba_to_linear(color.map(|e| e as f32 / 255.0));
|
||||
// Don't draw a transparent image.
|
||||
if color[3] == 0.0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let (graphic_id, rotation) = handle;
|
||||
let gl_aabr = self.gl_aabr(bounds);
|
||||
|
||||
@ -387,12 +370,6 @@ impl IcedRenderer {
|
||||
_ => {},
|
||||
}
|
||||
|
||||
let color = srgba_to_linear(color.map(|e| e as f32 / 255.0));
|
||||
// Don't draw a transparent image.
|
||||
if color[3] == 0.0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let resolution = Vec2::new(
|
||||
(gl_aabr.size().w * self.half_res.x).round() as u16,
|
||||
(gl_aabr.size().h * self.half_res.y).round() as u16,
|
||||
@ -445,10 +422,12 @@ impl IcedRenderer {
|
||||
self.mesh
|
||||
.push_quad(create_ui_quad(gl_aabr, uv_aabr, color, UiMode::Image));
|
||||
},
|
||||
Primitive::Rectangle { bounds, color } => {
|
||||
let color = srgba_to_linear(color.map(|e| e as f32 / 255.0));
|
||||
Primitive::Rectangle {
|
||||
bounds,
|
||||
linear_color,
|
||||
} => {
|
||||
// Don't draw a transparent rectangle.
|
||||
if color[3] == 0.0 {
|
||||
if linear_color[3] == 0.0 {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -460,7 +439,7 @@ impl IcedRenderer {
|
||||
min: Vec2::zero(),
|
||||
max: Vec2::zero(),
|
||||
},
|
||||
color,
|
||||
linear_color,
|
||||
UiMode::Geometry,
|
||||
));
|
||||
},
|
||||
@ -474,8 +453,6 @@ impl IcedRenderer {
|
||||
} => {
|
||||
self.switch_state(State::Plain);
|
||||
|
||||
// TODO: Scissor?
|
||||
|
||||
// TODO: makes sure we are not doing all this work for hidden text
|
||||
// e.g. in chat
|
||||
let glyph_cache = self.cache.glyph_cache_mut();
|
||||
@ -486,20 +463,21 @@ impl IcedRenderer {
|
||||
// Queue the glyphs to be cached.
|
||||
glyph_cache.queue_pre_positioned(
|
||||
glyphs,
|
||||
// TODO: glyph_brush should document that these need to be the same length
|
||||
vec![(); glyph_count],
|
||||
// Since we already passed in `bounds` to position the glyphs some of this
|
||||
// seems redundant...
|
||||
glyph_brush::rusttype::Rect {
|
||||
min: glyph_brush::rusttype::Point {
|
||||
x: bounds.x * self.p_scale,
|
||||
//y: (self.win_dims.y - bounds.y) * self.p_scale,
|
||||
y: bounds.y * self.p_scale,
|
||||
},
|
||||
max: glyph_brush::rusttype::Point {
|
||||
x: (bounds.x + bounds.width) * self.p_scale,
|
||||
y: (bounds.y + bounds.height) * self.p_scale,
|
||||
},
|
||||
glyph_brush::ab_glyph::Rect {
|
||||
min: glyph_brush::ab_glyph::point(
|
||||
bounds.x * self.p_scale,
|
||||
//(self.win_dims.y - bounds.y) * self.p_scale,
|
||||
bounds.y * self.p_scale,
|
||||
),
|
||||
max: glyph_brush::ab_glyph::point(
|
||||
(bounds.x + bounds.width) * self.p_scale,
|
||||
(bounds.y + bounds.height) * self.p_scale,
|
||||
),
|
||||
},
|
||||
0.0, // z (we don't use this)
|
||||
);
|
||||
|
||||
// Leave ui and verts blank to fill in when processing cached glyphs
|
||||
@ -522,6 +500,66 @@ impl IcedRenderer {
|
||||
));
|
||||
}
|
||||
},
|
||||
Primitive::Clip { bounds, content } => {
|
||||
// Check for a change in the scissor.
|
||||
let new_scissor = {
|
||||
// Calculate minimum x and y coordinates while
|
||||
// flipping y axis (from +down to +uo) and
|
||||
// moving origin from top-left corner to bottom-left
|
||||
let min_x = bounds.x;
|
||||
let min_y = self.win_dims.y - bounds.y;
|
||||
let intersection = Aabr {
|
||||
min: Vec2 {
|
||||
x: (min_x * self.p_scale) as u16,
|
||||
y: (min_y * self.p_scale) as u16,
|
||||
},
|
||||
max: Vec2 {
|
||||
x: ((min_x + bounds.width) * self.p_scale) as u16,
|
||||
y: ((min_y + bounds.height) * self.p_scale) as u16,
|
||||
},
|
||||
}
|
||||
.intersection(self.window_scissor);
|
||||
|
||||
if intersection.is_valid() {
|
||||
intersection
|
||||
} else {
|
||||
Aabr::new_empty(Vec2::zero())
|
||||
}
|
||||
};
|
||||
// Not expecting this case: new_cursor == current_scissor
|
||||
|
||||
// Finish the current command.
|
||||
// TODO: ensure we never push empty commands (make fields private & debug assert
|
||||
// in constructors?)
|
||||
self.draw_commands.push(match self.current_state {
|
||||
State::Plain => DrawCommand::plain(self.start..self.mesh.vertices().len()),
|
||||
State::Image(id) => {
|
||||
DrawCommand::image(self.start..self.mesh.vertices().len(), id)
|
||||
},
|
||||
});
|
||||
self.start = self.mesh.vertices().len();
|
||||
|
||||
self.draw_commands.push(DrawCommand::Scissor(new_scissor));
|
||||
|
||||
// TODO: support nested clips?
|
||||
// TODO: if last command is a clip changing back to the default replace it with
|
||||
// this
|
||||
|
||||
// Renderer child
|
||||
self.draw_primitive(*content, renderer);
|
||||
|
||||
// Reset scissor
|
||||
self.draw_commands.push(match self.current_state {
|
||||
State::Plain => DrawCommand::plain(self.start..self.mesh.vertices().len()),
|
||||
State::Image(id) => {
|
||||
DrawCommand::image(self.start..self.mesh.vertices().len(), id)
|
||||
},
|
||||
});
|
||||
self.start = self.mesh.vertices().len();
|
||||
|
||||
self.draw_commands
|
||||
.push(DrawCommand::Scissor(self.window_scissor));
|
||||
},
|
||||
Primitive::Nothing => {},
|
||||
}
|
||||
}
|
||||
|
31
voxygen/src/ui/ice/renderer/primitive.rs
Normal file
31
voxygen/src/ui/ice/renderer/primitive.rs
Normal file
@ -0,0 +1,31 @@
|
||||
use crate::ui::{graphic, ice::widget::image};
|
||||
|
||||
pub enum Primitive {
|
||||
// Allocation :(
|
||||
Group {
|
||||
primitives: Vec<Primitive>,
|
||||
},
|
||||
Image {
|
||||
handle: (image::Handle, graphic::Rotation),
|
||||
bounds: iced::Rectangle,
|
||||
color: vek::Rgba<u8>,
|
||||
},
|
||||
Rectangle {
|
||||
bounds: iced::Rectangle,
|
||||
linear_color: vek::Rgba<f32>,
|
||||
},
|
||||
Text {
|
||||
glyphs: Vec<glyph_brush::SectionGlyph>,
|
||||
//size: f32,
|
||||
bounds: iced::Rectangle,
|
||||
linear_color: vek::Rgba<f32>,
|
||||
/*font: iced::Font,
|
||||
*horizontal_alignment: iced::HorizontalAlignment,
|
||||
*vertical_alignment: iced::VerticalAlignment, */
|
||||
},
|
||||
Clip {
|
||||
bounds: iced::Rectangle,
|
||||
content: Box<Primitive>,
|
||||
},
|
||||
Nothing,
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
use super::super::widget::image;
|
||||
use super::super::super::widget::image;
|
||||
use iced::Color;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
|
@ -2,6 +2,7 @@ use super::super::{
|
||||
super::{widget::compound_graphic, Rotation},
|
||||
IcedRenderer, Primitive,
|
||||
};
|
||||
use common::util::srgba_to_linear;
|
||||
use compound_graphic::GraphicKind;
|
||||
use iced::{mouse, Rectangle};
|
||||
|
||||
@ -24,7 +25,10 @@ impl compound_graphic::Renderer for IcedRenderer {
|
||||
bounds,
|
||||
color,
|
||||
},
|
||||
GraphicKind::Color(color) => Primitive::Rectangle { bounds, color },
|
||||
GraphicKind::Color(color) => Primitive::Rectangle {
|
||||
bounds,
|
||||
linear_color: srgba_to_linear(color.map(|e| e as f32 * 255.0)),
|
||||
},
|
||||
})
|
||||
.collect(),
|
||||
},
|
@ -8,3 +8,4 @@ mod image;
|
||||
mod row;
|
||||
mod space;
|
||||
mod text;
|
||||
mod text_input;
|
@ -13,11 +13,15 @@ impl text::Renderer for IcedRenderer {
|
||||
let p_scale = self.p_scale;
|
||||
// TODO: would be nice if the method was mut
|
||||
let section = glyph_brush::Section {
|
||||
text: content,
|
||||
scale: glyph_brush::rusttype::Scale::uniform(size as f32 * p_scale),
|
||||
font_id: font.0,
|
||||
screen_position: (0.0, 0.0),
|
||||
bounds: (bounds.width * p_scale, bounds.height * p_scale),
|
||||
..Default::default()
|
||||
layout: Default::default(),
|
||||
text: vec![glyph_brush::Text {
|
||||
text: content,
|
||||
scale: (size as f32 * p_scale).into(),
|
||||
font_id: font.0,
|
||||
extra: (),
|
||||
}],
|
||||
};
|
||||
|
||||
let maybe_rect = self.cache.glyph_calculator().glyph_bounds(section);
|
||||
@ -57,30 +61,26 @@ impl text::Renderer for IcedRenderer {
|
||||
let p_scale = self.p_scale;
|
||||
|
||||
let section = glyph_brush::Section {
|
||||
text: content,
|
||||
screen_position: (x * p_scale, y * p_scale),
|
||||
bounds: (bounds.width * p_scale, bounds.height * p_scale),
|
||||
scale: glyph_brush::rusttype::Scale::uniform(size as f32 * p_scale),
|
||||
layout: glyph_brush::Layout::Wrap {
|
||||
line_breaker: Default::default(),
|
||||
h_align,
|
||||
v_align,
|
||||
},
|
||||
font_id: font.0,
|
||||
..Default::default()
|
||||
text: vec![glyph_brush::Text {
|
||||
text: content,
|
||||
scale: (size as f32 * p_scale).into(),
|
||||
font_id: font.0,
|
||||
extra: (),
|
||||
}],
|
||||
};
|
||||
|
||||
let glyphs = self
|
||||
.cache
|
||||
.glyph_cache_mut()
|
||||
.glyphs(section)
|
||||
.map(|positioned_glyph| {
|
||||
(
|
||||
positioned_glyph.clone(), // :/
|
||||
[0.0, 0.0, 0.0, 1.0], // Color
|
||||
font.0,
|
||||
)
|
||||
})
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
(
|
273
voxygen/src/ui/ice/renderer/widget/text_input.rs
Normal file
273
voxygen/src/ui/ice/renderer/widget/text_input.rs
Normal file
@ -0,0 +1,273 @@
|
||||
use super::super::{super::FontId, IcedRenderer, Primitive};
|
||||
use glyph_brush::GlyphCruncher;
|
||||
use iced::{
|
||||
mouse,
|
||||
text_input::{self, cursor},
|
||||
Color, Point, Rectangle,
|
||||
};
|
||||
|
||||
const CURSOR_WIDTH: f32 = 1.0;
|
||||
// Extra scroll offset past the cursor
|
||||
const EXTRA_OFFSET: f32 = 5.0;
|
||||
|
||||
impl text_input::Renderer for IcedRenderer {
|
||||
type Font = FontId;
|
||||
type Style = ();
|
||||
|
||||
fn default_size(&self) -> u16 {
|
||||
// TODO: make configurable
|
||||
20
|
||||
}
|
||||
|
||||
fn measure_value(&self, value: &str, size: u16, font: Self::Font) -> f32 {
|
||||
// Using the physical scale might make this cached info usable below?
|
||||
// Although we also have a position of the screen there so this could be useless
|
||||
let p_scale = self.p_scale;
|
||||
|
||||
let section = glyph_brush::Section {
|
||||
screen_position: (0.0, 0.0),
|
||||
bounds: (f32::INFINITY, f32::INFINITY),
|
||||
layout: Default::default(),
|
||||
text: vec![glyph_brush::Text {
|
||||
text: value,
|
||||
scale: (size as f32 * p_scale).into(),
|
||||
font_id: font.0,
|
||||
extra: (),
|
||||
}],
|
||||
};
|
||||
|
||||
let mut glyph_calculator = self.cache.glyph_calculator();
|
||||
let mut width = glyph_calculator
|
||||
.glyph_bounds(section)
|
||||
.map_or(0.0, |rect| rect.width() / p_scale);
|
||||
|
||||
// glyph_brush ignores the exterior spaces
|
||||
// TODO: need better layout lib
|
||||
let exterior_spaces = value.len() - value.trim().len();
|
||||
|
||||
if exterior_spaces > 0 {
|
||||
use glyph_brush::ab_glyph::{Font, ScaleFont};
|
||||
// Could cache this if it is slow
|
||||
let font = glyph_calculator.fonts()[font.0].as_scaled(size as f32);
|
||||
let space_width = font.h_advance(font.glyph_id(' '));
|
||||
width += exterior_spaces as f32 * space_width;
|
||||
}
|
||||
|
||||
width
|
||||
}
|
||||
|
||||
fn offset(
|
||||
&self,
|
||||
text_bounds: Rectangle,
|
||||
font: Self::Font,
|
||||
size: u16,
|
||||
value: &text_input::Value,
|
||||
state: &text_input::State,
|
||||
) -> f32 {
|
||||
// Only need to offset if focused with cursor somewhere in the text
|
||||
if state.is_focused() {
|
||||
let cursor = state.cursor();
|
||||
|
||||
let focus_position = match cursor.state(value) {
|
||||
cursor::State::Index(i) => i,
|
||||
cursor::State::Selection { end, .. } => end,
|
||||
};
|
||||
|
||||
let (_, offset) = measure_cursor_and_scroll_offset(
|
||||
self,
|
||||
text_bounds,
|
||||
value,
|
||||
size,
|
||||
focus_position,
|
||||
font,
|
||||
);
|
||||
|
||||
offset
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
|
||||
fn draw(
|
||||
&mut self,
|
||||
bounds: Rectangle,
|
||||
text_bounds: Rectangle,
|
||||
//defaults: &Self::Defaults, No defaults!!
|
||||
cursor_position: Point,
|
||||
font: Self::Font,
|
||||
size: u16,
|
||||
placeholder: &str,
|
||||
value: &text_input::Value,
|
||||
state: &text_input::State,
|
||||
_style_sheet: &Self::Style,
|
||||
) -> Self::Output {
|
||||
let is_mouse_over = bounds.contains(cursor_position);
|
||||
|
||||
/*
|
||||
let style = if state.is_focused() {
|
||||
style.focused()
|
||||
} else if is_mouse_over {
|
||||
style.hovered()
|
||||
} else {
|
||||
style.active()
|
||||
}; */
|
||||
|
||||
let p_scale = self.p_scale;
|
||||
|
||||
// Allocation :(
|
||||
let text = value.to_string();
|
||||
let text = if text.is_empty() { Some(&*text) } else { None };
|
||||
|
||||
// TODO: background from style, image?
|
||||
|
||||
// TODO: color from style
|
||||
let color = if text.is_some() {
|
||||
Color::WHITE
|
||||
} else {
|
||||
Color::from_rgba(1.0, 1.0, 1.0, 0.4)
|
||||
};
|
||||
let linear_color = color.into_linear().into();
|
||||
|
||||
let (cursor_primitive, scroll_offset) = if state.is_focused() {
|
||||
let cursor = state.cursor();
|
||||
|
||||
let cursor_and_scroll_offset = |position| {
|
||||
measure_cursor_and_scroll_offset(self, text_bounds, value, size, position, font)
|
||||
};
|
||||
|
||||
let (cursor_primitive, offset) = match cursor.state(value) {
|
||||
cursor::State::Index(position) => {
|
||||
let (position, offset) = cursor_and_scroll_offset(position);
|
||||
(
|
||||
Primitive::Rectangle {
|
||||
bounds: Rectangle {
|
||||
x: text_bounds.x + position,
|
||||
y: text_bounds.y,
|
||||
width: CURSOR_WIDTH / p_scale,
|
||||
height: text_bounds.height,
|
||||
},
|
||||
linear_color,
|
||||
},
|
||||
offset,
|
||||
)
|
||||
},
|
||||
cursor::State::Selection { start, end } => {
|
||||
let left = start.min(end);
|
||||
let right = end.max(start);
|
||||
|
||||
let (left_position, left_offset) = cursor_and_scroll_offset(left);
|
||||
let (right_position, right_offset) = cursor_and_scroll_offset(right);
|
||||
|
||||
let width = right_position - left_position;
|
||||
|
||||
(
|
||||
Primitive::Rectangle {
|
||||
bounds: Rectangle {
|
||||
x: text_bounds.x + left_position,
|
||||
y: text_bounds.y,
|
||||
width,
|
||||
height: text_bounds.height,
|
||||
},
|
||||
// TODO: selection color from stlye
|
||||
linear_color: Color::from_rgba(1.0, 0.0, 1.0, 0.2).into_linear().into(),
|
||||
},
|
||||
if end == right {
|
||||
right_offset
|
||||
} else {
|
||||
left_offset
|
||||
},
|
||||
)
|
||||
},
|
||||
};
|
||||
|
||||
(Some(cursor_primitive), offset)
|
||||
} else {
|
||||
(None, 0.0)
|
||||
};
|
||||
|
||||
let section = glyph_brush::Section {
|
||||
screen_position: (
|
||||
text_bounds.x * p_scale + scroll_offset,
|
||||
text_bounds.center_y() * p_scale,
|
||||
),
|
||||
bounds: (text_bounds.width * p_scale, text_bounds.height * p_scale),
|
||||
layout: glyph_brush::Layout::SingleLine {
|
||||
line_breaker: Default::default(),
|
||||
h_align: glyph_brush::HorizontalAlign::Left,
|
||||
v_align: glyph_brush::VerticalAlign::Center,
|
||||
},
|
||||
text: vec![glyph_brush::Text {
|
||||
text: text.unwrap_or(placeholder),
|
||||
scale: (size as f32 * p_scale).into(),
|
||||
font_id: font.0,
|
||||
extra: (),
|
||||
}],
|
||||
};
|
||||
|
||||
let glyphs = self
|
||||
.cache
|
||||
.glyph_cache_mut()
|
||||
.glyphs(section)
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let text_primitive = Primitive::Text {
|
||||
glyphs,
|
||||
//size: size as f32,
|
||||
bounds,
|
||||
linear_color,
|
||||
/*font,
|
||||
*horizontal_alignment,
|
||||
*vertical_alignment, */
|
||||
};
|
||||
|
||||
let primitive = match cursor_primitive {
|
||||
Some(cursor_primitive) => Primitive::Group {
|
||||
primitives: vec![cursor_primitive, text_primitive],
|
||||
},
|
||||
None => text_primitive,
|
||||
};
|
||||
|
||||
// Probably already computed this somewhere
|
||||
let text_width = self.measure_value(text.unwrap_or(placeholder), size, font);
|
||||
|
||||
let primitive = if text_width > text_bounds.width {
|
||||
Primitive::Clip {
|
||||
bounds: text_bounds,
|
||||
content: Box::new(primitive),
|
||||
/* Note: iced_wgpu uses offset here but we can't do that since we pass the text
|
||||
* to the glyph_brush here */
|
||||
}
|
||||
} else {
|
||||
primitive
|
||||
};
|
||||
|
||||
(
|
||||
primitive,
|
||||
if is_mouse_over {
|
||||
mouse::Interaction::Text
|
||||
} else {
|
||||
mouse::Interaction::default()
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn measure_cursor_and_scroll_offset(
|
||||
renderer: &IcedRenderer,
|
||||
text_bounds: Rectangle,
|
||||
value: &text_input::Value,
|
||||
size: u16,
|
||||
cursor_index: usize,
|
||||
font: FontId,
|
||||
) -> (f32, f32) {
|
||||
use text_input::Renderer;
|
||||
|
||||
// TODO: so much allocation (fyi .until() allocates)
|
||||
let text_before_cursor = value.until(cursor_index).to_string();
|
||||
|
||||
let text_value_width = renderer.measure_value(&text_before_cursor, size, font);
|
||||
let offset = ((text_value_width + EXTRA_OFFSET) - text_bounds.width).max(0.0);
|
||||
|
||||
(text_value_width, offset)
|
||||
}
|
Loading…
Reference in New Issue
Block a user