initial text impl

This commit is contained in:
2025-08-23 21:15:39 -04:00
parent abcbc267b5
commit 5ce6fca275
33 changed files with 530 additions and 117 deletions

View File

@@ -1,4 +1,4 @@
use crate::{Painter, UiNum, UiRegion, Widget, WidgetId};
use crate::prelude::*;
pub struct Regioned {
pub region: UiRegion,

View File

@@ -1,7 +1,6 @@
use crate::prelude::*;
use image::DynamicImage;
use crate::{Color, Painter, TextureHandle, Widget, WidgetFnRet, render::RectPrimitive};
pub struct Image {
handle: Option<TextureHandle>,
}

View File

@@ -1,17 +1,17 @@
mod frame;
mod image;
mod num;
mod rect;
mod sense;
mod span;
mod stack;
mod text;
mod trait_fns;
pub use frame::*;
pub use image::*;
pub use num::*;
pub use rect::*;
pub use sense::*;
pub use span::*;
pub use stack::*;
pub use text::*;
pub use trait_fns::*;

View File

@@ -1,4 +1,4 @@
use crate::{Painter, UiColor, UiNum, Widget, render::RectPrimitive};
use crate::prelude::*;
#[derive(Clone, Copy)]
pub struct Rect {

View File

@@ -1,4 +1,4 @@
use crate::{Sense, SenseCtx, SenseFn, Sensor, Widget, WidgetId, WidgetIdFnRet, WidgetLike};
use crate::prelude::*;
pub trait Sensable<W, Ctx, Tag> {
fn on(self, sense: Sense, f: impl SenseFn<Ctx>) -> WidgetIdFnRet!(W, Ctx);

View File

@@ -1,4 +1,4 @@
use crate::{Dir, Painter, Sign, UIScalar, UiNum, UiRegion, Widget, WidgetId};
use crate::prelude::*;
pub struct Span {
pub children: Vec<(WidgetId, SpanLen)>,

View File

@@ -1,4 +1,4 @@
use crate::{Painter, Widget, WidgetId};
use crate::prelude::*;
pub struct Stack {
pub children: Vec<WidgetId>,

17
src/core/text.rs Normal file
View 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(),
}
}

View File

@@ -1,5 +1,5 @@
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> {
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) {
|ui| Regioned {
region: UiRegion::center().size(size.into()),
region: UiPos::center().expand(size.into()),
inner: self.add(ui).erase_type(),
}
}

View File

@@ -1,7 +1,7 @@
use std::{any::TypeId, marker::PhantomData};
use crate::{
FnTag, Ui, UiMsg, UiMsgSender, Widget, WidgetLike, WidgetTag,
layout::{FnTag, Ui, UiMsg, UiMsgSender, Widget, WidgetLike, WidgetTag},
util::{Id, RefCounter},
};
@@ -83,10 +83,10 @@ pub struct IdTag;
// pub trait WidgetIdFn<W, Ctx> = FnOnce(&mut Ui<Ctx>) -> WidgetId<W>;
macro_rules! WidgetIdFnRet {
($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)*) => {
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;

View File

@@ -1,8 +1,11 @@
mod color;
mod id;
mod num;
mod orientation;
mod painter;
mod region;
mod pos;
mod sense;
mod text;
mod texture;
mod ui;
mod vec2;
@@ -10,9 +13,12 @@ mod widget;
pub use color::*;
pub use id::*;
pub use num::*;
pub use orientation::*;
pub use painter::*;
pub use region::*;
pub use pos::*;
pub use sense::*;
pub use text::*;
pub use texture::*;
pub use ui::*;
pub use vec2::*;

21
src/layout/num.rs Normal file
View 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
}
}

View File

@@ -1,22 +1,21 @@
pub trait UiNum {
fn to_f32(self) -> f32;
use crate::layout::{Vec2, vec2};
#[derive(Clone, Copy, Debug)]
pub enum Corner {
TopLeft,
TopRight,
BotLeft,
BotRight,
}
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
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),
}
}
}

View File

