mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-09 14:48:08 -05:00
wallet/chatedit: resize with wrapped text
This commit is contained in:
@@ -268,6 +268,9 @@ pub fn create_chatedit(name: &str) -> SceneNode {
|
|||||||
let prop = Property::new("baseline", PropertyType::Float32, PropertySubType::Pixel);
|
let prop = Property::new("baseline", PropertyType::Float32, PropertySubType::Pixel);
|
||||||
node.add_property(prop).unwrap();
|
node.add_property(prop).unwrap();
|
||||||
|
|
||||||
|
let prop = Property::new("descent", PropertyType::Float32, PropertySubType::Pixel);
|
||||||
|
node.add_property(prop).unwrap();
|
||||||
|
|
||||||
let mut prop = Property::new("scroll", PropertyType::Float32, PropertySubType::Pixel);
|
let mut prop = Property::new("scroll", PropertyType::Float32, PropertySubType::Pixel);
|
||||||
prop.set_range_f32(0., f32::MAX);
|
prop.set_range_f32(0., f32::MAX);
|
||||||
node.add_property(prop).unwrap();
|
node.add_property(prop).unwrap();
|
||||||
|
|||||||
@@ -47,12 +47,13 @@ const LIGHTMODE: bool = false;
|
|||||||
|
|
||||||
mod android_ui_consts {
|
mod android_ui_consts {
|
||||||
pub const EDITCHAT_HEIGHT: f32 = 163.;
|
pub const EDITCHAT_HEIGHT: f32 = 163.;
|
||||||
pub const EDITCHAT_BOTTOM_PAD: f32 = 70.;
|
pub const EDITCHAT_BOTTOM_PAD: f32 = 50.;
|
||||||
pub const EDITCHAT_CURSOR_ASCENT: f32 = 50.;
|
pub const EDITCHAT_CURSOR_ASCENT: f32 = 50.;
|
||||||
pub const EDITCHAT_CURSOR_DESCENT: f32 = 20.;
|
pub const EDITCHAT_CURSOR_DESCENT: f32 = 20.;
|
||||||
pub const EDITCHAT_SELECT_ASCENT: f32 = 40.;
|
pub const EDITCHAT_SELECT_ASCENT: f32 = 40.;
|
||||||
pub const EDITCHAT_SELECT_DESCENT: f32 = 8.;
|
pub const EDITCHAT_SELECT_DESCENT: f32 = 8.;
|
||||||
pub const TEXTBAR_BASELINE: f32 = 93.;
|
pub const TEXTBAR_BASELINE: f32 = 93.;
|
||||||
|
pub const TEXT_DESCENT: f32 = 20.;
|
||||||
pub const EDITCHAT_LHS_PAD: f32 = 30.;
|
pub const EDITCHAT_LHS_PAD: f32 = 30.;
|
||||||
pub const SENDLABEL_WIDTH: f32 = 200.;
|
pub const SENDLABEL_WIDTH: f32 = 200.;
|
||||||
pub const SENDLABEL_LHS_PAD: f32 = 40.;
|
pub const SENDLABEL_LHS_PAD: f32 = 40.;
|
||||||
@@ -89,12 +90,13 @@ mod ui_consts {
|
|||||||
pub const KING_PATH: &str = "assets/king.png";
|
pub const KING_PATH: &str = "assets/king.png";
|
||||||
pub const BG_PATH: &str = "assets/bg.png";
|
pub const BG_PATH: &str = "assets/bg.png";
|
||||||
pub const EDITCHAT_HEIGHT: f32 = 50.;
|
pub const EDITCHAT_HEIGHT: f32 = 50.;
|
||||||
pub const EDITCHAT_BOTTOM_PAD: f32 = 16.;
|
pub const EDITCHAT_BOTTOM_PAD: f32 = 6.;
|
||||||
pub const EDITCHAT_CURSOR_ASCENT: f32 = 25.;
|
pub const EDITCHAT_CURSOR_ASCENT: f32 = 25.;
|
||||||
pub const EDITCHAT_CURSOR_DESCENT: f32 = 8.;
|
pub const EDITCHAT_CURSOR_DESCENT: f32 = 8.;
|
||||||
pub const EDITCHAT_SELECT_ASCENT: f32 = 30.;
|
pub const EDITCHAT_SELECT_ASCENT: f32 = 30.;
|
||||||
pub const EDITCHAT_SELECT_DESCENT: f32 = 10.;
|
pub const EDITCHAT_SELECT_DESCENT: f32 = 10.;
|
||||||
pub const TEXTBAR_BASELINE: f32 = 34.;
|
pub const TEXTBAR_BASELINE: f32 = 34.;
|
||||||
|
pub const TEXT_DESCENT: f32 = 10.;
|
||||||
pub const EDITCHAT_LHS_PAD: f32 = 20.;
|
pub const EDITCHAT_LHS_PAD: f32 = 20.;
|
||||||
pub const SENDLABEL_WIDTH: f32 = 120.;
|
pub const SENDLABEL_WIDTH: f32 = 120.;
|
||||||
pub const SENDLABEL_LHS_PAD: f32 = 30.;
|
pub const SENDLABEL_LHS_PAD: f32 = 30.;
|
||||||
@@ -730,12 +732,15 @@ pub(super) async fn make(app: &App, window: SceneNodePtr) {
|
|||||||
let node = create_vector_art("editbox_bg");
|
let node = create_vector_art("editbox_bg");
|
||||||
let prop = node.get_property("rect").unwrap();
|
let prop = node.get_property("rect").unwrap();
|
||||||
prop.set_f32(Role::App, 0, 0.).unwrap();
|
prop.set_f32(Role::App, 0, 0.).unwrap();
|
||||||
let code = cc.compile("h - EDITCHAT_HEIGHT").unwrap();
|
let code = cc.compile("h - editz_h").unwrap();
|
||||||
prop.set_expr(Role::App, 1, code).unwrap();
|
prop.set_expr(Role::App, 1, code).unwrap();
|
||||||
prop.set_expr(Role::App, 2, expr::load_var("w")).unwrap();
|
prop.set_expr(Role::App, 2, expr::load_var("w")).unwrap();
|
||||||
prop.set_f32(Role::App, 3, EDITCHAT_HEIGHT).unwrap();
|
let code = cc.compile("editz_h").unwrap();
|
||||||
|
prop.set_expr(Role::App, 3, code).unwrap();
|
||||||
node.set_property_u32(Role::App, "z_index", 2).unwrap();
|
node.set_property_u32(Role::App, "z_index", 2).unwrap();
|
||||||
|
|
||||||
|
let editbox_bg_rect_prop = prop.clone();
|
||||||
|
|
||||||
let mut shape = VectorShape::new();
|
let mut shape = VectorShape::new();
|
||||||
shape.add_filled_box(
|
shape.add_filled_box(
|
||||||
expr::const_f32(0.),
|
expr::const_f32(0.),
|
||||||
@@ -818,8 +823,10 @@ pub(super) async fn make(app: &App, window: SceneNodePtr) {
|
|||||||
prop.set_f32(Role::App, 3, EDITCHAT_HEIGHT).unwrap();
|
prop.set_f32(Role::App, 3, EDITCHAT_HEIGHT).unwrap();
|
||||||
|
|
||||||
chatview_rect_prop.add_depend(&prop, 3, "editz_h");
|
chatview_rect_prop.add_depend(&prop, 3, "editz_h");
|
||||||
|
editbox_bg_rect_prop.add_depend(&prop, 3, "editz_h");
|
||||||
|
|
||||||
node.set_property_f32(Role::App, "baseline", TEXTBAR_BASELINE).unwrap();
|
node.set_property_f32(Role::App, "baseline", TEXTBAR_BASELINE).unwrap();
|
||||||
|
node.set_property_f32(Role::App, "descent", TEXT_DESCENT).unwrap();
|
||||||
node.set_property_f32(Role::App, "font_size", FONTSIZE).unwrap();
|
node.set_property_f32(Role::App, "font_size", FONTSIZE).unwrap();
|
||||||
//node.set_property_str(Role::App, "text", "hello king!😁🍆jelly 🍆1234").unwrap();
|
//node.set_property_str(Role::App, "text", "hello king!😁🍆jelly 🍆1234").unwrap();
|
||||||
let prop = node.get_property("text_color").unwrap();
|
let prop = node.get_property("text_color").unwrap();
|
||||||
@@ -912,72 +919,4 @@ pub(super) async fn make(app: &App, window: SceneNodePtr) {
|
|||||||
|
|
||||||
let node = node.setup(|me| Button::new(me, app.ex.clone())).await;
|
let node = node.setup(|me| Button::new(me, app.ex.clone())).await;
|
||||||
layer_node.clone().link(node);
|
layer_node.clone().link(node);
|
||||||
|
|
||||||
// Create a popup layer to show upgrade msg
|
|
||||||
let node = create_layer("upgrade_popup");
|
|
||||||
let prop = node.get_property("rect").unwrap();
|
|
||||||
prop.set_f32(Role::App, 0, 0.).unwrap();
|
|
||||||
prop.set_f32(Role::App, 1, 0.).unwrap();
|
|
||||||
prop.set_expr(Role::App, 2, expr::load_var("w")).unwrap();
|
|
||||||
let code = cc.compile("h / 2").unwrap();
|
|
||||||
prop.set_expr(Role::App, 3, code).unwrap();
|
|
||||||
node.set_property_bool(Role::App, "is_visible", false).unwrap();
|
|
||||||
node.set_property_u32(Role::App, "z_index", 10).unwrap();
|
|
||||||
let popup_layer_node =
|
|
||||||
node.setup(|me| Layer::new(me, app.render_api.clone(), app.ex.clone())).await;
|
|
||||||
layer_node.clone().link(popup_layer_node.clone());
|
|
||||||
|
|
||||||
// Background for popup
|
|
||||||
let node = create_vector_art("upgradebg");
|
|
||||||
let prop = node.get_property("rect").unwrap();
|
|
||||||
prop.set_f32(Role::App, 0, 0.).unwrap();
|
|
||||||
prop.set_f32(Role::App, 1, 0.).unwrap();
|
|
||||||
prop.set_expr(Role::App, 2, expr::load_var("w")).unwrap();
|
|
||||||
prop.set_expr(Role::App, 3, expr::load_var("h")).unwrap();
|
|
||||||
node.set_property_u32(Role::App, "z_index", 0).unwrap();
|
|
||||||
|
|
||||||
// Setup the pimpl
|
|
||||||
let verts = vec![
|
|
||||||
ShapeVertex::from_xy(0., 0., [1., 0., 0., 1.]),
|
|
||||||
ShapeVertex::new(expr::load_var("w"), expr::const_f32(0.), [1., 0., 1., 1.]),
|
|
||||||
ShapeVertex::new(expr::const_f32(0.), expr::load_var("h"), [0., 0., 1., 1.]),
|
|
||||||
ShapeVertex::new(expr::load_var("w"), expr::load_var("h"), [1., 1., 0., 1.]),
|
|
||||||
];
|
|
||||||
let indices = vec![0, 2, 1, 1, 2, 3];
|
|
||||||
let shape = VectorShape { verts, indices };
|
|
||||||
let node =
|
|
||||||
node.setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone())).await;
|
|
||||||
popup_layer_node.clone().link(node);
|
|
||||||
|
|
||||||
// Create some text
|
|
||||||
let node = create_text("send_label");
|
|
||||||
let prop = node.get_property("rect").unwrap();
|
|
||||||
prop.set_f32(Role::App, 0, 10.).unwrap();
|
|
||||||
prop.set_f32(Role::App, 1, 10.).unwrap();
|
|
||||||
prop.set_expr(Role::App, 2, expr::load_var("w")).unwrap();
|
|
||||||
prop.set_expr(Role::App, 3, expr::load_var("h")).unwrap();
|
|
||||||
node.set_property_f32(Role::App, "baseline", TEXTBAR_BASELINE).unwrap();
|
|
||||||
node.set_property_f32(Role::App, "font_size", 2. * FONTSIZE).unwrap();
|
|
||||||
node.set_property_str(Role::App, "text", "YO THERE'S A NEW VERSION!!! UPGRADE TIEM!!!")
|
|
||||||
.unwrap();
|
|
||||||
//node.set_property_str(Role::App, "text", "anon1").unwrap();
|
|
||||||
let prop = node.get_property("text_color").unwrap();
|
|
||||||
prop.set_f32(Role::App, 0, 0.).unwrap();
|
|
||||||
prop.set_f32(Role::App, 1, 1.).unwrap();
|
|
||||||
prop.set_f32(Role::App, 2, 0.94).unwrap();
|
|
||||||
prop.set_f32(Role::App, 3, 1.).unwrap();
|
|
||||||
node.set_property_u32(Role::App, "z_index", 1).unwrap();
|
|
||||||
|
|
||||||
let node = node
|
|
||||||
.setup(|me| {
|
|
||||||
Text::new(
|
|
||||||
me,
|
|
||||||
window_scale.clone(),
|
|
||||||
app.render_api.clone(),
|
|
||||||
app.text_shaper.clone(),
|
|
||||||
app.ex.clone(),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
popup_layer_node.clone().link(node);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,6 +147,7 @@ pub struct ChatEdit {
|
|||||||
max_height: PropertyFloat32,
|
max_height: PropertyFloat32,
|
||||||
rect: PropertyRect,
|
rect: PropertyRect,
|
||||||
baseline: PropertyFloat32,
|
baseline: PropertyFloat32,
|
||||||
|
descent: PropertyFloat32,
|
||||||
scroll: PropertyFloat32,
|
scroll: PropertyFloat32,
|
||||||
scroll_speed: PropertyFloat32,
|
scroll_speed: PropertyFloat32,
|
||||||
cursor_pos: PropertyUint32,
|
cursor_pos: PropertyUint32,
|
||||||
@@ -201,6 +202,7 @@ impl ChatEdit {
|
|||||||
let max_height = PropertyFloat32::wrap(node_ref, Role::Internal, "max_height", 0).unwrap();
|
let max_height = PropertyFloat32::wrap(node_ref, Role::Internal, "max_height", 0).unwrap();
|
||||||
let rect = PropertyRect::wrap(node_ref, Role::Internal, "rect").unwrap();
|
let rect = PropertyRect::wrap(node_ref, Role::Internal, "rect").unwrap();
|
||||||
let baseline = PropertyFloat32::wrap(node_ref, Role::Internal, "baseline", 0).unwrap();
|
let baseline = PropertyFloat32::wrap(node_ref, Role::Internal, "baseline", 0).unwrap();
|
||||||
|
let descent = PropertyFloat32::wrap(node_ref, Role::Internal, "descent", 0).unwrap();
|
||||||
let scroll = PropertyFloat32::wrap(node_ref, Role::Internal, "scroll", 0).unwrap();
|
let scroll = PropertyFloat32::wrap(node_ref, Role::Internal, "scroll", 0).unwrap();
|
||||||
let scroll_speed =
|
let scroll_speed =
|
||||||
PropertyFloat32::wrap(node_ref, Role::Internal, "scroll_speed", 0).unwrap();
|
PropertyFloat32::wrap(node_ref, Role::Internal, "scroll_speed", 0).unwrap();
|
||||||
@@ -252,6 +254,7 @@ impl ChatEdit {
|
|||||||
max_height,
|
max_height,
|
||||||
rect,
|
rect,
|
||||||
baseline: baseline.clone(),
|
baseline: baseline.clone(),
|
||||||
|
descent,
|
||||||
scroll: scroll.clone(),
|
scroll: scroll.clone(),
|
||||||
scroll_speed,
|
scroll_speed,
|
||||||
cursor_pos,
|
cursor_pos,
|
||||||
@@ -326,8 +329,7 @@ impl ChatEdit {
|
|||||||
|
|
||||||
let total_height = wrapped_lines_len as f32 * baseline;
|
let total_height = wrapped_lines_len as f32 * baseline;
|
||||||
//let height = std::cmp::min(total_height, self.max_height.get());
|
//let height = std::cmp::min(total_height, self.max_height.get());
|
||||||
let height = total_height;
|
let height = total_height + self.descent.get();
|
||||||
debug!("height = {height}");
|
|
||||||
|
|
||||||
self.rect.prop().set_f32(Role::Internal, 3, height);
|
self.rect.prop().set_f32(Role::Internal, 3, height);
|
||||||
|
|
||||||
@@ -341,7 +343,6 @@ impl ChatEdit {
|
|||||||
("rect_h".to_string(), height),
|
("rect_h".to_string(), height),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
debug!("rect = {:?}", self.rect.get());
|
|
||||||
|
|
||||||
let mut clip = self.rect.get();
|
let mut clip = self.rect.get();
|
||||||
clip.x = 0.;
|
clip.x = 0.;
|
||||||
@@ -416,43 +417,60 @@ impl ChatEdit {
|
|||||||
mesh.alloc(&self.render_api).draw_untextured()
|
mesh.alloc(&self.render_api).draw_untextured()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cursor_px_offset(&self) -> f32 {
|
fn get_cursor_pos(&self) -> Point {
|
||||||
assert!(self.is_focused.get());
|
assert!(self.is_focused.get());
|
||||||
|
|
||||||
let (cursor_pos, glyphs) = {
|
|
||||||
let editable = self.editable.lock().unwrap();
|
|
||||||
let rendered = editable.render();
|
|
||||||
let cursor_pos = editable.get_cursor_pos(&rendered);
|
|
||||||
(cursor_pos, rendered.glyphs)
|
|
||||||
};
|
|
||||||
|
|
||||||
let font_size = self.font_size.get();
|
let font_size = self.font_size.get();
|
||||||
let window_scale = self.window_scale.get();
|
let window_scale = self.window_scale.get();
|
||||||
let baseline = self.baseline.get();
|
let baseline = self.baseline.get();
|
||||||
let scroll = self.scroll.get();
|
|
||||||
// Add composer glyphs too
|
let width = self.rect.prop().get_f32(2).unwrap();
|
||||||
let glyph_pos_iter = GlyphPositionIter::new(font_size, window_scale, &glyphs, baseline);
|
|
||||||
|
let (cursor_pos, wrap_glyphs) = {
|
||||||
|
let editable = self.editable.lock().unwrap();
|
||||||
|
let rendered = editable.render();
|
||||||
|
let cursor_pos = editable.get_cursor_pos(&rendered);
|
||||||
|
let glyphs = text::wrap(width, font_size, window_scale, &rendered.glyphs);
|
||||||
|
(cursor_pos, glyphs)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Convert cursor glyph pos to a coord (x, y)
|
||||||
|
let mut glyph_idx = 0;
|
||||||
// Used for drawing the cursor when it's at the end of the line.
|
// Used for drawing the cursor when it's at the end of the line.
|
||||||
let mut rhs = 0.;
|
let mut rhs = 0.;
|
||||||
|
let mut y_pos = 0.;
|
||||||
|
|
||||||
if cursor_pos == 0 {
|
if cursor_pos == 0 {
|
||||||
return 0.;
|
return Point::zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (glyph_idx, (mut glyph_rect, glyph)) in glyph_pos_iter.zip(glyphs.iter()).enumerate() {
|
for (line_idx, glyphs) in wrap_glyphs.iter().enumerate() {
|
||||||
glyph_rect.x -= scroll;
|
debug!("glyph_idx = {glyph_idx}, y_pos = {y_pos}, rhs = {rhs}");
|
||||||
|
let glyph_pos_iter = GlyphPositionIter::new(font_size, window_scale, glyphs, baseline);
|
||||||
|
|
||||||
if cursor_pos == glyph_idx {
|
if line_idx > 0 {
|
||||||
return glyph_rect.x;
|
// +1 for the EOL whitespace
|
||||||
|
glyph_idx += 1;
|
||||||
|
y_pos += baseline;
|
||||||
}
|
}
|
||||||
|
|
||||||
rhs = glyph_rect.rhs();
|
for (mut glyph_rect, glyph) in glyph_pos_iter.zip(glyphs.iter()) {
|
||||||
|
if cursor_pos == glyph_idx {
|
||||||
|
let rhs = glyph_rect.rhs();
|
||||||
|
debug!("retvrn {rhs}, {y_pos}");
|
||||||
|
return Point::new(rhs, y_pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
rhs = glyph_rect.rhs();
|
||||||
|
|
||||||
|
glyph_idx += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert!(cursor_pos == glyphs.len());
|
if !wrap_glyphs.is_empty() {
|
||||||
|
rhs += eol_nudge(font_size, &wrap_glyphs.last().unwrap());
|
||||||
rhs += eol_nudge(font_size, &glyphs);
|
}
|
||||||
rhs
|
Point::new(rhs, y_pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mark_selected_glyphs(&self, glyphs: &Vec<Glyph>, selections: Vec<Selection>) -> Vec<bool> {
|
fn mark_selected_glyphs(&self, glyphs: &Vec<Glyph>, selections: Vec<Selection>) -> Vec<bool> {
|
||||||
@@ -1209,11 +1227,7 @@ impl ChatEdit {
|
|||||||
|
|
||||||
let rect_w = self.rect.get().w;
|
let rect_w = self.rect.get().w;
|
||||||
|
|
||||||
let mut cursor_pos = Point::zero();
|
let cursor_pos = self.get_cursor_pos();
|
||||||
cursor_pos.x += self.cursor_px_offset();
|
|
||||||
if cursor_pos.x > rect_w {
|
|
||||||
return vec![]
|
|
||||||
}
|
|
||||||
cursor_instrs.push(GfxDrawInstruction::Move(cursor_pos));
|
cursor_instrs.push(GfxDrawInstruction::Move(cursor_pos));
|
||||||
|
|
||||||
let cursor_mesh = {
|
let cursor_mesh = {
|
||||||
@@ -1439,10 +1453,23 @@ impl UIObject for ChatEdit {
|
|||||||
let window_scale = self.window_scale.get();
|
let window_scale = self.window_scale.get();
|
||||||
let baseline = self.baseline.get();
|
let baseline = self.baseline.get();
|
||||||
|
|
||||||
|
// Convert y offset within rect to an x off based off line wrapping
|
||||||
|
let y_off = mouse_pos.y - rect.y;
|
||||||
|
let mut x_off = 0.;
|
||||||
|
|
||||||
|
let width = self.rect.prop().get_f32(2).unwrap();
|
||||||
|
let rendered = self.editable.lock().unwrap().render();
|
||||||
|
let wrapped_glyphs = text::wrap(width, font_size, window_scale, &rendered.glyphs);
|
||||||
|
for glyphs in wrapped_glyphs {
|
||||||
|
let glyph_pos_iter = GlyphPositionIter::new(font_size, window_scale, &glyphs, baseline);
|
||||||
|
let last_rect = glyph_pos_iter.last().unwrap();
|
||||||
|
x_off += last_rect.rhs();
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut editable = self.editable.lock().unwrap();
|
let mut editable = self.editable.lock().unwrap();
|
||||||
let rendered = editable.render();
|
let rendered = editable.render();
|
||||||
let x = mouse_pos.x - rect.x + self.scroll.get();
|
let x = x_off + mouse_pos.x - rect.x + self.scroll.get();
|
||||||
|
|
||||||
let cpos = rendered.x_to_pos(x, font_size, window_scale, baseline);
|
let cpos = rendered.x_to_pos(x, font_size, window_scale, baseline);
|
||||||
let cidx = rendered.pos_to_idx(cpos);
|
let cidx = rendered.pos_to_idx(cpos);
|
||||||
|
|||||||
@@ -106,7 +106,6 @@ impl VectorArt {
|
|||||||
|
|
||||||
//debug!(target: "ui::vector_art", "=> {verts:#?}");
|
//debug!(target: "ui::vector_art", "=> {verts:#?}");
|
||||||
let vertex_buffer = self.render_api.new_vertex_buffer(verts);
|
let vertex_buffer = self.render_api.new_vertex_buffer(verts);
|
||||||
// You are one lazy motherfucker
|
|
||||||
let index_buffer = self.render_api.new_index_buffer(self.shape.indices.clone());
|
let index_buffer = self.render_api.new_index_buffer(self.shape.indices.clone());
|
||||||
let mesh = GfxDrawMesh {
|
let mesh = GfxDrawMesh {
|
||||||
vertex_buffer,
|
vertex_buffer,
|
||||||
|
|||||||
Reference in New Issue
Block a user