mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 15:21:12 +00:00
highlight all text in editor
This commit is contained in:
parent
b5dcde267a
commit
d89bf1c0af
4 changed files with 108 additions and 74 deletions
|
@ -87,21 +87,8 @@ pub struct RectBuffers {
|
||||||
pub fn create_rect_buffers(
|
pub fn create_rect_buffers(
|
||||||
gpu_device: &wgpu::Device,
|
gpu_device: &wgpu::Device,
|
||||||
encoder: &mut wgpu::CommandEncoder,
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
|
rects: &[Rect]
|
||||||
) -> RectBuffers {
|
) -> RectBuffers {
|
||||||
// Test Rectangles
|
|
||||||
let test_rect_1 = Rect {
|
|
||||||
top_left_coords: (0.0, 0.0).into(),
|
|
||||||
width: 400.0,
|
|
||||||
height: 300.0,
|
|
||||||
color: [1.0, 0.0, 0.0],
|
|
||||||
};
|
|
||||||
let test_rect_2 = Rect {
|
|
||||||
top_left_coords: (400.0, 300.0).into(),
|
|
||||||
width: 400.0,
|
|
||||||
height: 300.0,
|
|
||||||
color: [0.0, 0.0, 1.0],
|
|
||||||
};
|
|
||||||
|
|
||||||
let vertex_buffer = gpu_device.create_buffer(&wgpu::BufferDescriptor {
|
let vertex_buffer = gpu_device.create_buffer(&wgpu::BufferDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
size: Vertex::SIZE * 4 * 3,
|
size: Vertex::SIZE * 4 * 3,
|
||||||
|
@ -119,10 +106,14 @@ pub fn create_rect_buffers(
|
||||||
});
|
});
|
||||||
|
|
||||||
let num_rects = {
|
let num_rects = {
|
||||||
let (stg_vertex, stg_index, num_indices) = QuadBufferBuilder::new()
|
let mut quad_buffer_builder = QuadBufferBuilder::new();
|
||||||
.push_rect(&test_rect_1)
|
for rect in rects {
|
||||||
.push_rect(&test_rect_2)
|
quad_buffer_builder = quad_buffer_builder.push_rect(&rect);
|
||||||
.build(&gpu_device);
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let (stg_vertex, stg_index, num_indices) =
|
||||||
|
quad_buffer_builder.build(&gpu_device);
|
||||||
|
|
||||||
stg_vertex.copy_to_buffer(encoder, &vertex_buffer);
|
stg_vertex.copy_to_buffer(encoder, &vertex_buffer);
|
||||||
stg_index.copy_to_buffer(encoder, &index_buffer);
|
stg_index.copy_to_buffer(encoder, &index_buffer);
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
use crate::buffer::create_rect_buffers;
|
use crate::buffer::create_rect_buffers;
|
||||||
use crate::text::{build_glyph_brush, Text};
|
use crate::text::{build_glyph_brush, Text};
|
||||||
use crate::vertex::Vertex;
|
use crate::vertex::Vertex;
|
||||||
|
use crate::rect::{convert_rect};
|
||||||
use ortho::{init_ortho, update_ortho_buffer, OrthoResources};
|
use ortho::{init_ortho, update_ortho_buffer, OrthoResources};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
@ -18,6 +19,7 @@ use std::path::Path;
|
||||||
use winit::event;
|
use winit::event;
|
||||||
use winit::event::{Event, ModifiersState};
|
use winit::event::{Event, ModifiersState};
|
||||||
use winit::event_loop::ControlFlow;
|
use winit::event_loop::ControlFlow;
|
||||||
|
use wgpu_glyph::{ab_glyph};
|
||||||
|
|
||||||
pub mod ast;
|
pub mod ast;
|
||||||
mod buffer;
|
mod buffer;
|
||||||
|
@ -189,13 +191,25 @@ fn run_event_loop() -> Result<(), Box<dyn Error>> {
|
||||||
label: Some("Redraw"),
|
label: Some("Redraw"),
|
||||||
});
|
});
|
||||||
|
|
||||||
let rect_buffers = create_rect_buffers(&gpu_device, &mut encoder);
|
|
||||||
|
|
||||||
let frame = swap_chain
|
let frame = swap_chain
|
||||||
.get_current_frame()
|
.get_current_frame()
|
||||||
.expect("Failed to acquire next SwapChainFrame")
|
.expect("Failed to acquire next SwapChainFrame")
|
||||||
.output;
|
.output;
|
||||||
|
|
||||||
|
let text_bounds_rect_opt = queue_all_text(
|
||||||
|
&size,
|
||||||
|
&text_state,
|
||||||
|
&mut glyph_brush,
|
||||||
|
);
|
||||||
|
|
||||||
|
match text_bounds_rect_opt {
|
||||||
|
Some(ab_bounds_rect) => {
|
||||||
|
let rect_buffers = create_rect_buffers(
|
||||||
|
&gpu_device,
|
||||||
|
&mut encoder,
|
||||||
|
&[convert_rect(ab_bounds_rect, [255.0, 255.0, 255.0])],
|
||||||
|
);
|
||||||
|
|
||||||
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||||
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
|
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
|
||||||
attachment: &frame.view,
|
attachment: &frame.view,
|
||||||
|
@ -205,25 +219,29 @@ fn run_event_loop() -> Result<(), Box<dyn Error>> {
|
||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
if rect_buffers.num_rects > 0 {
|
|
||||||
render_pass.set_pipeline(&rect_pipeline);
|
render_pass.set_pipeline(&rect_pipeline);
|
||||||
render_pass.set_bind_group(0, &ortho.bind_group, &[]);
|
render_pass.set_bind_group(0, &ortho.bind_group, &[]);
|
||||||
render_pass.set_vertex_buffer(0, rect_buffers.vertex_buffer.slice(..));
|
render_pass.set_vertex_buffer(0, rect_buffers.vertex_buffer.slice(..));
|
||||||
render_pass.set_index_buffer(rect_buffers.index_buffer.slice(..));
|
render_pass.set_index_buffer(rect_buffers.index_buffer.slice(..));
|
||||||
render_pass.draw_indexed(0..rect_buffers.num_rects, 0, 0..1);
|
render_pass.draw_indexed(0..rect_buffers.num_rects, 0, 0..1);
|
||||||
}
|
|
||||||
|
|
||||||
drop(render_pass);
|
drop(render_pass);
|
||||||
|
},
|
||||||
|
None =>
|
||||||
|
(),
|
||||||
|
};
|
||||||
|
|
||||||
draw_all_text(
|
// draw all text
|
||||||
|
glyph_brush
|
||||||
|
.draw_queued(
|
||||||
&gpu_device,
|
&gpu_device,
|
||||||
&mut staging_belt,
|
&mut staging_belt,
|
||||||
&mut encoder,
|
&mut encoder,
|
||||||
&frame,
|
&frame.view,
|
||||||
&size,
|
size.width,
|
||||||
&text_state,
|
size.height,
|
||||||
&mut glyph_brush,
|
)
|
||||||
);
|
.expect("Draw queued");
|
||||||
|
|
||||||
staging_belt.finish();
|
staging_belt.finish();
|
||||||
cmd_queue.submit(Some(encoder.finish()));
|
cmd_queue.submit(Some(encoder.finish()));
|
||||||
|
@ -308,20 +326,16 @@ fn create_render_pipeline(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_all_text(
|
fn queue_all_text(
|
||||||
gpu_device: &wgpu::Device,
|
|
||||||
staging_belt: &mut wgpu::util::StagingBelt,
|
|
||||||
encoder: &mut wgpu::CommandEncoder,
|
|
||||||
frame: &wgpu::SwapChainTexture,
|
|
||||||
size: &winit::dpi::PhysicalSize<u32>,
|
size: &winit::dpi::PhysicalSize<u32>,
|
||||||
text_state: &str,
|
text_state: &str,
|
||||||
glyph_brush: &mut wgpu_glyph::GlyphBrush<()>,
|
glyph_brush: &mut wgpu_glyph::GlyphBrush<()>,
|
||||||
) {
|
) -> Option<ab_glyph::Rect> {
|
||||||
let bounds = (size.width as f32, size.height as f32).into();
|
let area_bounds = (size.width as f32, size.height as f32).into();
|
||||||
|
|
||||||
let main_label = Text {
|
let main_label = Text {
|
||||||
position: (30.0, 30.0).into(),
|
position: (30.0, 30.0).into(),
|
||||||
bounds,
|
area_bounds,
|
||||||
color: (0.4666, 0.2, 1.0, 1.0).into(),
|
color: (0.4666, 0.2, 1.0, 1.0).into(),
|
||||||
text: String::from("Enter some text:"),
|
text: String::from("Enter some text:"),
|
||||||
size: 40.0,
|
size: 40.0,
|
||||||
|
@ -330,8 +344,8 @@ fn draw_all_text(
|
||||||
|
|
||||||
let code_text = Text {
|
let code_text = Text {
|
||||||
position: (30.0, 90.0).into(),
|
position: (30.0, 90.0).into(),
|
||||||
bounds,
|
area_bounds,
|
||||||
color: (1.0, 1.0, 1.0, 1.0).into(),
|
color: (0.0, 0.05, 0.46, 1.0).into(),
|
||||||
text: String::from(format!("{}|", text_state).as_str()),
|
text: String::from(format!("{}|", text_state).as_str()),
|
||||||
size: 40.0,
|
size: 40.0,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -339,18 +353,9 @@ fn draw_all_text(
|
||||||
|
|
||||||
text::queue_text_draw(&main_label, glyph_brush);
|
text::queue_text_draw(&main_label, glyph_brush);
|
||||||
|
|
||||||
text::queue_text_draw(&code_text, glyph_brush);
|
let code_bounds_rect_opt = text::queue_text_draw(&code_text, glyph_brush);
|
||||||
|
|
||||||
glyph_brush
|
code_bounds_rect_opt
|
||||||
.draw_queued(
|
|
||||||
gpu_device,
|
|
||||||
staging_belt,
|
|
||||||
encoder,
|
|
||||||
&frame.view,
|
|
||||||
size.width,
|
|
||||||
size.height,
|
|
||||||
)
|
|
||||||
.expect("Draw queued");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_text_state(text_state: &mut String, received_char: &char) {
|
fn update_text_state(text_state: &mut String, received_char: &char) {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use cgmath::Vector2;
|
use cgmath::Vector2;
|
||||||
|
use wgpu_glyph::{ab_glyph};
|
||||||
|
|
||||||
pub struct Rect {
|
pub struct Rect {
|
||||||
pub top_left_coords: Vector2<f32>,
|
pub top_left_coords: Vector2<f32>,
|
||||||
|
@ -6,3 +7,12 @@ pub struct Rect {
|
||||||
pub height: f32,
|
pub height: f32,
|
||||||
pub color: [f32; 3],
|
pub color: [f32; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn convert_rect(glyph_rect: ab_glyph::Rect, color: [f32; 3]) -> Rect {
|
||||||
|
Rect {
|
||||||
|
top_left_coords: [glyph_rect.min.x, glyph_rect.min.y].into(),
|
||||||
|
width: glyph_rect.width(),
|
||||||
|
height: glyph_rect.height(),
|
||||||
|
color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
|
|
||||||
use ab_glyph::{FontArc, InvalidFont};
|
use ab_glyph::{FontArc, InvalidFont};
|
||||||
use cgmath::{Vector2, Vector4};
|
use cgmath::{Vector2, Vector4};
|
||||||
use wgpu_glyph::{ab_glyph, GlyphBrush, GlyphBrushBuilder, Section};
|
use wgpu_glyph::{ab_glyph, GlyphBrush, GlyphBrushBuilder, GlyphCruncher, Section};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Text {
|
pub struct Text {
|
||||||
pub position: Vector2<f32>,
|
pub position: Vector2<f32>,
|
||||||
pub bounds: Vector2<f32>,
|
pub area_bounds: Vector2<f32>,
|
||||||
pub color: Vector4<f32>,
|
pub color: Vector4<f32>,
|
||||||
pub text: String,
|
pub text: String,
|
||||||
pub size: f32,
|
pub size: f32,
|
||||||
|
@ -20,7 +20,7 @@ impl Default for Text {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
position: (0.0, 0.0).into(),
|
position: (0.0, 0.0).into(),
|
||||||
bounds: (std::f32::INFINITY, std::f32::INFINITY).into(),
|
area_bounds: (std::f32::INFINITY, std::f32::INFINITY).into(),
|
||||||
color: (1.0, 1.0, 1.0, 1.0).into(),
|
color: (1.0, 1.0, 1.0, 1.0).into(),
|
||||||
text: String::new(),
|
text: String::new(),
|
||||||
size: 16.0,
|
size: 16.0,
|
||||||
|
@ -30,7 +30,7 @@ impl Default for Text {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn queue_text_draw(text: &Text, glyph_brush: &mut GlyphBrush<()>) {
|
pub fn queue_text_draw(text: &Text, glyph_brush: &mut GlyphBrush<()>) -> Option<ab_glyph::Rect>{
|
||||||
let layout = wgpu_glyph::Layout::default().h_align(if text.centered {
|
let layout = wgpu_glyph::Layout::default().h_align(if text.centered {
|
||||||
wgpu_glyph::HorizontalAlign::Center
|
wgpu_glyph::HorizontalAlign::Center
|
||||||
} else {
|
} else {
|
||||||
|
@ -39,17 +39,18 @@ pub fn queue_text_draw(text: &Text, glyph_brush: &mut GlyphBrush<()>) {
|
||||||
|
|
||||||
let section = Section {
|
let section = Section {
|
||||||
screen_position: text.position.into(),
|
screen_position: text.position.into(),
|
||||||
bounds: text.bounds.into(),
|
bounds: text.area_bounds.into(),
|
||||||
layout,
|
layout,
|
||||||
..Section::default()
|
..Section::default()
|
||||||
}
|
}.add_text(
|
||||||
.add_text(
|
|
||||||
wgpu_glyph::Text::new(&text.text)
|
wgpu_glyph::Text::new(&text.text)
|
||||||
.with_color(text.color)
|
.with_color(text.color)
|
||||||
.with_scale(text.size),
|
.with_scale(text.size),
|
||||||
);
|
);
|
||||||
|
|
||||||
glyph_brush.queue(section);
|
glyph_brush.queue(section.clone());
|
||||||
|
|
||||||
|
glyph_brush.glyph_bounds_custom_layout(section, &layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_glyph_brush(
|
pub fn build_glyph_brush(
|
||||||
|
@ -60,3 +61,30 @@ pub fn build_glyph_brush(
|
||||||
|
|
||||||
Ok(GlyphBrushBuilder::using_font(inconsolata).build(&gpu_device, render_format))
|
Ok(GlyphBrushBuilder::using_font(inconsolata).build(&gpu_device, render_format))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*fn my_draw_text(&mut self, ...) {
|
||||||
|
let layout = ...;
|
||||||
|
let section = ...;
|
||||||
|
|
||||||
|
// Avoid re-allocating new vec's every time by storing them internally
|
||||||
|
self.last_glyphs.clear();
|
||||||
|
self.last_bounds.clear();
|
||||||
|
|
||||||
|
// Get all the glyphs for the current section to calculate their bounds. Due to
|
||||||
|
// mutable borrow, this must be stored first.
|
||||||
|
self.last_glyphs
|
||||||
|
.extend(self.brush.glyphs_custom_layout(&s, &layout).cloned());
|
||||||
|
|
||||||
|
// Calculate the bounds of each glyph
|
||||||
|
self.last_bounds
|
||||||
|
.extend(self.last_glyphs.iter().map(|glyph| {
|
||||||
|
let bounds = &fonts[glyph.font_id.0].glyph_bounds(&glyph.glyph);
|
||||||
|
Rect::new(
|
||||||
|
Vec2::new(bounds.min.x, bounds.min.y),
|
||||||
|
Vec2::new(bounds.max.x, bounds.max.y),
|
||||||
|
)
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Queue the glyphs for drawing
|
||||||
|
self.brush.queue_custom_layout(s, &layout);
|
||||||
|
}*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue