text update for more code reuse + much better caching
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
layout::{
|
||||
Layers, Modules, TextAttrs, TextBuffer, TextData, TextOffset, TextureHandle, Textures,
|
||||
Layers, Modules, TextAttrs, TextBuffer, TextData, TextTexture, TextureHandle, Textures,
|
||||
UiRegion, UiVec2, Vec2, WidgetId, Widgets,
|
||||
},
|
||||
render::{Primitive, PrimitiveHandle},
|
||||
@@ -29,7 +29,7 @@ pub struct PainterCtx<'a> {
|
||||
pub screen_size: Vec2,
|
||||
pub modules: &'a mut Modules,
|
||||
pub px_dependent: &'a mut HashSet<Id>,
|
||||
drawing: HashSet<Id>,
|
||||
draw_started: HashSet<Id>,
|
||||
}
|
||||
|
||||
pub struct WidgetInstance {
|
||||
@@ -80,12 +80,14 @@ impl<'a> PainterCtx<'a> {
|
||||
screen_size: data.output_size,
|
||||
modules: &mut data.modules,
|
||||
px_dependent: &mut data.px_dependent,
|
||||
drawing: HashSet::default(),
|
||||
draw_started: HashSet::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn redraw(&mut self, id: Id) {
|
||||
self.drawing.clear();
|
||||
if self.draw_started.contains(&id) {
|
||||
return;
|
||||
}
|
||||
let Some(active) = self.active.get(&id) else {
|
||||
return;
|
||||
};
|
||||
@@ -99,11 +101,13 @@ impl<'a> PainterCtx<'a> {
|
||||
widgets: self.widgets,
|
||||
region: UiRegion::full(),
|
||||
screen_size: self.screen_size,
|
||||
px_dependent: self.px_dependent,
|
||||
id,
|
||||
};
|
||||
let desired = ctx.size_inner(id, active.region);
|
||||
if size != desired {
|
||||
self.redraw(rid);
|
||||
if self.drawing.contains(&id) {
|
||||
if self.draw_started.contains(&id) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -124,7 +128,7 @@ impl<'a> PainterCtx<'a> {
|
||||
}
|
||||
|
||||
pub fn draw(&mut self, id: Id) {
|
||||
self.drawing.clear();
|
||||
self.draw_started.clear();
|
||||
self.layers.clear();
|
||||
self.draw_inner(0, id, UiRegion::full(), None, None);
|
||||
}
|
||||
@@ -143,7 +147,7 @@ impl<'a> PainterCtx<'a> {
|
||||
// but this has a very weird issue where you can't move widgets unless u remove first
|
||||
// so swapping is impossible rn I think?
|
||||
// there's definitely better solutions like a counter (>1 = panic) but don't care rn
|
||||
if self.drawing.contains(&id) {
|
||||
if self.draw_started.contains(&id) {
|
||||
panic!("Cannot draw the same widget twice (1)");
|
||||
}
|
||||
let mut old_children = old_children.unwrap_or_default();
|
||||
@@ -165,7 +169,7 @@ impl<'a> PainterCtx<'a> {
|
||||
resize = active.resize;
|
||||
}
|
||||
|
||||
self.drawing.insert(id);
|
||||
self.draw_started.insert(id);
|
||||
|
||||
let mut painter = Painter {
|
||||
region,
|
||||
@@ -308,11 +312,7 @@ impl<'a, 'c> Painter<'a, 'c> {
|
||||
}
|
||||
|
||||
/// returns (handle, offset from top left)
|
||||
pub fn render_text(
|
||||
&mut self,
|
||||
buffer: &mut TextBuffer,
|
||||
attrs: &TextAttrs,
|
||||
) -> (TextureHandle, TextOffset) {
|
||||
pub fn render_text(&mut self, buffer: &mut TextBuffer, attrs: &TextAttrs) -> TextTexture {
|
||||
self.ctx.text.draw(buffer, attrs, self.ctx.textures)
|
||||
}
|
||||
|
||||
@@ -331,6 +331,8 @@ impl<'a, 'c> Painter<'a, 'c> {
|
||||
widgets: self.ctx.widgets,
|
||||
checked: &mut self.sized_children,
|
||||
screen_size: self.ctx.screen_size,
|
||||
px_dependent: self.ctx.px_dependent,
|
||||
id: self.id,
|
||||
region: self.region,
|
||||
}
|
||||
}
|
||||
@@ -357,9 +359,11 @@ pub struct SizeCtx<'a> {
|
||||
pub text: &'a mut TextData,
|
||||
pub textures: &'a mut Textures,
|
||||
widgets: &'a Widgets,
|
||||
px_dependent: &'a mut HashSet<Id>,
|
||||
checked: &'a mut HashMap<Id, UiVec2>,
|
||||
region: UiRegion,
|
||||
screen_size: Vec2,
|
||||
id: Id,
|
||||
}
|
||||
|
||||
impl SizeCtx<'_> {
|
||||
@@ -381,14 +385,11 @@ impl SizeCtx<'_> {
|
||||
pub fn size_within<W>(&mut self, id: &WidgetId<W>, region: UiRegion) -> UiVec2 {
|
||||
self.size_inner(id.id, region.within(&self.region))
|
||||
}
|
||||
pub fn px_size(&self) -> Vec2 {
|
||||
pub fn px_size(&mut self) -> Vec2 {
|
||||
self.px_dependent.insert(self.id);
|
||||
self.region.in_size(self.screen_size)
|
||||
}
|
||||
pub fn draw_text(
|
||||
&mut self,
|
||||
buffer: &mut TextBuffer,
|
||||
attrs: &TextAttrs,
|
||||
) -> (TextureHandle, TextOffset) {
|
||||
pub fn draw_text(&mut self, buffer: &mut TextBuffer, attrs: &TextAttrs) -> TextTexture {
|
||||
self.text.draw(buffer, attrs, self.textures)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use cosmic_text::{Attrs, AttrsList, Buffer, Family, FontSystem, Metrics, SwashCa
|
||||
use image::{Rgba, RgbaImage};
|
||||
|
||||
use crate::{
|
||||
layout::{TextureHandle, Textures, UiColor, Vec2},
|
||||
layout::{Align, TextureHandle, Textures, UiColor, Vec2},
|
||||
util::HashMap,
|
||||
};
|
||||
|
||||
@@ -27,6 +27,8 @@ pub struct TextAttrs {
|
||||
pub line_height: f32,
|
||||
pub family: Family<'static>,
|
||||
pub wrap: bool,
|
||||
/// inner alignment of text region (within where its drawn)
|
||||
pub align: Align,
|
||||
}
|
||||
|
||||
impl TextAttrs {
|
||||
@@ -56,6 +58,7 @@ impl Default for TextAttrs {
|
||||
line_height: size * 1.2,
|
||||
family: Family::SansSerif,
|
||||
wrap: false,
|
||||
align: Align::Center,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,7 +69,11 @@ impl TextData {
|
||||
buffer: &mut TextBuffer,
|
||||
attrs: &TextAttrs,
|
||||
textures: &mut Textures,
|
||||
) -> (TextureHandle, TextOffset) {
|
||||
) -> TextTexture {
|
||||
// TODO: either this or the layout stuff (or both) is super slow,
|
||||
// should probably do texture packing and things if possible.
|
||||
// very visible if you add just a couple of wrapping texts and resize window
|
||||
// should also be timed to figure out exactly what points need to be sped up
|
||||
let mut pixels = HashMap::default();
|
||||
let mut min_x = 0;
|
||||
let mut min_y = 0;
|
||||
@@ -113,22 +120,23 @@ impl TextData {
|
||||
let y = (y - min_y) as u32;
|
||||
image.put_pixel(x, y, color);
|
||||
}
|
||||
let offset = TextOffset {
|
||||
TextTexture {
|
||||
handle: textures.add(image),
|
||||
top_left: Vec2::new(min_x as f32, min_y as f32),
|
||||
bot_right: Vec2::new(max_width - max_x as f32, height - max_y as f32),
|
||||
};
|
||||
(textures.add(image), offset)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct TextOffset {
|
||||
#[derive(Clone)]
|
||||
pub struct TextTexture {
|
||||
pub handle: TextureHandle,
|
||||
pub top_left: Vec2,
|
||||
pub bot_right: Vec2,
|
||||
}
|
||||
|
||||
impl TextOffset {
|
||||
pub fn size(&self, handle: &TextureHandle) -> Vec2 {
|
||||
handle.size() - self.top_left + self.bot_right
|
||||
impl TextTexture {
|
||||
pub fn size(&self) -> Vec2 {
|
||||
self.handle.size() - self.top_left + self.bot_right
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ use std::{
|
||||
};
|
||||
|
||||
pub struct Ui {
|
||||
// TODO: make this at least pub(super)
|
||||
pub(crate) data: PainterData,
|
||||
root: Option<WidgetId>,
|
||||
updates: Vec<Id>,
|
||||
|
||||
Reference in New Issue
Block a user