@@ -1,5 +1,10 @@
use image::GenericImageView;
use crate::{
ActiveSensors, SensorMap, TextureHandle, UiRegion, WidgetId, Widgets,
layout::{
ActiveSensors, SensorMap, TextData, TextureHandle, Textures, UiPos, UiRegion, Vec2,
WidgetId, Widgets,
},
render::{Primitive, Primitives},
};
@@ -9,16 +14,22 @@ pub struct Painter<'a, Ctx: 'static> {
sensors_map: &'a SensorMap<Ctx>,
active_sensors: &'a mut ActiveSensors,
primitives: &'a mut Primitives,
textures: &'a mut Textures,
text: &'a mut TextData,
region: UiRegion,
screen_size: Vec2,
}
impl<'a, Ctx> Painter<'a, Ctx> {
pub fn new(
pub(crate) fn new(
nodes: &'a Widgets<Ctx>,
primitives: &'a mut Primitives,
ctx: &'a mut Ctx,
sensors_map: &'a SensorMap<Ctx>,
active_sensors: &'a mut ActiveSensors,
text: &'a mut TextData,
textures: &'a mut Textures,
screen_size: Vec2,
) -> Self {
Self {
nodes,
@@ -26,7 +37,10 @@ impl<'a, Ctx> Painter<'a, Ctx> {
active_sensors,
sensors_map,
primitives,
text,
region: UiRegion::full(),
textures,
screen_size,
}
}
@@ -69,9 +83,30 @@ impl<'a, Ctx> Painter<'a, Ctx> {
}
pub fn draw_texture(&mut self, handle: &TextureHandle) {
self.primitives.drawn_textures.push(handle.clone());
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 {
self.region
}

View File

@@ -1,6 +1,5 @@
use crate::{
Axis, Vec2,
layout::vec2,
layout::{Axis, Corner, Vec2, vec2},
util::{F32Util, impl_op},
};
@@ -12,6 +11,15 @@ pub struct 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 {
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 {
Self::anchor(corner.anchor())
}
@@ -69,6 +84,15 @@ impl UiPos {
self.flip();
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)]
@@ -122,21 +146,12 @@ impl UiRegion {
bot_right: UiPos::corner(Corner::BotRight),
}
}
pub fn center() -> Self {
Self::anchor(Vec2::new(0.5, 0.5))
}
pub fn anchor(anchor: Vec2) -> Self {
Self {
top_left: 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 {
Self {
top_left: self.top_left.within(parent),
@@ -170,19 +185,16 @@ impl UiRegion {
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 {
ScreenRect {
top_left: self.top_left.anchor * size + self.top_left.offset,
bot_right: self.bot_right.anchor * size + self.bot_right.offset,
}
}
pub fn center(&self) -> UiPos {
UiPos::center().within(self)
}
}
#[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),
}
}
}

View File

@@ -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)]
pub enum Sense {
@@ -81,10 +85,7 @@ impl<Ctx> Ui<Ctx> {
for sensor in &mut group.sensors {
if should_run(sensor.sense, group.cursor, group.hover) {
(sensor.f.box_clone())(SenseCtx {
ui: self,
app: ctx,
});
(sensor.f.box_clone())(SenseCtx { ui: self, app: ctx });
}
}
}

57
src/layout/text.rs Normal file
View 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)
}
}

View File

