reactivity base
This commit is contained in:
195
Cargo.lock
generated
195
Cargo.lock
generated
@@ -25,8 +25,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
|
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"const-random",
|
"getrandom",
|
||||||
"getrandom 0.3.3",
|
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"version_check",
|
"version_check",
|
||||||
"zerocopy",
|
"zerocopy",
|
||||||
@@ -269,26 +268,6 @@ dependencies = [
|
|||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "const-random"
|
|
||||||
version = "0.1.18"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359"
|
|
||||||
dependencies = [
|
|
||||||
"const-random-macro",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "const-random-macro"
|
|
||||||
version = "0.1.16"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
|
|
||||||
dependencies = [
|
|
||||||
"getrandom 0.2.16",
|
|
||||||
"once_cell",
|
|
||||||
"tiny-keccak",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation"
|
name = "core-foundation"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
@@ -453,15 +432,6 @@ version = "0.3.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"
|
checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fsevent-sys"
|
|
||||||
version = "4.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gethostname"
|
name = "gethostname"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
@@ -472,17 +442,6 @@ dependencies = [
|
|||||||
"windows-targets 0.48.5",
|
"windows-targets 0.48.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "getrandom"
|
|
||||||
version = "0.2.16"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"wasi 0.11.1+wasi-snapshot-preview1",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
@@ -492,7 +451,7 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"r-efi",
|
"r-efi",
|
||||||
"wasi 0.14.2+wasi-0.2.4",
|
"wasi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -583,9 +542,7 @@ name = "gui"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"notify",
|
|
||||||
"pollster",
|
"pollster",
|
||||||
"rhai",
|
|
||||||
"wgpu",
|
"wgpu",
|
||||||
"winit",
|
"winit",
|
||||||
]
|
]
|
||||||
@@ -632,35 +589,6 @@ dependencies = [
|
|||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "inotify"
|
|
||||||
version = "0.11.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 2.9.1",
|
|
||||||
"inotify-sys",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "inotify-sys"
|
|
||||||
version = "0.1.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "instant"
|
|
||||||
version = "0.1.13"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jni"
|
name = "jni"
|
||||||
version = "0.21.1"
|
version = "0.21.1"
|
||||||
@@ -689,7 +617,7 @@ version = "0.1.33"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a"
|
checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom 0.3.3",
|
"getrandom",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -720,26 +648,6 @@ version = "3.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
|
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "kqueue"
|
|
||||||
version = "1.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "eac30106d7dce88daf4a3fcb4879ea939476d5074a9b7ddd0fb97fa4bed5596a"
|
|
||||||
dependencies = [
|
|
||||||
"kqueue-sys",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "kqueue-sys"
|
|
||||||
version = "1.0.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 1.3.2",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.174"
|
version = "0.2.174"
|
||||||
@@ -846,18 +754,6 @@ dependencies = [
|
|||||||
"paste",
|
"paste",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "mio"
|
|
||||||
version = "1.0.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"log",
|
|
||||||
"wasi 0.11.1+wasi-snapshot-preview1",
|
|
||||||
"windows-sys 0.59.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "naga"
|
name = "naga"
|
||||||
version = "26.0.0"
|
version = "26.0.0"
|
||||||
@@ -914,30 +810,6 @@ dependencies = [
|
|||||||
"jni-sys",
|
"jni-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "notify"
|
|
||||||
version = "8.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 2.9.1",
|
|
||||||
"fsevent-sys",
|
|
||||||
"inotify",
|
|
||||||
"kqueue",
|
|
||||||
"libc",
|
|
||||||
"log",
|
|
||||||
"mio",
|
|
||||||
"notify-types",
|
|
||||||
"walkdir",
|
|
||||||
"windows-sys 0.60.2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "notify-types"
|
|
||||||
version = "2.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.19"
|
version = "0.2.19"
|
||||||
@@ -1187,9 +1059,6 @@ name = "once_cell"
|
|||||||
version = "1.21.3"
|
version = "1.21.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||||
dependencies = [
|
|
||||||
"portable-atomic",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "orbclient"
|
name = "orbclient"
|
||||||
@@ -1410,32 +1279,6 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832"
|
checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rhai"
|
|
||||||
version = "1.22.2"
|
|
||||||
source = "git+https://github.com/rhaiscript/rhai#9508db6a828d8d8b2ac868054d985098c62ba904"
|
|
||||||
dependencies = [
|
|
||||||
"ahash",
|
|
||||||
"bitflags 2.9.1",
|
|
||||||
"instant",
|
|
||||||
"num-traits",
|
|
||||||
"once_cell",
|
|
||||||
"rhai_codegen",
|
|
||||||
"smallvec",
|
|
||||||
"smartstring",
|
|
||||||
"thin-vec",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rhai_codegen"
|
|
||||||
version = "3.1.0"
|
|
||||||
source = "git+https://github.com/rhaiscript/rhai#9508db6a828d8d8b2ac868054d985098c62ba904"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-hash"
|
name = "rustc-hash"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -1555,17 +1398,6 @@ version = "1.15.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "smartstring"
|
|
||||||
version = "1.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg",
|
|
||||||
"static_assertions",
|
|
||||||
"version_check",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smithay-client-toolkit"
|
name = "smithay-client-toolkit"
|
||||||
version = "0.19.2"
|
version = "0.19.2"
|
||||||
@@ -1641,12 +1473,6 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thin-vec"
|
|
||||||
version = "0.2.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "144f754d318415ac792f9d69fc87abbbfc043ce2ef041c60f16ad828f638717d"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.69"
|
version = "1.0.69"
|
||||||
@@ -1687,15 +1513,6 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tiny-keccak"
|
|
||||||
version = "2.0.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
|
|
||||||
dependencies = [
|
|
||||||
"crunchy",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tiny-skia"
|
name = "tiny-skia"
|
||||||
version = "0.11.4"
|
version = "0.11.4"
|
||||||
@@ -1794,12 +1611,6 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasi"
|
|
||||||
version = "0.11.1+wasi-snapshot-preview1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.14.2+wasi-0.2.4"
|
version = "0.14.2+wasi-0.2.4"
|
||||||
|
|||||||
@@ -8,8 +8,6 @@ edition = "2021"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
pollster = "0.4.0"
|
pollster = "0.4.0"
|
||||||
winit = "0.30.11"
|
winit = "0.30.11"
|
||||||
rhai = { git = "https://github.com/rhaiscript/rhai", features = ["f32_float"] }
|
|
||||||
notify = "8.0.0"
|
|
||||||
wgpu = "26.0.1"
|
wgpu = "26.0.1"
|
||||||
bytemuck = "1.23.1"
|
bytemuck = "1.23.1"
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
let a = rect();
|
|
||||||
a.top_left = anchor_offset(0.5, 0.5, -200.0, -100.0);
|
|
||||||
a.bottom_right = anchor_offset(0.5, 0.5, 100.0, 100.0);
|
|
||||||
a.radius = 40.0;
|
|
||||||
a.inner_radius = 30.0;
|
|
||||||
a.thickness = 10.0;
|
|
||||||
|
|
||||||
let b = rect();
|
|
||||||
b.top_left = anchor_offset(0.25, 0.25, -100.0, -100.0);
|
|
||||||
b.bottom_right = anchor_offset(0.25, 0.25, 100.0, 100.0);
|
|
||||||
b.radius = 40.0;
|
|
||||||
b.inner_radius = 30.0;
|
|
||||||
b.thickness = 10.0;
|
|
||||||
|
|
||||||
[a, b]
|
|
||||||
@@ -2,7 +2,7 @@ use std::ops::Range;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
primitive::{Axis, Painter, RoundedRectData, UIRegion},
|
primitive::{Axis, Painter, RoundedRectData, UIRegion},
|
||||||
NodeArray, UIColor, UINode,
|
UIColor, Widget, WidgetArrLike, WidgetFn, WidgetId, WidgetLike,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
@@ -20,7 +20,7 @@ impl RoundedRect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UINode for RoundedRect {
|
impl Widget for RoundedRect {
|
||||||
fn draw(&self, painter: &mut Painter) {
|
fn draw(&self, painter: &mut Painter) {
|
||||||
painter.write(RoundedRectData {
|
painter.write(RoundedRectData {
|
||||||
color: self.color,
|
color: self.color,
|
||||||
@@ -32,11 +32,11 @@ impl UINode for RoundedRect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Span {
|
pub struct Span {
|
||||||
pub elements: Vec<(Range<f32>, Box<dyn UINode>)>,
|
pub elements: Vec<(Range<f32>, WidgetId)>,
|
||||||
pub axis: Axis,
|
pub axis: Axis,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UINode for Span {
|
impl Widget for Span {
|
||||||
fn draw(&self, painter: &mut Painter) {
|
fn draw(&self, painter: &mut Painter) {
|
||||||
for (span, child) in &self.elements {
|
for (span, child) in &self.elements {
|
||||||
let mut sub_region = UIRegion::full();
|
let mut sub_region = UIRegion::full();
|
||||||
@@ -52,14 +52,13 @@ impl Span {
|
|||||||
pub fn proportioned<const LEN: usize>(
|
pub fn proportioned<const LEN: usize>(
|
||||||
axis: Axis,
|
axis: Axis,
|
||||||
ratios: [impl UINum; LEN],
|
ratios: [impl UINum; LEN],
|
||||||
elements: impl NodeArray<LEN>,
|
elements: [WidgetId; LEN],
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let ratios = ratios.map(|r| r.to_f32());
|
let ratios = ratios.map(|r| r.to_f32());
|
||||||
let total: f32 = ratios.iter().sum();
|
let total: f32 = ratios.iter().sum();
|
||||||
let mut start = 0.0;
|
let mut start = 0.0;
|
||||||
Self {
|
Self {
|
||||||
elements: elements
|
elements: elements
|
||||||
.to_arr()
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.zip(ratios)
|
.zip(ratios)
|
||||||
.map(|(e, r)| {
|
.map(|(e, r)| {
|
||||||
@@ -74,15 +73,15 @@ impl Span {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Regioned<N: UINode> {
|
pub struct Regioned {
|
||||||
region: UIRegion,
|
region: UIRegion,
|
||||||
inner: N,
|
inner: WidgetId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: UINode> UINode for Regioned<N> {
|
impl Widget for Regioned {
|
||||||
fn draw(&self, painter: &mut Painter) {
|
fn draw(&self, painter: &mut Painter) {
|
||||||
painter.region.select(&self.region);
|
painter.region.select(&self.region);
|
||||||
self.inner.draw(painter);
|
painter.draw(&self.inner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,26 +117,26 @@ impl<T: UINum> From<T> for Padding {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait NodeUtil: Sized + UINode {
|
pub trait WidgetUtil<W> {
|
||||||
fn pad(self, padding: impl Into<Padding>) -> Regioned<Self>;
|
fn pad(self, padding: impl Into<Padding>) -> impl WidgetLike<Regioned>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: UINode> NodeUtil for T {
|
impl<W: Widget, WL: WidgetLike<W>> WidgetUtil<W> for WL {
|
||||||
fn pad(self, padding: impl Into<Padding>) -> Regioned<Self> {
|
fn pad(self, padding: impl Into<Padding>) -> impl WidgetLike<Regioned> {
|
||||||
Regioned {
|
WidgetFn(|ui| Regioned {
|
||||||
region: padding.into().region(),
|
region: padding.into().region(),
|
||||||
inner: self,
|
inner: self.id(ui).erase_type(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait NodeArrayUtil<const LEN: usize> {
|
pub trait WidgetArrUtil<const LEN: usize, Ws> {
|
||||||
fn proportioned(self, axis: Axis, ratios: [impl UINum; LEN]) -> Span;
|
fn span(self, axis: Axis, ratios: [impl UINum; LEN]) -> impl WidgetLike<Span>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: NodeArray<LEN>, const LEN: usize> NodeArrayUtil<LEN> for T {
|
impl<const LEN: usize, Ws, Wa: WidgetArrLike<LEN, Ws>> WidgetArrUtil<LEN, Ws> for Wa {
|
||||||
fn proportioned(self, axis: Axis, ratios: [impl UINum; LEN]) -> Span {
|
fn span(self, axis: Axis, ratios: [impl UINum; LEN]) -> impl WidgetLike<Span> {
|
||||||
Span::proportioned(axis, ratios, self)
|
WidgetFn(move |ui| Span::proportioned(axis, ratios, self.ui(ui).arr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,66 +1,8 @@
|
|||||||
mod node;
|
mod ui;
|
||||||
pub use node::*;
|
mod widget;
|
||||||
|
|
||||||
use crate::primitive::{Color, Painter};
|
pub use ui::*;
|
||||||
|
pub use widget::*;
|
||||||
|
|
||||||
|
use crate::primitive::Color;
|
||||||
pub type UIColor = Color<u8>;
|
pub type UIColor = Color<u8>;
|
||||||
|
|
||||||
pub trait UINode: 'static {
|
|
||||||
fn draw(&self, painter: &mut Painter);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct UI {
|
|
||||||
base: Box<dyn UINode>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UI {
|
|
||||||
pub fn to_primitives(&self) -> Painter {
|
|
||||||
let mut painter = Painter::default();
|
|
||||||
self.base.draw(&mut painter);
|
|
||||||
painter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: UINode> From<N> for UI {
|
|
||||||
fn from(node: N) -> Self {
|
|
||||||
Self {
|
|
||||||
base: Box::new(node),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UINode for Box<dyn UINode> {
|
|
||||||
fn draw(&self, painter: &mut Painter) {
|
|
||||||
self.as_ref().draw(painter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait NodeArray<const LEN: usize> {
|
|
||||||
fn to_arr(self) -> [Box<dyn UINode>; LEN];
|
|
||||||
}
|
|
||||||
|
|
||||||
// I hate this language it's so bad why do I even use it
|
|
||||||
macro_rules! impl_node_arr {
|
|
||||||
($n:expr;$($T:tt)+) => {
|
|
||||||
impl<$($T: UINode,)*> NodeArray<$n> for ($($T,)*) {
|
|
||||||
fn to_arr(self) -> [Box<dyn UINode>; $n] {
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
let ($($T,)*) = self;
|
|
||||||
[$(Box::new($T),)*]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_node_arr!(1;A);
|
|
||||||
impl_node_arr!(2;A B);
|
|
||||||
impl_node_arr!(3;A B C);
|
|
||||||
impl_node_arr!(4;A B C D);
|
|
||||||
impl_node_arr!(5;A B C D E);
|
|
||||||
impl_node_arr!(6;A B C D E F);
|
|
||||||
impl_node_arr!(7;A B C D E F G);
|
|
||||||
impl_node_arr!(8;A B C D E F G H);
|
|
||||||
impl_node_arr!(9;A B C D E F G H I);
|
|
||||||
impl_node_arr!(10;A B C D E F G H I J);
|
|
||||||
impl_node_arr!(11;A B C D E F G H I J K);
|
|
||||||
impl_node_arr!(12;A B C D E F G H I J K L);
|
|
||||||
|
|||||||
101
src/layout/ui.rs
Normal file
101
src/layout/ui.rs
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
use crate::{
|
||||||
|
primitive::{Painter, Primitives},
|
||||||
|
util::{IDTracker, ID},
|
||||||
|
HashMap, Widget, WidgetId, WidgetLike, WidgetRef,
|
||||||
|
};
|
||||||
|
use std::{
|
||||||
|
any::{Any, TypeId},
|
||||||
|
cell::RefCell,
|
||||||
|
rc::Rc,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct UI {
|
||||||
|
ids: IDTracker,
|
||||||
|
base: Option<WidgetId>,
|
||||||
|
pub widgets: Widgets,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Widgets(HashMap<ID, Box<dyn Widget>>);
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct UIBuilder {
|
||||||
|
ui: Rc<RefCell<UI>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<UI> for UIBuilder {
|
||||||
|
fn from(ui: UI) -> Self {
|
||||||
|
UIBuilder {
|
||||||
|
ui: Rc::new(RefCell::new(ui)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UIBuilder {
|
||||||
|
pub fn add<W: Widget>(&mut self, w: W) -> WidgetRef<W> {
|
||||||
|
WidgetRef::new(self.clone(), [self.push(w)])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push<W: Widget>(&mut self, w: W) -> WidgetId {
|
||||||
|
let mut ui = self.ui.borrow_mut();
|
||||||
|
let id = ui.ids.next();
|
||||||
|
ui.widgets.insert(id.duplicate(), w);
|
||||||
|
WidgetId::new(id, TypeId::of::<W>())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn finish<WL: WidgetLike<W>, W>(mut self, base: WL) -> UI {
|
||||||
|
let base = base.id(&mut self).erase_type();
|
||||||
|
let mut ui = Rc::into_inner(self.ui).unwrap().into_inner();
|
||||||
|
ui.base = Some(base);
|
||||||
|
ui
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UI {
|
||||||
|
pub fn build() -> UIBuilder {
|
||||||
|
Self::empty().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn empty() -> Self {
|
||||||
|
Self {
|
||||||
|
ids: IDTracker::new(),
|
||||||
|
base: None,
|
||||||
|
widgets: Widgets::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_primitives(&self) -> Primitives {
|
||||||
|
let mut painter = Painter::new(&self.widgets);
|
||||||
|
if let Some(base) = &self.base {
|
||||||
|
painter.draw(base);
|
||||||
|
}
|
||||||
|
painter.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widgets {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self(HashMap::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self, id: &WidgetId) -> &dyn Widget {
|
||||||
|
self.0.get(&id.id).unwrap().as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_mut<W: Widget>(&mut self, id: &WidgetId<W>) -> Option<&mut W> {
|
||||||
|
self.0.get_mut(&id.id).unwrap().as_any_mut().downcast_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert(&mut self, id: ID, widget: impl Widget) {
|
||||||
|
self.0.insert(id, Box::new(widget));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert_any(&mut self, id: ID, widget: Box<dyn Widget>) {
|
||||||
|
self.0.insert(id, widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl dyn Widget {
|
||||||
|
pub fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
157
src/layout/widget.rs
Normal file
157
src/layout/widget.rs
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
use std::{
|
||||||
|
any::{Any, TypeId},
|
||||||
|
marker::PhantomData,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{primitive::Painter, util::ID, UIBuilder};
|
||||||
|
|
||||||
|
pub trait Widget: 'static + Any {
|
||||||
|
fn draw(&self, painter: &mut Painter);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<W: Widget> Widget for (W,) {
|
||||||
|
fn draw(&self, painter: &mut Painter) {
|
||||||
|
self.0.draw(painter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, Hash, PartialEq, Debug)]
|
||||||
|
pub struct WidgetId<W = ()> {
|
||||||
|
pub(super) ty: TypeId,
|
||||||
|
pub(super) id: ID,
|
||||||
|
_pd: PhantomData<W>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: temp
|
||||||
|
impl Clone for WidgetId {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
ty: self.ty,
|
||||||
|
id: self.id.duplicate(),
|
||||||
|
_pd: self._pd,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<W> WidgetId<W> {
|
||||||
|
pub(super) fn new(id: ID, ty: TypeId) -> Self {
|
||||||
|
Self {
|
||||||
|
ty,
|
||||||
|
id,
|
||||||
|
_pd: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn erase_type(self) -> WidgetId<()> {
|
||||||
|
self.cast_type()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cast_type<W2>(self) -> WidgetId<W2> {
|
||||||
|
WidgetId {
|
||||||
|
ty: self.ty,
|
||||||
|
id: self.id,
|
||||||
|
_pd: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait WidgetLike<W> {
|
||||||
|
fn id(self, ui: &mut UIBuilder) -> WidgetId<W>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// wouldn't be needed if negative trait bounds & disjoint impls existed
|
||||||
|
pub struct WidgetFn<F: FnOnce(&mut UIBuilder) -> W, W>(pub F);
|
||||||
|
|
||||||
|
impl<W: Widget, F: FnOnce(&mut UIBuilder) -> W> WidgetLike<W> for WidgetFn<F, W> {
|
||||||
|
fn id(self, ui: &mut UIBuilder) -> WidgetId<W> {
|
||||||
|
let w = (self.0)(ui);
|
||||||
|
ui.add(w).to_id()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<W: Widget> WidgetLike<W> for W {
|
||||||
|
fn id(self, ui: &mut UIBuilder) -> WidgetId<W> {
|
||||||
|
ui.add(self).to_id()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<W> WidgetLike<W> for WidgetId<W> {
|
||||||
|
fn id(self, _: &mut UIBuilder) -> WidgetId<W> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<W> WidgetLike<W> for WidgetArr<1, (W,)> {
|
||||||
|
fn id(self, _: &mut UIBuilder) -> WidgetId<W> {
|
||||||
|
let [id] = self.arr;
|
||||||
|
id.cast_type()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WidgetArr<const LEN: usize, Ws> {
|
||||||
|
pub ui: UIBuilder,
|
||||||
|
pub arr: [WidgetId<()>; LEN],
|
||||||
|
_pd: PhantomData<Ws>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const LEN: usize, Ws> WidgetArr<LEN, Ws> {
|
||||||
|
pub fn new(ui: UIBuilder, arr: [WidgetId<()>; LEN]) -> Self {
|
||||||
|
Self {
|
||||||
|
ui,
|
||||||
|
arr,
|
||||||
|
_pd: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type WidgetRef<W> = WidgetArr<1, (W,)>;
|
||||||
|
|
||||||
|
impl<W> WidgetRef<W> {
|
||||||
|
pub fn handle(&self) -> WidgetId<W> {
|
||||||
|
let [id] = &self.arr;
|
||||||
|
id.clone().cast_type()
|
||||||
|
}
|
||||||
|
pub fn to_id(self) -> WidgetId<W> {
|
||||||
|
let [id] = self.arr;
|
||||||
|
id.cast_type()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait WidgetArrLike<const LEN: usize, Ws> {
|
||||||
|
fn ui(self, ui: &mut UIBuilder) -> WidgetArr<LEN, Ws>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const LEN: usize, Ws> WidgetArrLike<LEN, Ws> for WidgetArr<LEN, Ws> {
|
||||||
|
fn ui(self, _: &mut UIBuilder) -> WidgetArr<LEN, Ws> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// I hate this language it's so bad why do I even use it
|
||||||
|
macro_rules! impl_node_arr {
|
||||||
|
($n:expr;$($T:tt)*) => {
|
||||||
|
impl<$($T,${concat($T,$T)}: WidgetLike<$T>,)*> WidgetArrLike<$n, ($($T,)*)> for ($(${concat($T,$T)},)*) {
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn ui(self, ui: &mut UIBuilder) -> WidgetArr<$n, ($($T,)*)> {
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
let ($($T,)*) = self;
|
||||||
|
WidgetArr::new(
|
||||||
|
ui.clone(),
|
||||||
|
[$($T.id(ui).cast_type(),)*],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_node_arr!(1;A);
|
||||||
|
impl_node_arr!(2;A B);
|
||||||
|
impl_node_arr!(3;A B C);
|
||||||
|
impl_node_arr!(4;A B C D);
|
||||||
|
impl_node_arr!(5;A B C D E);
|
||||||
|
impl_node_arr!(6;A B C D E F);
|
||||||
|
impl_node_arr!(7;A B C D E F G);
|
||||||
|
impl_node_arr!(8;A B C D E F G H);
|
||||||
|
impl_node_arr!(9;A B C D E F G H I);
|
||||||
|
impl_node_arr!(10;A B C D E F G H I J);
|
||||||
|
impl_node_arr!(11;A B C D E F G H I J K);
|
||||||
|
impl_node_arr!(12;A B C D E F G H I J K L);
|
||||||
@@ -2,9 +2,15 @@
|
|||||||
#![feature(const_ops)]
|
#![feature(const_ops)]
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![feature(const_from)]
|
#![feature(const_from)]
|
||||||
|
#![feature(trait_alias)]
|
||||||
|
|
||||||
mod layout;
|
mod layout;
|
||||||
mod render;
|
mod render;
|
||||||
|
mod util;
|
||||||
|
mod base;
|
||||||
|
|
||||||
pub use layout::*;
|
pub use layout::*;
|
||||||
pub use render::*;
|
pub use render::*;
|
||||||
|
pub use base::*;
|
||||||
|
|
||||||
|
pub type HashMap<K, V> = std::collections::HashMap<K, V>;
|
||||||
|
|||||||
@@ -8,23 +8,19 @@ pub use def::*;
|
|||||||
pub use format::*;
|
pub use format::*;
|
||||||
pub use point::*;
|
pub use point::*;
|
||||||
|
|
||||||
use crate::{render::data::PrimitiveInstance, UINode};
|
use crate::{render::data::PrimitiveInstance, WidgetId, Widgets};
|
||||||
use bytemuck::Pod;
|
use bytemuck::Pod;
|
||||||
|
|
||||||
pub struct Painter {
|
#[derive(Default)]
|
||||||
pub region: UIRegion,
|
pub struct Primitives {
|
||||||
pub instances: Vec<PrimitiveInstance>,
|
pub instances: Vec<PrimitiveInstance>,
|
||||||
pub data: Vec<u32>,
|
pub data: Vec<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Painter {
|
pub struct Painter<'a> {
|
||||||
fn default() -> Self {
|
nodes: &'a Widgets,
|
||||||
Self {
|
primitives: Primitives,
|
||||||
region: UIRegion::full(),
|
pub region: UIRegion,
|
||||||
instances: Default::default(),
|
|
||||||
data: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// NOTE: Self must have at least u32 alignment
|
/// NOTE: Self must have at least u32 alignment
|
||||||
@@ -32,19 +28,36 @@ pub trait PrimitiveData: Pod {
|
|||||||
const DISCRIM: u32;
|
const DISCRIM: u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Painter {
|
impl<'a> Painter<'a> {
|
||||||
pub fn write<D: PrimitiveData>(&mut self, data: D) {
|
pub fn new(nodes: &'a Widgets) -> Self {
|
||||||
let ptr = self.data.len() as u32;
|
Self {
|
||||||
|
nodes,
|
||||||
|
primitives: Primitives::default(),
|
||||||
|
region: UIRegion::full(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn write<Data: PrimitiveData>(&mut self, data: Data) {
|
||||||
|
let ptr = self.primitives.data.len() as u32;
|
||||||
let region = self.region;
|
let region = self.region;
|
||||||
self.instances.push(PrimitiveInstance { region, ptr });
|
self.primitives
|
||||||
self.data.push(D::DISCRIM);
|
.instances
|
||||||
self.data
|
.push(PrimitiveInstance { region, ptr });
|
||||||
|
self.primitives.data.push(Data::DISCRIM);
|
||||||
|
self.primitives
|
||||||
|
.data
|
||||||
.extend_from_slice(bytemuck::cast_slice::<_, u32>(&[data]));
|
.extend_from_slice(bytemuck::cast_slice::<_, u32>(&[data]));
|
||||||
}
|
}
|
||||||
pub fn draw_within(&mut self, node: &impl UINode, region: UIRegion) {
|
pub fn draw(&mut self, node: &WidgetId) {
|
||||||
|
self.nodes.get(node).draw(self);
|
||||||
|
}
|
||||||
|
pub fn draw_within(&mut self, node: &WidgetId, region: UIRegion) {
|
||||||
let old = self.region;
|
let old = self.region;
|
||||||
self.region.select(®ion);
|
self.region.select(®ion);
|
||||||
node.draw(self);
|
self.draw(node);
|
||||||
self.region = old;
|
self.region = old;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn finish(self) -> Primitives {
|
||||||
|
self.primitives
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use app::App;
|
use app::App;
|
||||||
use gui::{primitive::Axis, NodeArrayUtil, NodeUtil, RoundedRect, UIColor};
|
use gui::{primitive::Axis, RoundedRect, UIColor, WidgetArrLike, WidgetArrUtil, WidgetUtil, UI};
|
||||||
use render::Renderer;
|
use render::Renderer;
|
||||||
use winit::{event::WindowEvent, event_loop::ActiveEventLoop, window::Window};
|
use winit::{event::WindowEvent, event_loop::ActiveEventLoop, window::Window};
|
||||||
|
|
||||||
@@ -25,24 +25,32 @@ impl Client {
|
|||||||
thickness: 0.0,
|
thickness: 0.0,
|
||||||
inner_radius: 0.0,
|
inner_radius: 0.0,
|
||||||
};
|
};
|
||||||
let ui = (
|
let mut ui = UI::build();
|
||||||
|
let blue = ui.add(rect.color(UIColor::BLUE));
|
||||||
|
let handle = blue.handle();
|
||||||
|
let mut ui = ui.finish(
|
||||||
(
|
(
|
||||||
rect.color(UIColor::BLUE),
|
|
||||||
(
|
(
|
||||||
rect.color(UIColor::RED),
|
blue,
|
||||||
(rect.color(UIColor::ORANGE), rect.color(UIColor::LIME))
|
(
|
||||||
.proportioned(Axis::Y, [1, 1]),
|
rect.color(UIColor::RED),
|
||||||
rect.color(UIColor::YELLOW),
|
(
|
||||||
|
rect.color(UIColor::ORANGE),
|
||||||
|
rect.color(UIColor::LIME).pad(10.0),
|
||||||
|
)
|
||||||
|
.span(Axis::Y, [1, 1]),
|
||||||
|
rect.color(UIColor::YELLOW),
|
||||||
|
)
|
||||||
|
.span(Axis::X, [2, 2, 1])
|
||||||
|
.pad(10),
|
||||||
)
|
)
|
||||||
.proportioned(Axis::X, [2, 2, 1])
|
.span(Axis::X, [1, 3]),
|
||||||
.pad(10),
|
rect.color(UIColor::GREEN),
|
||||||
)
|
)
|
||||||
.proportioned(Axis::X, [1, 3]),
|
.span(Axis::Y, [3, 1])
|
||||||
rect.color(UIColor::GREEN),
|
.pad(10),
|
||||||
)
|
);
|
||||||
.proportioned(Axis::Y, [3, 1])
|
ui.widgets.get_mut(&handle).unwrap().color = UIColor::MAGENTA;
|
||||||
.pad(10)
|
|
||||||
.into();
|
|
||||||
renderer.update(&ui);
|
renderer.update(&ui);
|
||||||
Self { renderer }
|
Self { renderer }
|
||||||
}
|
}
|
||||||
|
|||||||
43
src/util/id.rs
Normal file
43
src/util/id.rs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/// intentionally does not implement copy or clone
|
||||||
|
/// which should make it harder to misuse;
|
||||||
|
/// the idea is to generally try to guarantee all IDs
|
||||||
|
/// point to something valid, although duplicate
|
||||||
|
/// gets around this if needed
|
||||||
|
#[derive(Eq, Hash, PartialEq, Debug)]
|
||||||
|
pub struct ID(usize);
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct IDTracker {
|
||||||
|
free: Vec<ID>,
|
||||||
|
cur: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IDTracker {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::should_implement_trait)]
|
||||||
|
pub fn next(&mut self) -> ID {
|
||||||
|
if let Some(id) = self.free.pop() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
let id = ID(self.cur);
|
||||||
|
self.cur += 1;
|
||||||
|
id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn free(&mut self, id: ID) {
|
||||||
|
self.free.push(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ID {
|
||||||
|
/// this must be used carefully to make sure
|
||||||
|
/// all IDs are still valid references;
|
||||||
|
/// named weirdly to indicate this.
|
||||||
|
/// generally should not be used in "user" code
|
||||||
|
pub fn duplicate(&self) -> Self {
|
||||||
|
Self(self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
3
src/util/mod.rs
Normal file
3
src/util/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
mod id;
|
||||||
|
|
||||||
|
pub use id::*;
|
||||||
Reference in New Issue
Block a user