initial text impl
This commit is contained in:
208
Cargo.lock
generated
208
Cargo.lock
generated
@@ -430,6 +430,29 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cosmic-text"
|
||||||
|
version = "0.14.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "da46a9d5a8905cc538a4a5bceb6a4510de7a51049c5588c0114efce102bcbbe8"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.1",
|
||||||
|
"fontdb",
|
||||||
|
"log",
|
||||||
|
"rangemap",
|
||||||
|
"rustc-hash",
|
||||||
|
"rustybuzz",
|
||||||
|
"self_cell",
|
||||||
|
"smol_str",
|
||||||
|
"swash",
|
||||||
|
"sys-locale",
|
||||||
|
"ttf-parser 0.21.1",
|
||||||
|
"unicode-bidi",
|
||||||
|
"unicode-linebreak",
|
||||||
|
"unicode-script",
|
||||||
|
"unicode-segmentation",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32fast"
|
name = "crc32fast"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
@@ -594,6 +617,38 @@ version = "0.1.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "font-types"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "02a596f5713680923a2080d86de50fe472fb290693cf0f701187a1c8b36996b7"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fontconfig-parser"
|
||||||
|
version = "0.5.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbc773e24e02d4ddd8395fd30dc147524273a83e54e0f312d986ea30de5f5646"
|
||||||
|
dependencies = [
|
||||||
|
"roxmltree",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fontdb"
|
||||||
|
version = "0.16.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b0299020c3ef3f60f526a4f64ab4a3d4ce116b1acbf24cdd22da0068e5d81dc3"
|
||||||
|
dependencies = [
|
||||||
|
"fontconfig-parser",
|
||||||
|
"log",
|
||||||
|
"memmap2",
|
||||||
|
"slotmap",
|
||||||
|
"tinyvec",
|
||||||
|
"ttf-parser 0.20.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "foreign-types"
|
name = "foreign-types"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
@@ -1469,7 +1524,7 @@ version = "0.25.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b"
|
checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ttf-parser",
|
"ttf-parser 0.25.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1714,6 +1769,12 @@ version = "0.1.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c3d6831663a5098ea164f89cff59c6284e95f4e3c76ce9848d4529f5ccca9bde"
|
checksum = "c3d6831663a5098ea164f89cff59c6284e95f4e3c76ce9848d4529f5ccca9bde"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rangemap"
|
||||||
|
version = "1.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f93e7e49bb0bf967717f7bd674458b3d6b0c5f48ec7e3038166026a69fc22223"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rav1e"
|
name = "rav1e"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
@@ -1790,6 +1851,16 @@ dependencies = [
|
|||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "read-fonts"
|
||||||
|
version = "0.29.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "04ca636dac446b5664bd16c069c00a9621806895b8bb02c2dc68542b23b8f25d"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
"font-types",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
@@ -1820,6 +1891,12 @@ version = "0.8.52"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce"
|
checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "roxmltree"
|
||||||
|
version = "0.20.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-hash"
|
name = "rustc-hash"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -1858,6 +1935,23 @@ version = "1.0.21"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
|
checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustybuzz"
|
||||||
|
version = "0.14.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cfb9cf8877777222e4a3bc7eb247e398b56baba500c38c1c46842431adc8b55c"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.1",
|
||||||
|
"bytemuck",
|
||||||
|
"libm",
|
||||||
|
"smallvec",
|
||||||
|
"ttf-parser 0.21.1",
|
||||||
|
"unicode-bidi-mirroring",
|
||||||
|
"unicode-ccc",
|
||||||
|
"unicode-properties",
|
||||||
|
"unicode-script",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "same-file"
|
name = "same-file"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
@@ -1892,6 +1986,12 @@ dependencies = [
|
|||||||
"tiny-skia",
|
"tiny-skia",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "self_cell"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.219"
|
version = "1.0.219"
|
||||||
@@ -1942,6 +2042,16 @@ dependencies = [
|
|||||||
"quote",
|
"quote",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "skrifa"
|
||||||
|
version = "0.31.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dbeb4ca4399663735553a09dd17ce7e49a0a0203f03b706b39628c4d913a8607"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
"read-fonts",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.4.11"
|
version = "0.4.11"
|
||||||
@@ -2018,6 +2128,17 @@ version = "0.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
|
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "swash"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f745de914febc7c9ab4388dfaf94bbc87e69f57bb41133a9b0c84d4be49856f3"
|
||||||
|
dependencies = [
|
||||||
|
"skrifa",
|
||||||
|
"yazi",
|
||||||
|
"zeno",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.104"
|
version = "2.0.104"
|
||||||
@@ -2029,6 +2150,15 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sys-locale"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "system-deps"
|
name = "system-deps"
|
||||||
version = "6.2.2"
|
version = "6.2.2"
|
||||||
@@ -2133,6 +2263,21 @@ dependencies = [
|
|||||||
"strict-num",
|
"strict-num",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinyvec"
|
||||||
|
version = "1.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
|
||||||
|
dependencies = [
|
||||||
|
"tinyvec_macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinyvec_macros"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml"
|
name = "toml"
|
||||||
version = "0.8.23"
|
version = "0.8.23"
|
||||||
@@ -2183,6 +2328,18 @@ version = "0.1.34"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
|
checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ttf-parser"
|
||||||
|
version = "0.20.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ttf-parser"
|
||||||
|
version = "0.21.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ttf-parser"
|
name = "ttf-parser"
|
||||||
version = "0.25.1"
|
version = "0.25.1"
|
||||||
@@ -2194,18 +2351,55 @@ name = "ui"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
|
"cosmic-text",
|
||||||
"image",
|
"image",
|
||||||
"pollster",
|
"pollster",
|
||||||
"wgpu",
|
"wgpu",
|
||||||
"winit",
|
"winit",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-bidi"
|
||||||
|
version = "0.3.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-bidi-mirroring"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "23cb788ffebc92c5948d0e997106233eeb1d8b9512f93f41651f52b6c5f5af86"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ccc"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1df77b101bcc4ea3d78dafc5ad7e4f58ceffe0b2b16bf446aeb50b6cb4157656"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.18"
|
version = "1.0.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-linebreak"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-properties"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-script"
|
||||||
|
version = "0.5.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9fb421b350c9aff471779e262955939f565ec18b86c15364e6bdf0d662ca7c1f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-segmentation"
|
name = "unicode-segmentation"
|
||||||
version = "1.12.0"
|
version = "1.12.0"
|
||||||
@@ -3112,6 +3306,18 @@ version = "0.8.27"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7"
|
checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yazi"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e01738255b5a16e78bbb83e7fbba0a1e7dd506905cfc53f4622d89015a03fbb5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zeno"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6df3dc4292935e51816d896edcd52aa30bc297907c26167fec31e2b0c6a32524"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.8.26"
|
version = "0.8.26"
|
||||||
|
|||||||
@@ -11,4 +11,5 @@ winit = "0.30.11"
|
|||||||
wgpu = "26.0.1"
|
wgpu = "26.0.1"
|
||||||
bytemuck = "1.23.1"
|
bytemuck = "1.23.1"
|
||||||
image = "0.25.6"
|
image = "0.25.6"
|
||||||
|
cosmic-text = "0.14.2"
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::{Painter, UiNum, UiRegion, Widget, WidgetId};
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub struct Regioned {
|
pub struct Regioned {
|
||||||
pub region: UiRegion,
|
pub region: UiRegion,
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
|
use crate::prelude::*;
|
||||||
use image::DynamicImage;
|
use image::DynamicImage;
|
||||||
|
|
||||||
use crate::{Color, Painter, TextureHandle, Widget, WidgetFnRet, render::RectPrimitive};
|
|
||||||
|
|
||||||
pub struct Image {
|
pub struct Image {
|
||||||
handle: Option<TextureHandle>,
|
handle: Option<TextureHandle>,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
mod frame;
|
mod frame;
|
||||||
mod image;
|
mod image;
|
||||||
mod num;
|
|
||||||
mod rect;
|
mod rect;
|
||||||
mod sense;
|
mod sense;
|
||||||
mod span;
|
mod span;
|
||||||
mod stack;
|
mod stack;
|
||||||
|
mod text;
|
||||||
mod trait_fns;
|
mod trait_fns;
|
||||||
|
|
||||||
pub use frame::*;
|
pub use frame::*;
|
||||||
pub use image::*;
|
pub use image::*;
|
||||||
pub use num::*;
|
|
||||||
pub use rect::*;
|
pub use rect::*;
|
||||||
pub use sense::*;
|
pub use sense::*;
|
||||||
pub use span::*;
|
pub use span::*;
|
||||||
pub use stack::*;
|
pub use stack::*;
|
||||||
|
pub use text::*;
|
||||||
pub use trait_fns::*;
|
pub use trait_fns::*;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::{Painter, UiColor, UiNum, Widget, render::RectPrimitive};
|
use crate::prelude::*;
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct Rect {
|
pub struct Rect {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::{Sense, SenseCtx, SenseFn, Sensor, Widget, WidgetId, WidgetIdFnRet, WidgetLike};
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub trait Sensable<W, Ctx, Tag> {
|
pub trait Sensable<W, Ctx, Tag> {
|
||||||
fn on(self, sense: Sense, f: impl SenseFn<Ctx>) -> WidgetIdFnRet!(W, Ctx);
|
fn on(self, sense: Sense, f: impl SenseFn<Ctx>) -> WidgetIdFnRet!(W, Ctx);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::{Dir, Painter, Sign, UIScalar, UiNum, UiRegion, Widget, WidgetId};
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub struct Span {
|
pub struct Span {
|
||||||
pub children: Vec<(WidgetId, SpanLen)>,
|
pub children: Vec<(WidgetId, SpanLen)>,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::{Painter, Widget, WidgetId};
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub struct Stack {
|
pub struct Stack {
|
||||||
pub children: Vec<WidgetId>,
|
pub children: Vec<WidgetId>,
|
||||||
|
|||||||
17
src/core/text.rs
Normal file
17
src/core/text.rs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
pub struct Text {
|
||||||
|
content: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Ctx> Widget<Ctx> for Text {
|
||||||
|
fn draw(&self, painter: &mut Painter<Ctx>) {
|
||||||
|
painter.draw_text(&self.content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn text(text: impl Into<String>) -> Text {
|
||||||
|
Text {
|
||||||
|
content: text.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::{UiRegion, Vec2, WidgetArrLike, WidgetFnRet, WidgetLike};
|
use crate::layout::{Dir, UiPos, UiRegion, Vec2, WidgetArrLike, WidgetFnRet, WidgetLike};
|
||||||
|
|
||||||
pub trait CoreWidget<W: 'static, Ctx: 'static, Tag> {
|
pub trait CoreWidget<W: 'static, Ctx: 'static, Tag> {
|
||||||
fn pad(self, padding: impl Into<Padding>) -> WidgetFnRet!(Regioned, Ctx);
|
fn pad(self, padding: impl Into<Padding>) -> WidgetFnRet!(Regioned, Ctx);
|
||||||
@@ -17,7 +17,7 @@ impl<W: WidgetLike<Ctx, Tag>, Ctx: 'static, Tag> CoreWidget<W::Widget, Ctx, Tag>
|
|||||||
|
|
||||||
fn center(self, size: impl Into<Vec2>) -> WidgetFnRet!(Regioned, Ctx) {
|
fn center(self, size: impl Into<Vec2>) -> WidgetFnRet!(Regioned, Ctx) {
|
||||||
|ui| Regioned {
|
|ui| Regioned {
|
||||||
region: UiRegion::center().size(size.into()),
|
region: UiPos::center().expand(size.into()),
|
||||||
inner: self.add(ui).erase_type(),
|
inner: self.add(ui).erase_type(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::{any::TypeId, marker::PhantomData};
|
use std::{any::TypeId, marker::PhantomData};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
FnTag, Ui, UiMsg, UiMsgSender, Widget, WidgetLike, WidgetTag,
|
layout::{FnTag, Ui, UiMsg, UiMsgSender, Widget, WidgetLike, WidgetTag},
|
||||||
util::{Id, RefCounter},
|
util::{Id, RefCounter},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -83,10 +83,10 @@ pub struct IdTag;
|
|||||||
// pub trait WidgetIdFn<W, Ctx> = FnOnce(&mut Ui<Ctx>) -> WidgetId<W>;
|
// pub trait WidgetIdFn<W, Ctx> = FnOnce(&mut Ui<Ctx>) -> WidgetId<W>;
|
||||||
macro_rules! WidgetIdFnRet {
|
macro_rules! WidgetIdFnRet {
|
||||||
($W:ty, $Ctx:ty) => {
|
($W:ty, $Ctx:ty) => {
|
||||||
impl FnOnce(&mut $crate::Ui<$Ctx>) -> $crate::WidgetId<$W>
|
impl FnOnce(&mut $crate::layout::Ui<$Ctx>) -> $crate::layout::WidgetId<$W>
|
||||||
};
|
};
|
||||||
($W:ty, $Ctx:ty, $($use:tt)*) => {
|
($W:ty, $Ctx:ty, $($use:tt)*) => {
|
||||||
impl FnOnce(&mut $crate::Ui<$Ctx>) -> $crate::WidgetId<$W> + use<$($use)*>
|
impl FnOnce(&mut $crate::layout::Ui<$Ctx>) -> $crate::layout::WidgetId<$W> + use<$($use)*>
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
pub(crate) use WidgetIdFnRet;
|
pub(crate) use WidgetIdFnRet;
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
mod color;
|
mod color;
|
||||||
mod id;
|
mod id;
|
||||||
|
mod num;
|
||||||
|
mod orientation;
|
||||||
mod painter;
|
mod painter;
|
||||||
mod region;
|
mod pos;
|
||||||
mod sense;
|
mod sense;
|
||||||
|
mod text;
|
||||||
mod texture;
|
mod texture;
|
||||||
mod ui;
|
mod ui;
|
||||||
mod vec2;
|
mod vec2;
|
||||||
@@ -10,9 +13,12 @@ mod widget;
|
|||||||
|
|
||||||
pub use color::*;
|
pub use color::*;
|
||||||
pub use id::*;
|
pub use id::*;
|
||||||
|
pub use num::*;
|
||||||
|
pub use orientation::*;
|
||||||
pub use painter::*;
|
pub use painter::*;
|
||||||
pub use region::*;
|
pub use pos::*;
|
||||||
pub use sense::*;
|
pub use sense::*;
|
||||||
|
pub use text::*;
|
||||||
pub use texture::*;
|
pub use texture::*;
|
||||||
pub use ui::*;
|
pub use ui::*;
|
||||||
pub use vec2::*;
|
pub use vec2::*;
|
||||||
|
|||||||
21
src/layout/num.rs
Normal file
21
src/layout/num.rs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
pub trait UiNum {
|
||||||
|
fn to_f32(self) -> f32;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UiNum for f32 {
|
||||||
|
fn to_f32(self) -> f32 {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UiNum for u32 {
|
||||||
|
fn to_f32(self) -> f32 {
|
||||||
|
self as f32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UiNum for i32 {
|
||||||
|
fn to_f32(self) -> f32 {
|
||||||
|
self as f32
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,23 +1,22 @@
|
|||||||
pub trait UiNum {
|
use crate::layout::{Vec2, vec2};
|
||||||
fn to_f32(self) -> f32;
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub enum Corner {
|
||||||
|
TopLeft,
|
||||||
|
TopRight,
|
||||||
|
BotLeft,
|
||||||
|
BotRight,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UiNum for f32 {
|
impl Corner {
|
||||||
fn to_f32(self) -> f32 {
|
pub const fn anchor(&self) -> Vec2 {
|
||||||
self
|
match self {
|
||||||
|
Corner::TopLeft => vec2(0.0, 0.0),
|
||||||
|
Corner::TopRight => vec2(1.0, 0.0),
|
||||||
|
Corner::BotLeft => vec2(0.0, 1.0),
|
||||||
|
Corner::BotRight => vec2(1.0, 1.0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UiNum for u32 {
|
|
||||||
fn to_f32(self) -> f32 {
|
|
||||||
self as f32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UiNum for i32 {
|
|
||||||
fn to_f32(self) -> f32 {
|
|
||||||
self as f32
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||||
@@ -1,5 +1,10 @@
|
|||||||
|
use image::GenericImageView;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ActiveSensors, SensorMap, TextureHandle, UiRegion, WidgetId, Widgets,
|
layout::{
|
||||||
|
ActiveSensors, SensorMap, TextData, TextureHandle, Textures, UiPos, UiRegion, Vec2,
|
||||||
|
WidgetId, Widgets,
|
||||||
|
},
|
||||||
render::{Primitive, Primitives},
|
render::{Primitive, Primitives},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -9,16 +14,22 @@ pub struct Painter<'a, Ctx: 'static> {
|
|||||||
sensors_map: &'a SensorMap<Ctx>,
|
sensors_map: &'a SensorMap<Ctx>,
|
||||||
active_sensors: &'a mut ActiveSensors,
|
active_sensors: &'a mut ActiveSensors,
|
||||||
primitives: &'a mut Primitives,
|
primitives: &'a mut Primitives,
|
||||||
|
textures: &'a mut Textures,
|
||||||
|
text: &'a mut TextData,
|
||||||
region: UiRegion,
|
region: UiRegion,
|
||||||
|
screen_size: Vec2,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Ctx> Painter<'a, Ctx> {
|
impl<'a, Ctx> Painter<'a, Ctx> {
|
||||||
pub fn new(
|
pub(crate) fn new(
|
||||||
nodes: &'a Widgets<Ctx>,
|
nodes: &'a Widgets<Ctx>,
|
||||||
primitives: &'a mut Primitives,
|
primitives: &'a mut Primitives,
|
||||||
ctx: &'a mut Ctx,
|
ctx: &'a mut Ctx,
|
||||||
sensors_map: &'a SensorMap<Ctx>,
|
sensors_map: &'a SensorMap<Ctx>,
|
||||||
active_sensors: &'a mut ActiveSensors,
|
active_sensors: &'a mut ActiveSensors,
|
||||||
|
text: &'a mut TextData,
|
||||||
|
textures: &'a mut Textures,
|
||||||
|
screen_size: Vec2,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
nodes,
|
nodes,
|
||||||
@@ -26,7 +37,10 @@ impl<'a, Ctx> Painter<'a, Ctx> {
|
|||||||
active_sensors,
|
active_sensors,
|
||||||
sensors_map,
|
sensors_map,
|
||||||
primitives,
|
primitives,
|
||||||
|
text,
|
||||||
region: UiRegion::full(),
|
region: UiRegion::full(),
|
||||||
|
textures,
|
||||||
|
screen_size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,9 +83,30 @@ impl<'a, Ctx> Painter<'a, Ctx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_texture(&mut self, handle: &TextureHandle) {
|
pub fn draw_texture(&mut self, handle: &TextureHandle) {
|
||||||
|
self.primitives.drawn_textures.push(handle.clone());
|
||||||
self.write(handle.inner);
|
self.write(handle.inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn draw_texture_at(&mut self, handle: &TextureHandle, region: UiRegion) {
|
||||||
|
let old = self.region;
|
||||||
|
self.region = region;
|
||||||
|
self.draw_texture(handle);
|
||||||
|
self.region = old;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_text(&mut self, content: &str) {
|
||||||
|
let handle = self.text.draw(content, self.textures);
|
||||||
|
let dims: Vec2 = self.textures[&handle].dimensions().into();
|
||||||
|
let center = self.region.center().snap(self.screen_size);
|
||||||
|
let top_left = center - (dims / 2.0).floor();
|
||||||
|
let bot_right = center + (dims / 2.0).ceil();
|
||||||
|
let region = UiRegion {
|
||||||
|
top_left: UiPos::offset(top_left),
|
||||||
|
bot_right: UiPos::offset(bot_right),
|
||||||
|
};
|
||||||
|
self.draw_texture_at(&handle, region);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn region(&self) -> UiRegion {
|
pub fn region(&self) -> UiRegion {
|
||||||
self.region
|
self.region
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
Axis, Vec2,
|
layout::{Axis, Corner, Vec2, vec2},
|
||||||
layout::vec2,
|
|
||||||
util::{F32Util, impl_op},
|
util::{F32Util, impl_op},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -12,6 +11,15 @@ pub struct UiPos {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl UiPos {
|
impl UiPos {
|
||||||
|
/// expands this position into a sized region centered at self
|
||||||
|
pub fn expand(&self, size: impl Into<Vec2>) -> UiRegion {
|
||||||
|
let size = size.into();
|
||||||
|
UiRegion {
|
||||||
|
top_left: self.shifted(-size / 2.0),
|
||||||
|
bot_right: self.shifted(size / 2.0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub const fn center() -> Self {
|
pub const fn center() -> Self {
|
||||||
Self::anchor(vec2(0.5, 0.5))
|
Self::anchor(vec2(0.5, 0.5))
|
||||||
}
|
}
|
||||||
@@ -23,6 +31,13 @@ impl UiPos {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn offset(offset: Vec2) -> Self {
|
||||||
|
Self {
|
||||||
|
anchor: Vec2::ZERO,
|
||||||
|
offset,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub const fn corner(corner: Corner) -> Self {
|
pub const fn corner(corner: Corner) -> Self {
|
||||||
Self::anchor(corner.anchor())
|
Self::anchor(corner.anchor())
|
||||||
}
|
}
|
||||||
@@ -69,6 +84,15 @@ impl UiPos {
|
|||||||
self.flip();
|
self.flip();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_size(&self, size: Vec2) -> Vec2 {
|
||||||
|
self.anchor * size + self.offset
|
||||||
|
}
|
||||||
|
|
||||||
|
/// snaps this to a specific screen size to get actual pixel coordinates
|
||||||
|
pub fn snap(&self, size: Vec2) -> Vec2 {
|
||||||
|
self.to_size(size).round()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
@@ -122,21 +146,12 @@ impl UiRegion {
|
|||||||
bot_right: UiPos::corner(Corner::BotRight),
|
bot_right: UiPos::corner(Corner::BotRight),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn center() -> Self {
|
|
||||||
Self::anchor(Vec2::new(0.5, 0.5))
|
|
||||||
}
|
|
||||||
pub fn anchor(anchor: Vec2) -> Self {
|
pub fn anchor(anchor: Vec2) -> Self {
|
||||||
Self {
|
Self {
|
||||||
top_left: UiPos::anchor(anchor),
|
top_left: UiPos::anchor(anchor),
|
||||||
bot_right: UiPos::anchor(anchor),
|
bot_right: UiPos::anchor(anchor),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn size(mut self, size: impl Into<Vec2>) -> Self {
|
|
||||||
let size = size.into();
|
|
||||||
self.top_left = self.top_left.shifted(-size / 2.0);
|
|
||||||
self.bot_right = self.bot_right.shifted(size / 2.0);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
pub fn within(&self, parent: &Self) -> Self {
|
pub fn within(&self, parent: &Self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
top_left: self.top_left.within(parent),
|
top_left: self.top_left.within(parent),
|
||||||
@@ -170,19 +185,16 @@ impl UiRegion {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn corner(corner: Corner) -> Self {
|
|
||||||
Self {
|
|
||||||
top_left: UiPos::corner(corner),
|
|
||||||
bot_right: UiPos::corner(corner),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_screen(&self, size: Vec2) -> ScreenRect {
|
pub fn to_screen(&self, size: Vec2) -> ScreenRect {
|
||||||
ScreenRect {
|
ScreenRect {
|
||||||
top_left: self.top_left.anchor * size + self.top_left.offset,
|
top_left: self.top_left.anchor * size + self.top_left.offset,
|
||||||
bot_right: self.bot_right.anchor * size + self.bot_right.offset,
|
bot_right: self.bot_right.anchor * size + self.bot_right.offset,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn center(&self) -> UiPos {
|
||||||
|
UiPos::center().within(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -221,22 +233,3 @@ impl UIScalarView<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
|
||||||
pub enum Corner {
|
|
||||||
TopLeft,
|
|
||||||
TopRight,
|
|
||||||
BotLeft,
|
|
||||||
BotRight,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Corner {
|
|
||||||
pub const fn anchor(&self) -> Vec2 {
|
|
||||||
match self {
|
|
||||||
Corner::TopLeft => vec2(0.0, 0.0),
|
|
||||||
Corner::TopRight => vec2(1.0, 0.0),
|
|
||||||
Corner::BotLeft => vec2(0.0, 1.0),
|
|
||||||
Corner::BotRight => vec2(1.0, 1.0),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
use crate::{HashMap, Ui, UiRegion, Vec2, WidgetId, util::Id};
|
use crate::{
|
||||||
|
HashMap,
|
||||||
|
layout::{Ui, UiRegion, Vec2, WidgetId},
|
||||||
|
util::Id,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
pub enum Sense {
|
pub enum Sense {
|
||||||
@@ -81,10 +85,7 @@ impl<Ctx> Ui<Ctx> {
|
|||||||
|
|
||||||
for sensor in &mut group.sensors {
|
for sensor in &mut group.sensors {
|
||||||
if should_run(sensor.sense, group.cursor, group.hover) {
|
if should_run(sensor.sense, group.cursor, group.hover) {
|
||||||
(sensor.f.box_clone())(SenseCtx {
|
(sensor.f.box_clone())(SenseCtx { ui: self, app: ctx });
|
||||||
ui: self,
|
|
||||||
app: ctx,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
57
src/layout/text.rs
Normal file
57
src/layout/text.rs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
use cosmic_text::{Attrs, Buffer, FontSystem, Metrics, Shaping, SwashCache};
|
||||||
|
use image::{Rgba, RgbaImage};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
HashMap,
|
||||||
|
layout::{TextureHandle, Textures},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub(crate) struct TextData {
|
||||||
|
font_system: FontSystem,
|
||||||
|
cache: SwashCache,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TextData {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
font_system: FontSystem::new(),
|
||||||
|
cache: SwashCache::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TextData {
|
||||||
|
pub fn draw(&mut self, content: &str, textures: &mut Textures) -> TextureHandle {
|
||||||
|
let metrics = Metrics::new(30.0, 30.0);
|
||||||
|
let mut buffer = Buffer::new(&mut self.font_system, metrics);
|
||||||
|
let mut buffer = buffer.borrow_with(&mut self.font_system);
|
||||||
|
buffer.set_text(content, &Attrs::new(), Shaping::Advanced);
|
||||||
|
|
||||||
|
// dawg what is this api ???
|
||||||
|
let mut pixels = HashMap::new();
|
||||||
|
let mut min_x = 0;
|
||||||
|
let mut min_y = 0;
|
||||||
|
let mut max_x = 0;
|
||||||
|
let mut max_y = 0;
|
||||||
|
buffer.draw(
|
||||||
|
&mut self.cache,
|
||||||
|
cosmic_text::Color::rgb(0xff, 0xff, 0xff),
|
||||||
|
|x, y, _, _, color| {
|
||||||
|
min_x = min_x.min(x);
|
||||||
|
min_y = min_y.min(y);
|
||||||
|
max_x = max_x.max(x);
|
||||||
|
max_y = max_y.max(y);
|
||||||
|
pixels.insert((x, y), Rgba(color.as_rgba()));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
let width = (max_x - min_x + 1) as u32;
|
||||||
|
let height = (max_y - min_y + 1) as u32;
|
||||||
|
let mut image = RgbaImage::new(width, height);
|
||||||
|
for ((x, y), color) in pixels {
|
||||||
|
let x = (x - min_x) as u32;
|
||||||
|
let y = (y - min_y) as u32;
|
||||||
|
image.put_pixel(x, y, color);
|
||||||
|
}
|
||||||
|
textures.add(image)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,14 @@
|
|||||||
|
use std::ops::Index;
|
||||||
|
|
||||||
use image::DynamicImage;
|
use image::DynamicImage;
|
||||||
|
|
||||||
use crate::{UiMsg, UiMsgSender, render::TexturePrimitive, util::RefCounter};
|
use crate::{
|
||||||
|
layout::{UiMsg, UiMsgSender},
|
||||||
|
render::TexturePrimitive,
|
||||||
|
util::RefCounter,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct TextureHandle {
|
pub struct TextureHandle {
|
||||||
pub inner: TexturePrimitive,
|
pub inner: TexturePrimitive,
|
||||||
counter: RefCounter,
|
counter: RefCounter,
|
||||||
@@ -10,11 +17,11 @@ pub struct TextureHandle {
|
|||||||
|
|
||||||
/// a texture manager for a ui
|
/// a texture manager for a ui
|
||||||
/// note that this is heavily oriented towards wgpu's renderer so the primitives don't need mapped
|
/// note that this is heavily oriented towards wgpu's renderer so the primitives don't need mapped
|
||||||
#[derive(Default)]
|
|
||||||
pub struct Textures {
|
pub struct Textures {
|
||||||
free: Vec<u32>,
|
free: Vec<u32>,
|
||||||
images: Vec<Option<DynamicImage>>,
|
images: Vec<Option<DynamicImage>>,
|
||||||
updates: Vec<Update>,
|
updates: Vec<Update>,
|
||||||
|
send: UiMsgSender,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum TextureUpdate<'a> {
|
pub enum TextureUpdate<'a> {
|
||||||
@@ -30,8 +37,16 @@ enum Update {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Textures {
|
impl Textures {
|
||||||
pub fn add(&mut self, image: DynamicImage, send: UiMsgSender) -> TextureHandle {
|
pub fn new(send: UiMsgSender) -> Self {
|
||||||
let view_idx = self.push(image);
|
Self {
|
||||||
|
free: Vec::new(),
|
||||||
|
images: Vec::new(),
|
||||||
|
updates: Vec::new(),
|
||||||
|
send,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn add(&mut self, image: impl Into<DynamicImage>) -> TextureHandle {
|
||||||
|
let view_idx = self.push(image.into());
|
||||||
// 0 == default in renderer; TODO: actually create samplers here
|
// 0 == default in renderer; TODO: actually create samplers here
|
||||||
let sampler_idx = 0;
|
let sampler_idx = 0;
|
||||||
TextureHandle {
|
TextureHandle {
|
||||||
@@ -40,7 +55,7 @@ impl Textures {
|
|||||||
sampler_idx,
|
sampler_idx,
|
||||||
},
|
},
|
||||||
counter: RefCounter::new(),
|
counter: RefCounter::new(),
|
||||||
send,
|
send: self.send.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,3 +94,11 @@ impl Drop for TextureHandle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Index<&TextureHandle> for Textures {
|
||||||
|
type Output = DynamicImage;
|
||||||
|
|
||||||
|
fn index(&self, index: &TextureHandle) -> &Self::Output {
|
||||||
|
self.images[index.inner.view_idx as usize].as_ref().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
use image::DynamicImage;
|
use image::DynamicImage;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ActiveSensors, HashMap, Painter, SensorMap, TextureHandle, Textures, Widget, WidgetId,
|
HashMap,
|
||||||
WidgetLike,
|
layout::{
|
||||||
|
ActiveSensors, Painter, SensorMap, TextData, TextureHandle, Textures, Vec2, Widget,
|
||||||
|
WidgetId, WidgetLike,
|
||||||
|
},
|
||||||
render::Primitives,
|
render::Primitives,
|
||||||
util::{Id, IdTracker},
|
util::{Id, IdTracker},
|
||||||
};
|
};
|
||||||
@@ -18,8 +21,11 @@ pub struct Ui<Ctx> {
|
|||||||
updates: Vec<WidgetId>,
|
updates: Vec<WidgetId>,
|
||||||
recv: Receiver<UiMsg>,
|
recv: Receiver<UiMsg>,
|
||||||
send: UiMsgSender,
|
send: UiMsgSender,
|
||||||
|
size: Vec2,
|
||||||
|
// TODO: make these non pub(crate)
|
||||||
pub(crate) primitives: Primitives,
|
pub(crate) primitives: Primitives,
|
||||||
pub(crate) textures: Textures,
|
pub(crate) textures: Textures,
|
||||||
|
pub(crate) text: TextData,
|
||||||
full_redraw: bool,
|
full_redraw: bool,
|
||||||
|
|
||||||
pub(super) active_sensors: ActiveSensors,
|
pub(super) active_sensors: ActiveSensors,
|
||||||
@@ -85,7 +91,12 @@ impl<Ctx> Ui<Ctx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_texture(&mut self, image: DynamicImage) -> TextureHandle {
|
pub fn add_texture(&mut self, image: DynamicImage) -> TextureHandle {
|
||||||
self.textures.add(image, self.send.clone())
|
self.textures.add(image)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resize(&mut self, size: impl Into<Vec2>) {
|
||||||
|
self.size = size.into();
|
||||||
|
self.full_redraw = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn redraw_all(&mut self, ctx: &mut Ctx)
|
pub fn redraw_all(&mut self, ctx: &mut Ctx)
|
||||||
@@ -100,6 +111,9 @@ impl<Ctx> Ui<Ctx> {
|
|||||||
ctx,
|
ctx,
|
||||||
&self.sensor_map,
|
&self.sensor_map,
|
||||||
&mut self.active_sensors,
|
&mut self.active_sensors,
|
||||||
|
&mut self.text,
|
||||||
|
&mut self.textures,
|
||||||
|
self.size,
|
||||||
);
|
);
|
||||||
if let Some(base) = &self.base {
|
if let Some(base) = &self.base {
|
||||||
painter.draw(base);
|
painter.draw(base);
|
||||||
@@ -217,18 +231,20 @@ impl<Ctx> dyn Widget<Ctx> {
|
|||||||
|
|
||||||
impl<Ctx: 'static> Default for Ui<Ctx> {
|
impl<Ctx: 'static> Default for Ui<Ctx> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let (del_send, del_recv) = channel();
|
let (send, recv) = channel();
|
||||||
Self {
|
Self {
|
||||||
base: Default::default(),
|
base: Default::default(),
|
||||||
widgets: Widgets::new(),
|
widgets: Widgets::new(),
|
||||||
updates: Default::default(),
|
updates: Default::default(),
|
||||||
primitives: Default::default(),
|
primitives: Default::default(),
|
||||||
textures: Textures::default(),
|
textures: Textures::new(send.clone()),
|
||||||
|
text: TextData::default(),
|
||||||
full_redraw: false,
|
full_redraw: false,
|
||||||
active_sensors: Default::default(),
|
active_sensors: Default::default(),
|
||||||
sensor_map: Default::default(),
|
sensor_map: Default::default(),
|
||||||
send: del_send,
|
send,
|
||||||
recv: del_recv,
|
recv,
|
||||||
|
size: Vec2::ZERO,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
use crate::{util::{impl_op, F32Util}, UiNum};
|
use crate::{
|
||||||
|
layout::UiNum,
|
||||||
|
util::{F32Util, impl_op},
|
||||||
|
};
|
||||||
use std::ops::*;
|
use std::ops::*;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@@ -28,6 +31,27 @@ impl Vec2 {
|
|||||||
y: self.y.lerp(from.y, to.y),
|
y: self.y.lerp(from.y, to.y),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn round(self) -> Self {
|
||||||
|
Self {
|
||||||
|
x: self.x.round(),
|
||||||
|
y: self.y.round(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn floor(self) -> Self {
|
||||||
|
Self {
|
||||||
|
x: self.x.floor(),
|
||||||
|
y: self.y.floor(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn ceil(self) -> Self {
|
||||||
|
Self {
|
||||||
|
x: self.x.ceil(),
|
||||||
|
y: self.y.ceil(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl const From<f32> for Vec2 {
|
impl const From<f32> for Vec2 {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use crate::{Painter, Ui, WidgetId, WidgetIdFnRet};
|
use crate::layout::{Painter, Ui, WidgetId, WidgetIdFnRet};
|
||||||
|
|
||||||
use std::{any::Any, marker::PhantomData};
|
use std::{any::Any, marker::PhantomData};
|
||||||
|
|
||||||
pub trait Widget<Ctx>: Any {
|
pub trait Widget<Ctx>: Any {
|
||||||
@@ -33,7 +34,7 @@ pub trait WidgetLike<Ctx, Tag> {
|
|||||||
/// currently a macro for rust analyzer (doesn't support trait aliases atm)
|
/// currently a macro for rust analyzer (doesn't support trait aliases atm)
|
||||||
macro_rules! WidgetFnRet {
|
macro_rules! WidgetFnRet {
|
||||||
($W:ty, $Ctx:ty) => {
|
($W:ty, $Ctx:ty) => {
|
||||||
impl FnOnce(&mut $crate::Ui<$Ctx>) -> $W
|
impl FnOnce(&mut $crate::layout::Ui<$Ctx>) -> $W
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
pub(crate) use WidgetFnRet;
|
pub(crate) use WidgetFnRet;
|
||||||
|
|||||||
11
src/lib.rs
11
src/lib.rs
@@ -5,13 +5,16 @@
|
|||||||
#![feature(trait_alias)]
|
#![feature(trait_alias)]
|
||||||
#![feature(negative_impls)]
|
#![feature(negative_impls)]
|
||||||
|
|
||||||
mod core;
|
pub mod core;
|
||||||
mod layout;
|
pub mod layout;
|
||||||
pub mod render;
|
pub mod render;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
pub use core::*;
|
pub mod prelude {
|
||||||
pub use layout::*;
|
pub use crate::core::*;
|
||||||
|
pub use crate::layout::*;
|
||||||
|
pub use crate::render::*;
|
||||||
|
}
|
||||||
|
|
||||||
pub type HashMap<K, V> = std::collections::HashMap<K, V>;
|
pub type HashMap<K, V> = std::collections::HashMap<K, V>;
|
||||||
pub type HashSet<K> = std::collections::HashSet<K>;
|
pub type HashSet<K> = std::collections::HashSet<K>;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use wgpu::VertexAttribute;
|
use wgpu::VertexAttribute;
|
||||||
|
|
||||||
use crate::UiRegion;
|
use crate::layout::UiRegion;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable, Default)]
|
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable, Default)]
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::num::NonZero;
|
use std::num::NonZero;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Ui,
|
layout::Ui,
|
||||||
render::{data::PrimitiveInstance, texture::GpuTextures, util::ArrBuf},
|
render::{data::PrimitiveInstance, texture::GpuTextures, util::ArrBuf},
|
||||||
};
|
};
|
||||||
use data::WindowUniform;
|
use data::WindowUniform;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
Color, UiRegion,
|
layout::{Color, TextureHandle, UiRegion},
|
||||||
render::{ArrBuf, data::PrimitiveInstance},
|
render::{ArrBuf, data::PrimitiveInstance},
|
||||||
};
|
};
|
||||||
use bytemuck::Pod;
|
use bytemuck::Pod;
|
||||||
@@ -8,6 +8,8 @@ use wgpu::*;
|
|||||||
pub struct Primitives {
|
pub struct Primitives {
|
||||||
pub(super) instances: Vec<PrimitiveInstance>,
|
pub(super) instances: Vec<PrimitiveInstance>,
|
||||||
pub(super) data: PrimitiveData,
|
pub(super) data: PrimitiveData,
|
||||||
|
// ensure drawn textures don't get freed
|
||||||
|
pub(crate) drawn_textures: Vec<TextureHandle>,
|
||||||
pub updated: bool,
|
pub updated: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,6 +18,7 @@ impl Default for Primitives {
|
|||||||
Self {
|
Self {
|
||||||
instances: Default::default(),
|
instances: Default::default(),
|
||||||
data: Default::default(),
|
data: Default::default(),
|
||||||
|
drawn_textures: Default::default(),
|
||||||
updated: true,
|
updated: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,6 +101,7 @@ impl Primitives {
|
|||||||
self.updated = true;
|
self.updated = true;
|
||||||
self.instances.clear();
|
self.instances.clear();
|
||||||
self.data.clear();
|
self.data.clear();
|
||||||
|
self.drawn_textures.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use image::{DynamicImage, EncodableLayout};
|
use image::{DynamicImage, EncodableLayout};
|
||||||
use wgpu::{util::DeviceExt, *};
|
use wgpu::{util::DeviceExt, *};
|
||||||
|
|
||||||
use crate::{TextureUpdate, Textures};
|
use crate::layout::{TextureUpdate, Textures};
|
||||||
|
|
||||||
pub struct GpuTextures {
|
pub struct GpuTextures {
|
||||||
device: Device,
|
device: Device,
|
||||||
@@ -23,6 +23,9 @@ impl GpuTextures {
|
|||||||
TextureUpdate::Free(i) => self.free(i),
|
TextureUpdate::Free(i) => self.free(i),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// if changed {
|
||||||
|
// println!("{}", self.views.len());
|
||||||
|
// }
|
||||||
changed
|
changed
|
||||||
}
|
}
|
||||||
fn set(&mut self, i: u32, image: &DynamicImage) {
|
fn set(&mut self, i: u32, image: &DynamicImage) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use ui::Ui;
|
use ui::layout::Ui;
|
||||||
use winit::{
|
use winit::{
|
||||||
application::ApplicationHandler,
|
application::ApplicationHandler,
|
||||||
event::WindowEvent,
|
event::WindowEvent,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use ui::{CursorState, Vec2};
|
use ui::layout::{CursorState, Vec2};
|
||||||
use winit::event::WindowEvent;
|
use winit::event::WindowEvent;
|
||||||
|
|
||||||
use crate::testing::Client;
|
use crate::testing::Client;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use app::App;
|
use app::App;
|
||||||
use render::Renderer;
|
use render::Renderer;
|
||||||
use ui::*;
|
use ui::prelude::*;
|
||||||
use winit::{event::WindowEvent, event_loop::ActiveEventLoop, window::Window};
|
use winit::{event::WindowEvent, event_loop::ActiveEventLoop, window::Window};
|
||||||
|
|
||||||
use crate::testing::input::Input;
|
use crate::testing::input::Input;
|
||||||
@@ -80,10 +80,11 @@ impl Client {
|
|||||||
color: UiColor,
|
color: UiColor,
|
||||||
main: &WidgetId<Regioned>,
|
main: &WidgetId<Regioned>,
|
||||||
to: &WidgetId<To>,
|
to: &WidgetId<To>,
|
||||||
) -> impl WidgetLike<Client, IdTag> {
|
label: impl Into<String>,
|
||||||
|
) -> impl WidgetLike<Client, FnTag> {
|
||||||
let main = main.clone();
|
let main = main.clone();
|
||||||
let to = to.clone().erase_type();
|
let to = to.clone().erase_type();
|
||||||
Rect::new(color)
|
let rect = Rect::new(color)
|
||||||
.id_on(Sense::PressStart, move |id, ctx| {
|
.id_on(Sense::PressStart, move |id, ctx| {
|
||||||
ctx.ui[&main].inner = to.clone();
|
ctx.ui[&main].inner = to.clone();
|
||||||
ctx.ui[id].color = color.add_rgb(-0.2);
|
ctx.ui[id].color = color.add_rgb(-0.2);
|
||||||
@@ -96,14 +97,15 @@ impl Client {
|
|||||||
})
|
})
|
||||||
.edit_on(Sense::HoverEnd, move |r, _| {
|
.edit_on(Sense::HoverEnd, move |r, _| {
|
||||||
r.color = color;
|
r.color = color;
|
||||||
})
|
});
|
||||||
|
(rect, text(label)).stack()
|
||||||
}
|
}
|
||||||
|
|
||||||
let tabs = ui.add(
|
let tabs = ui.add(
|
||||||
(
|
(
|
||||||
switch_button(UiColor::RED, &main, &pad_test),
|
switch_button(UiColor::RED, &main, &pad_test, "pad test"),
|
||||||
switch_button(UiColor::GREEN, &main, &span_test),
|
switch_button(UiColor::GREEN, &main, &span_test, "span test"),
|
||||||
switch_button(UiColor::BLUE, &main, &span_add_test),
|
switch_button(UiColor::BLUE, &main, &span_add_test, "span add test"),
|
||||||
)
|
)
|
||||||
.span(Dir::RIGHT, [1, 1, 1]),
|
.span(Dir::RIGHT, [1, 1, 1]),
|
||||||
);
|
);
|
||||||
@@ -113,8 +115,8 @@ impl Client {
|
|||||||
println!("{}", ctx.ui.num_widgets());
|
println!("{}", ctx.ui.num_widgets());
|
||||||
})
|
})
|
||||||
.region(
|
.region(
|
||||||
UiRegion::corner(Corner::BotRight)
|
UiPos::corner(Corner::BotRight)
|
||||||
.size((150, 150))
|
.expand((150, 150))
|
||||||
.shifted((-75, -75)),
|
.shifted((-75, -75)),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -125,8 +127,8 @@ impl Client {
|
|||||||
ctx.ui[&s].children.pop();
|
ctx.ui[&s].children.pop();
|
||||||
})
|
})
|
||||||
.region(
|
.region(
|
||||||
UiRegion::corner(Corner::BotLeft)
|
UiPos::corner(Corner::BotLeft)
|
||||||
.size((150, 150))
|
.expand((150, 150))
|
||||||
.shifted((75, -75)),
|
.shifted((75, -75)),
|
||||||
);
|
);
|
||||||
ui.set_base(
|
ui.set_base(
|
||||||
@@ -160,7 +162,10 @@ impl Client {
|
|||||||
self.renderer.update(ui);
|
self.renderer.update(ui);
|
||||||
self.renderer.draw()
|
self.renderer.draw()
|
||||||
}
|
}
|
||||||
WindowEvent::Resized(size) => self.renderer.resize(&size),
|
WindowEvent::Resized(size) => {
|
||||||
|
ui.resize((size.width, size.height));
|
||||||
|
self.renderer.resize(&size)
|
||||||
|
}
|
||||||
WindowEvent::KeyboardInput { event, .. } => {
|
WindowEvent::KeyboardInput { event, .. } => {
|
||||||
if event.state.is_pressed() {
|
if event.state.is_pressed() {
|
||||||
let child = ui
|
let child = ui
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use pollster::FutureExt;
|
use pollster::FutureExt;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use ui::{
|
use ui::{
|
||||||
Ui,
|
layout::Ui,
|
||||||
render::{UiLimits, UiRenderer},
|
render::{UiLimits, UiRenderer},
|
||||||
};
|
};
|
||||||
use wgpu::{util::StagingBelt, *};
|
use wgpu::{util::StagingBelt, *};
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use std::sync::{
|
use std::sync::{
|
||||||
Arc,
|
Arc,
|
||||||
atomic::{AtomicU32, Ordering},
|
atomic::{AtomicU32, Ordering},
|
||||||
mpsc::Sender,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct RefCounter(Arc<AtomicU32>);
|
pub struct RefCounter(Arc<AtomicU32>);
|
||||||
|
|||||||
Reference in New Issue
Block a user