@@ -1,7 +1,14 @@
use std::ops::Index;
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 inner: TexturePrimitive,
counter: RefCounter,
@@ -10,11 +17,11 @@ pub struct TextureHandle {
/// a texture manager for a ui
/// note that this is heavily oriented towards wgpu's renderer so the primitives don't need mapped
#[derive(Default)]
pub struct Textures {
free: Vec<u32>,
images: Vec<Option<DynamicImage>>,
updates: Vec<Update>,
send: UiMsgSender,
}
pub enum TextureUpdate<'a> {
@@ -30,8 +37,16 @@ enum Update {
}
impl Textures {
pub fn add(&mut self, image: DynamicImage, send: UiMsgSender) -> TextureHandle {
let view_idx = self.push(image);
pub fn new(send: UiMsgSender) -> Self {
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
let sampler_idx = 0;
TextureHandle {
@@ -40,7 +55,7 @@ impl Textures {
sampler_idx,
},
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()
}
}

View File

@@ -1,8 +1,11 @@
use image::DynamicImage;
use crate::{
ActiveSensors, HashMap, Painter, SensorMap, TextureHandle, Textures, Widget, WidgetId,
WidgetLike,
HashMap,
layout::{
ActiveSensors, Painter, SensorMap, TextData, TextureHandle, Textures, Vec2, Widget,
WidgetId, WidgetLike,
},
render::Primitives,
util::{Id, IdTracker},
};
@@ -18,8 +21,11 @@ pub struct Ui<Ctx> {
updates: Vec<WidgetId>,
recv: Receiver<UiMsg>,
send: UiMsgSender,
size: Vec2,
// TODO: make these non pub(crate)
pub(crate) primitives: Primitives,
pub(crate) textures: Textures,
pub(crate) text: TextData,
full_redraw: bool,
pub(super) active_sensors: ActiveSensors,
@@ -85,7 +91,12 @@ impl<Ctx> Ui<Ctx> {
}
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)
@@ -100,6 +111,9 @@ impl<Ctx> Ui<Ctx> {
ctx,
&self.sensor_map,
&mut self.active_sensors,
&mut self.text,
&mut self.textures,
self.size,
);
if let Some(base) = &self.base {
painter.draw(base);
@@ -217,18 +231,20 @@ impl<Ctx> dyn Widget<Ctx> {
impl<Ctx: 'static> Default for Ui<Ctx> {
fn default() -> Self {
let (del_send, del_recv) = channel();
let (send, recv) = channel();
Self {
base: Default::default(),
widgets: Widgets::new(),
updates: Default::default(),
primitives: Default::default(),
textures: Textures::default(),
textures: Textures::new(send.clone()),
text: TextData::default(),
full_redraw: false,
active_sensors: Default::default(),
sensor_map: Default::default(),
send: del_send,
recv: del_recv,
send,
recv,
size: Vec2::ZERO,
}
}
}

View File

@@ -1,4 +1,7 @@
use crate::{util::{impl_op, F32Util}, UiNum};
use crate::{
layout::UiNum,
util::{F32Util, impl_op},
};
use std::ops::*;
#[repr(C)]
@@ -28,6 +31,27 @@ impl Vec2 {
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 {

View File

@@ -1,4 +1,5 @@
use crate::{Painter, Ui, WidgetId, WidgetIdFnRet};
use crate::layout::{Painter, Ui, WidgetId, WidgetIdFnRet};
use std::{any::Any, marker::PhantomData};
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)
macro_rules! WidgetFnRet {
($W:ty, $Ctx:ty) => {
impl FnOnce(&mut $crate::Ui<$Ctx>) -> $W
impl FnOnce(&mut $crate::layout::Ui<$Ctx>) -> $W
};
}
pub(crate) use WidgetFnRet;

View File

@@ -5,13 +5,16 @@
#![feature(trait_alias)]
#![feature(negative_impls)]
mod core;
mod layout;
pub mod core;
pub mod layout;
pub mod render;
mod util;
pub use core::*;
pub use layout::*;
pub mod prelude {
pub use crate::core::*;
pub use crate::layout::*;
pub use crate::render::*;
}
pub type HashMap<K, V> = std::collections::HashMap<K, V>;
pub type HashSet<K> = std::collections::HashSet<K>;

View File

@@ -1,6 +1,6 @@
use wgpu::VertexAttribute;
use crate::UiRegion;
use crate::layout::UiRegion;
#[repr(C)]
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable, Default)]

View File

@@ -1,7 +1,7 @@
use std::num::NonZero;
use crate::{
Ui,
layout::Ui,
render::{data::PrimitiveInstance, texture::GpuTextures, util::ArrBuf},
};
use data::WindowUniform;

View File

@@ -1,5 +1,5 @@
use crate::{
Color, UiRegion,
layout::{Color, TextureHandle, UiRegion},
render::{ArrBuf, data::PrimitiveInstance},
};
use bytemuck::Pod;
@@ -8,6 +8,8 @@ use wgpu::*;
pub struct Primitives {
pub(super) instances: Vec<PrimitiveInstance>,
pub(super) data: PrimitiveData,
// ensure drawn textures don't get freed
pub(crate) drawn_textures: Vec<TextureHandle>,
pub updated: bool,
}
@@ -16,6 +18,7 @@ impl Default for Primitives {
Self {
instances: Default::default(),
data: Default::default(),
drawn_textures: Default::default(),
updated: true,
}
}
@@ -98,6 +101,7 @@ impl Primitives {
self.updated = true;
self.instances.clear();
self.data.clear();
self.drawn_textures.clear();
}
}

View File

@@ -1,7 +1,7 @@
use image::{DynamicImage, EncodableLayout};
use wgpu::{util::DeviceExt, *};
use crate::{TextureUpdate, Textures};
use crate::layout::{TextureUpdate, Textures};
pub struct GpuTextures {
device: Device,
@@ -23,6 +23,9 @@ impl GpuTextures {
TextureUpdate::Free(i) => self.free(i),
}
}
// if changed {
// println!("{}", self.views.len());
// }
changed
}
fn set(&mut self, i: u32, image: &DynamicImage) {

View File

@@ -1,4 +1,4 @@
use ui::Ui;
use ui::layout::Ui;
use winit::{
application::ApplicationHandler,
event::WindowEvent,

View File

@@ -1,4 +1,4 @@
use ui::{CursorState, Vec2};
use ui::layout::{CursorState, Vec2};
use winit::event::WindowEvent;
use crate::testing::Client;

View File

@@ -2,7 +2,7 @@ use std::sync::Arc;
use app::App;
use render::Renderer;
use ui::*;
use ui::prelude::*;
use winit::{event::WindowEvent, event_loop::ActiveEventLoop, window::Window};
use crate::testing::input::Input;
@@ -80,10 +80,11 @@ impl Client {
color: UiColor,
main: &WidgetId<Regioned>,
to: &WidgetId<To>,
) -> impl WidgetLike<Client, IdTag> {
label: impl Into<String>,
) -> impl WidgetLike<Client, FnTag> {
let main = main.clone();
let to = to.clone().erase_type();
Rect::new(color)
let rect = Rect::new(color)
.id_on(Sense::PressStart, move |id, ctx| {
ctx.ui[&main].inner = to.clone();
ctx.ui[id].color = color.add_rgb(-0.2);
@@ -96,14 +97,15 @@ impl Client {
})
.edit_on(Sense::HoverEnd, move |r, _| {
r.color = color;
})
});
(rect, text(label)).stack()
}
let tabs = ui.add(
(
switch_button(UiColor::RED, &main, &pad_test),
switch_button(UiColor::GREEN, &main, &span_test),
switch_button(UiColor::BLUE, &main, &span_add_test),
switch_button(UiColor::RED, &main, &pad_test, "pad test"),
switch_button(UiColor::GREEN, &main, &span_test, "span test"),
switch_button(UiColor::BLUE, &main, &span_add_test, "span add test"),
)
.span(Dir::RIGHT, [1, 1, 1]),
);
@@ -113,8 +115,8 @@ impl Client {
println!("{}", ctx.ui.num_widgets());
})
.region(
UiRegion::corner(Corner::BotRight)
.size((150, 150))
UiPos::corner(Corner::BotRight)
.expand((150, 150))
.shifted((-75, -75)),
);
@@ -125,8 +127,8 @@ impl Client {
ctx.ui[&s].children.pop();
})
.region(
UiRegion::corner(Corner::BotLeft)
.size((150, 150))
UiPos::corner(Corner::BotLeft)
.expand((150, 150))
.shifted((75, -75)),
);
ui.set_base(
@@ -160,7 +162,10 @@ impl Client {
self.renderer.update(ui);
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, .. } => {
if event.state.is_pressed() {
let child = ui

View File

@@ -1,7 +1,7 @@
use pollster::FutureExt;
use std::sync::Arc;
use ui::{
Ui,
layout::Ui,
render::{UiLimits, UiRenderer},
};
use wgpu::{util::StagingBelt, *};

View File

@@ -1,7 +1,6 @@
use std::sync::{
Arc,
atomic::{AtomicU32, Ordering},
mpsc::Sender,
};
pub struct RefCounter(Arc<AtomicU32>);