mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-04-28 03:00:18 -04:00
wallet: editbox clipping rect when regenerating mesh
This commit is contained in:
@@ -31,6 +31,15 @@ pub struct Vertex {
|
||||
pub uv: [f32; 2],
|
||||
}
|
||||
|
||||
impl Vertex {
|
||||
pub fn pos(&self) -> Point {
|
||||
self.pos.into()
|
||||
}
|
||||
pub fn set_pos(&mut self, pos: &Point) {
|
||||
self.pos = pos.as_arr();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Point {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
@@ -41,6 +50,10 @@ impl Point {
|
||||
(self.x, self.y)
|
||||
}
|
||||
|
||||
pub fn as_arr(&self) -> [f32; 2] {
|
||||
[self.x, self.y]
|
||||
}
|
||||
|
||||
pub fn offset(&self, off_x: f32, off_y: f32) -> Self {
|
||||
Self { x: self.x + off_x, y: self.y + off_y }
|
||||
}
|
||||
@@ -50,6 +63,12 @@ impl Point {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[f32; 2]> for Point {
|
||||
fn from(pos: [f32; 2]) -> Self {
|
||||
Self { x: pos[0], y: pos[1] }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Rectangle {
|
||||
pub x: f32,
|
||||
@@ -98,6 +117,21 @@ impl Rectangle {
|
||||
Some(clipped)
|
||||
}
|
||||
|
||||
pub fn clip_point(&self, point: &mut Point) {
|
||||
if point.x < self.x {
|
||||
point.x = self.x;
|
||||
}
|
||||
if point.y < self.y {
|
||||
point.y = self.y;
|
||||
}
|
||||
if point.x > self.x + self.w {
|
||||
point.x = self.x + self.w;
|
||||
}
|
||||
if point.y > self.y + self.h {
|
||||
point.y = self.y + self.h;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains(&self, point: &Point) -> bool {
|
||||
self.x <= point.x &&
|
||||
point.x <= self.x + self.w &&
|
||||
|
||||
@@ -22,14 +22,26 @@ pub struct MeshInfo {
|
||||
pub struct MeshBuilder {
|
||||
verts: Vec<Vertex>,
|
||||
indices: Vec<u16>,
|
||||
clipper: Option<Rectangle>,
|
||||
}
|
||||
|
||||
impl MeshBuilder {
|
||||
pub fn new() -> Self {
|
||||
Self { verts: vec![], indices: vec![] }
|
||||
Self { verts: vec![], indices: vec![], clipper: None }
|
||||
}
|
||||
pub fn with_clip(clipper: Rectangle) -> Self {
|
||||
Self { verts: vec![], indices: vec![], clipper: Some(clipper) }
|
||||
}
|
||||
|
||||
pub fn append(&mut self, mut verts: Vec<Vertex>, indices: Vec<u16>) {
|
||||
if let Some(clipper) = &self.clipper {
|
||||
for vert in &mut verts {
|
||||
let mut vpos = vert.pos();
|
||||
clipper.clip_point(&mut vpos);
|
||||
vert.set_pos(&vpos);
|
||||
}
|
||||
}
|
||||
|
||||
let mut indices = indices.into_iter().map(|i| i + self.verts.len() as u16).collect();
|
||||
self.verts.append(&mut verts);
|
||||
self.indices.append(&mut indices);
|
||||
|
||||
@@ -103,7 +103,6 @@ impl RepeatingKeyTimer {
|
||||
|
||||
#[derive(Clone)]
|
||||
struct TextRenderInfo {
|
||||
glyphs: Vec<Glyph>,
|
||||
mesh: MeshInfo,
|
||||
texture_id: TextureId,
|
||||
}
|
||||
@@ -120,7 +119,8 @@ pub struct EditBox {
|
||||
text_shaper: TextShaperPtr,
|
||||
key_repeat: SyncMutex<PressedKeysSmoothRepeat>,
|
||||
|
||||
render_info: SyncMutex<TextRenderInfo>,
|
||||
render_info: SyncMutex<Option<TextRenderInfo>>,
|
||||
glyphs: SyncMutex<Vec<Glyph>>,
|
||||
dc_key: u64,
|
||||
|
||||
is_active: PropertyBool,
|
||||
@@ -164,20 +164,11 @@ impl EditBox {
|
||||
let debug = PropertyBool::wrap(node, "debug", 0).unwrap();
|
||||
drop(scene_graph);
|
||||
|
||||
let render_info = Self::regen_mesh(
|
||||
&render_api,
|
||||
&text_shaper,
|
||||
text.get(),
|
||||
font_size.get(),
|
||||
text_color.get(),
|
||||
baseline.get(),
|
||||
debug.get(),
|
||||
)
|
||||
.await;
|
||||
|
||||
// testing
|
||||
window::show_keyboard(true);
|
||||
|
||||
let glyphs = text_shaper.shape(text.get(), font_size.get()).await;
|
||||
|
||||
let self_ = Arc::new_cyclic(|me: &Weak<Self>| {
|
||||
// Start a task monitoring for key down events
|
||||
let ev_sub = event_pub.subscribe_char();
|
||||
@@ -230,7 +221,8 @@ impl EditBox {
|
||||
text_shaper,
|
||||
key_repeat: SyncMutex::new(PressedKeysSmoothRepeat::new(400, 50)),
|
||||
|
||||
render_info: SyncMutex::new(render_info),
|
||||
render_info: SyncMutex::new(None),
|
||||
glyphs: SyncMutex::new(glyphs),
|
||||
dc_key: OsRng.gen(),
|
||||
|
||||
is_active,
|
||||
@@ -254,18 +246,16 @@ impl EditBox {
|
||||
|
||||
/// Called whenever the text or any text property changes.
|
||||
/// Not related to cursor, text highlighting or bounding (clip) rects.
|
||||
async fn regen_mesh(
|
||||
render_api: &RenderApi,
|
||||
text_shaper: &TextShaper,
|
||||
text: String,
|
||||
font_size: f32,
|
||||
text_color: Color,
|
||||
baseline: f32,
|
||||
debug: bool,
|
||||
) -> TextRenderInfo {
|
||||
async fn regen_mesh(&self, clip: &Rectangle) -> TextRenderInfo {
|
||||
let text = self.text.get();
|
||||
let font_size = self.font_size.get();
|
||||
let text_color = self.text_color.get();
|
||||
let baseline = self.baseline.get();
|
||||
let debug = self.debug.get();
|
||||
debug!(target: "ui::editbox", "Rendering text '{}'", text);
|
||||
let glyphs = text_shaper.shape(text, font_size).await;
|
||||
let atlas = text2::make_texture_atlas(render_api, font_size, &glyphs).await.unwrap();
|
||||
|
||||
let glyphs = self.glyphs.lock().unwrap().clone();
|
||||
let atlas = text2::make_texture_atlas(&self.render_api, font_size, &glyphs).await.unwrap();
|
||||
|
||||
let mut mesh = MeshBuilder::new();
|
||||
let mut glyph_pos_iter = GlyphPositionIter::new(font_size, &glyphs, baseline);
|
||||
@@ -280,9 +270,9 @@ impl EditBox {
|
||||
mesh.draw_box(&glyph_rect, color, &uv_rect);
|
||||
}
|
||||
|
||||
let mesh = mesh.alloc(&render_api).await.unwrap();
|
||||
let mesh = mesh.alloc(&self.render_api).await.unwrap();
|
||||
|
||||
TextRenderInfo { glyphs, mesh, texture_id: atlas.texture_id }
|
||||
TextRenderInfo { mesh, texture_id: atlas.texture_id }
|
||||
}
|
||||
|
||||
async fn do_key_action(&self, key: char, mods: &KeyMods) {
|
||||
@@ -351,7 +341,7 @@ impl EditBox {
|
||||
|
||||
let cursor_pos = self.cursor_pos.get();
|
||||
|
||||
let glyphs = self.render_info.lock().unwrap().glyphs.clone();
|
||||
let glyphs = self.glyphs.lock().unwrap().clone();
|
||||
|
||||
// We rebuild the string but insert our substr at cursor_pos.
|
||||
// The substr is inserted before cursor_pos, and appending to the end
|
||||
@@ -407,17 +397,11 @@ impl EditBox {
|
||||
async fn redraw(&self) {
|
||||
let old = self.render_info.lock().unwrap().clone();
|
||||
|
||||
let render_info = Self::regen_mesh(
|
||||
&self.render_api,
|
||||
&self.text_shaper,
|
||||
self.text.get(),
|
||||
self.font_size.get(),
|
||||
self.text_color.get(),
|
||||
self.baseline.get(),
|
||||
self.debug.get(),
|
||||
)
|
||||
.await;
|
||||
*self.render_info.lock().unwrap() = render_info;
|
||||
let glyphs = self.text_shaper.shape(self.text.get(), self.font_size.get()).await;
|
||||
*self.glyphs.lock().unwrap() = glyphs;
|
||||
|
||||
// draw will recalc this when it's None
|
||||
*self.render_info.lock().unwrap() = None;
|
||||
|
||||
let sg = self.sg.lock().await;
|
||||
let node = sg.get_node(self.node_id).unwrap();
|
||||
@@ -434,9 +418,11 @@ impl EditBox {
|
||||
debug!(target: "ui::editbox", "replace draw calls done");
|
||||
|
||||
// We're finished with these so clean up.
|
||||
self.render_api.delete_buffer(old.mesh.vertex_buffer);
|
||||
self.render_api.delete_buffer(old.mesh.index_buffer);
|
||||
self.render_api.delete_texture(old.texture_id);
|
||||
if let Some(old) = old {
|
||||
self.render_api.delete_buffer(old.mesh.vertex_buffer);
|
||||
self.render_api.delete_buffer(old.mesh.index_buffer);
|
||||
self.render_api.delete_texture(old.texture_id);
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn draw(&self, sg: &SceneGraph, parent_rect: &Rectangle) -> Option<DrawUpdate> {
|
||||
@@ -444,15 +430,6 @@ impl EditBox {
|
||||
// Only used for debug messages
|
||||
let node = sg.get_node(self.node_id).unwrap();
|
||||
|
||||
let render_info = self.render_info.lock().unwrap().clone();
|
||||
|
||||
let mesh = DrawMesh {
|
||||
vertex_buffer: render_info.mesh.vertex_buffer,
|
||||
index_buffer: render_info.mesh.index_buffer,
|
||||
texture: Some(render_info.texture_id),
|
||||
num_elements: render_info.mesh.num_elements,
|
||||
};
|
||||
|
||||
if let Err(err) = eval_rect(self.rect.clone(), parent_rect) {
|
||||
panic!("Node {:?} bad rect property: {}", node, err);
|
||||
}
|
||||
@@ -461,6 +438,23 @@ impl EditBox {
|
||||
panic!("Node {:?} bad rect property", node);
|
||||
};
|
||||
|
||||
let render_info = self.render_info.lock().unwrap().clone();
|
||||
let render_info = match render_info {
|
||||
Some(render_info) => render_info,
|
||||
None => {
|
||||
let render_info = self.regen_mesh(&rect).await;
|
||||
*self.render_info.lock().unwrap() = Some(render_info.clone());
|
||||
render_info
|
||||
}
|
||||
};
|
||||
|
||||
let mesh = DrawMesh {
|
||||
vertex_buffer: render_info.mesh.vertex_buffer,
|
||||
index_buffer: render_info.mesh.index_buffer,
|
||||
texture: Some(render_info.texture_id),
|
||||
num_elements: render_info.mesh.num_elements,
|
||||
};
|
||||
|
||||
rect.x += parent_rect.x;
|
||||
rect.y += parent_rect.x;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user