mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
apply scizzor from conrod, replace [T; 4] with vek::Aabr<T> for ui rects
Former-commit-id: 4eaa8832ddda40882cc45c3a08c5de2fa5e68682
This commit is contained in:
parent
d82adb7e71
commit
b0009f9e14
@ -108,7 +108,6 @@ impl Chat {
|
||||
.set(self.ids.message_box_bg, ui_widgets);
|
||||
let (mut items, scrollbar) = List::flow_down(self.messages.len())
|
||||
.middle_of(self.ids.message_box_bg)
|
||||
// Why does scrollbar disappear when the list is the exact same height as its contents?
|
||||
.scrollbar_next_to()
|
||||
.scrollbar_thickness(20.0)
|
||||
.scrollbar_color(Color::Rgba(0.0, 0.0, 0.0, 1.0))
|
||||
|
@ -1,4 +1,3 @@
|
||||
// Library
|
||||
use gfx::{
|
||||
self,
|
||||
// Macros
|
||||
@ -8,8 +7,7 @@ use gfx::{
|
||||
gfx_pipeline,
|
||||
gfx_pipeline_inner,
|
||||
};
|
||||
|
||||
// Local
|
||||
use vek::*;
|
||||
use super::super::{
|
||||
Pipeline,
|
||||
TgtColorFmt,
|
||||
@ -68,8 +66,7 @@ impl Mode {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: don't use [f32; 4] for rectangle as the format (eg 2 points vs point + dims) is ambiguous
|
||||
pub fn push_quad_to_mesh(mesh: &mut Mesh<UiPipeline>, rect: [f32; 4], uv_rect: [f32; 4], color: [f32; 4], mode: Mode) {
|
||||
pub fn push_quad_to_mesh(mesh: &mut Mesh<UiPipeline>, rect: Aabr<f32>, uv_rect: Aabr<f32>, color: [f32; 4], mode: Mode) {
|
||||
let mode_val = mode.value();
|
||||
let v = |pos, uv| {
|
||||
Vertex {
|
||||
@ -79,8 +76,13 @@ pub fn push_quad_to_mesh(mesh: &mut Mesh<UiPipeline>, rect: [f32; 4], uv_rect: [
|
||||
mode: mode_val,
|
||||
}
|
||||
};
|
||||
let (l, t, r, b) = (rect[0], rect[1], rect[2], rect[3]);
|
||||
let (uv_l, uv_t, uv_r, uv_b) = (uv_rect[0], uv_rect[1], uv_rect[2], uv_rect[3]);
|
||||
let aabr_to_lbrt = |aabr: Aabr<f32>| (
|
||||
aabr.min.x, aabr.min.y,
|
||||
aabr.max.x, aabr.max.y,
|
||||
);
|
||||
|
||||
let (l, b, r, t) = aabr_to_lbrt(rect);
|
||||
let (uv_l, uv_b, uv_r, uv_t) = aabr_to_lbrt(uv_rect);
|
||||
mesh.push_quad(Quad::new(
|
||||
v([r, t], [uv_r, uv_t]),
|
||||
v([l, t], [uv_l, uv_t]),
|
||||
|
@ -1,12 +1,9 @@
|
||||
// Library
|
||||
use vek::*;
|
||||
use gfx::{
|
||||
self,
|
||||
traits::{Device, FactoryExt},
|
||||
};
|
||||
use image;
|
||||
|
||||
// Local
|
||||
use super::{
|
||||
consts::Consts,
|
||||
mesh::Mesh,
|
||||
@ -268,14 +265,15 @@ impl Renderer {
|
||||
&mut self,
|
||||
model: &Model<ui::UiPipeline>,
|
||||
tex: &Texture<ui::UiPipeline>,
|
||||
scissor: Aabr<u16>,
|
||||
) {
|
||||
let (width, height) = self.get_resolution().map(|e| e).into_tuple();
|
||||
let Aabr { min, max } = scissor;
|
||||
self.encoder.draw(
|
||||
&model.slice,
|
||||
&self.ui_pipeline.pso,
|
||||
&ui::pipe::Data {
|
||||
vbuf: model.vbuf.clone(),
|
||||
scissor: gfx::Rect { x: 0, y: 0, w: width, h: height },
|
||||
scissor: gfx::Rect { x: min.x, y: min.y, w: max.x - min.x, h: max.y - min.y },
|
||||
tex: (tex.srv.clone(), tex.sampler.clone()),
|
||||
tgt_color: self.tgt_color_view.clone(),
|
||||
tgt_depth: self.tgt_depth_view.clone(),
|
||||
|
@ -69,10 +69,31 @@ impl Cache {
|
||||
pub fn glyph_cache_mut_and_tex(&mut self) -> (&mut GlyphCache<'static>, &Texture<UiPipeline>) { (&mut self.glyph_cache, &self.glyph_cache_tex) }
|
||||
}
|
||||
|
||||
pub enum DrawCommand {
|
||||
Image(Model<UiPipeline>, ImgId),
|
||||
enum DrawKind {
|
||||
Image(ImgId),
|
||||
// Text and non-textured geometry
|
||||
Plain(Model<UiPipeline>),
|
||||
Plain,
|
||||
}
|
||||
enum DrawCommand {
|
||||
Draw {
|
||||
kind: DrawKind,
|
||||
model: Model<UiPipeline>,
|
||||
},
|
||||
Scissor(Aabr<u16>),
|
||||
}
|
||||
impl DrawCommand {
|
||||
fn image(model: Model<UiPipeline>, img_id: ImgId) -> DrawCommand {
|
||||
DrawCommand::Draw {
|
||||
kind: DrawKind::Image(img_id),
|
||||
model,
|
||||
}
|
||||
}
|
||||
fn plain(model: Model<UiPipeline>) -> DrawCommand {
|
||||
DrawCommand::Draw {
|
||||
kind: DrawKind::Plain,
|
||||
model,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// How to scale the ui
|
||||
@ -109,14 +130,18 @@ impl Scale {
|
||||
pub fn scaling_mode(&mut self, mode: ScaleMode) {
|
||||
self.mode = mode;
|
||||
}
|
||||
// Calculate factor to transform from logical coordinates to our scaled coordinates
|
||||
fn scale_factor(&self) -> f64 {
|
||||
// Calculate factor to transform between logical coordinates and our scaled coordinates
|
||||
fn scale_factor_logical(&self) -> f64 {
|
||||
match self.mode {
|
||||
ScaleMode::Absolute(scale) => scale / self.dpi_factor,
|
||||
ScaleMode::DpiFactor => 1.0,
|
||||
ScaleMode::RelativeToWindow(dims) => (self.window_dims.x / dims.x).min(self.window_dims.y / dims.y),
|
||||
}
|
||||
}
|
||||
// Calculate factor to transform between physical coordinates and our scaled coordinates
|
||||
fn scale_factor_physical(&self) -> f64 {
|
||||
self.scale_factor_logical() * self.dpi_factor
|
||||
}
|
||||
// Updates internal window size (and/or dpi_factor)
|
||||
fn window_resized(&mut self, new_dims: Vec2<f64>, renderer: &Renderer) {
|
||||
self.dpi_factor = renderer.get_resolution().x as f64 / new_dims.x;
|
||||
@ -124,11 +149,11 @@ impl Scale {
|
||||
}
|
||||
// Get scaled window size
|
||||
fn scaled_window_size(&self) -> Vec2<f64> {
|
||||
self.window_dims / self.scale_factor()
|
||||
self.window_dims / self.scale_factor_logical()
|
||||
}
|
||||
// Transform point from logical to scaled coordinates
|
||||
fn scale_point(&self, point: Vec2<f64>) -> Vec2<f64> {
|
||||
point / self.scale_factor()
|
||||
point / self.scale_factor_logical()
|
||||
}
|
||||
}
|
||||
|
||||
@ -225,23 +250,70 @@ impl Ui {
|
||||
|
||||
let mut current_img = None;
|
||||
|
||||
let window_scizzor = default_scissor(renderer);
|
||||
let mut current_scizzor = window_scizzor;
|
||||
|
||||
// Switches to the `Plain` state and completes the previous `Command` if not already in the
|
||||
// `Plain` state.
|
||||
macro_rules! switch_to_plain_state {
|
||||
() => {
|
||||
if let Some(image_id) = current_img.take() {
|
||||
self.draw_commands.push(DrawCommand::Image(renderer.create_model(&mesh).unwrap(), image_id));
|
||||
self.draw_commands.push(DrawCommand::image(renderer.create_model(&mesh).unwrap(), image_id));
|
||||
mesh.clear();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let p_scale_factor = self.scale.scale_factor_physical();
|
||||
|
||||
while let Some(prim) = primitives.next() {
|
||||
// TODO: Use scizzor
|
||||
let Primitive {kind, scizzor, id, rect} = prim;
|
||||
|
||||
// Check for a change in the scizzor
|
||||
let new_scizzor = {
|
||||
let (l, b, w, h) = scizzor.l_b_w_h();
|
||||
// Calculate minimum x and y coordinates while
|
||||
// - flipping y axis (from +up to +down)
|
||||
// - moving origin to top-left corner (from middle)
|
||||
let min_x = ui.win_w / 2.0 + l;
|
||||
let min_y = ui.win_h / 2.0 - b - h;
|
||||
Aabr {
|
||||
min: Vec2 {
|
||||
x: (min_x * p_scale_factor) as u16,
|
||||
y: (min_y * p_scale_factor) as u16,
|
||||
},
|
||||
max: Vec2 {
|
||||
x: ((min_x + w) * p_scale_factor) as u16,
|
||||
y: ((min_y + h) * p_scale_factor) as u16,
|
||||
}
|
||||
}
|
||||
.intersection(window_scizzor)
|
||||
};
|
||||
if new_scizzor != current_scizzor {
|
||||
// Finish the current command
|
||||
match current_img.take() {
|
||||
None =>
|
||||
self.draw_commands.push(DrawCommand::plain(renderer.create_model(&mesh).unwrap())),
|
||||
Some(image_id) =>
|
||||
self.draw_commands.push(DrawCommand::image(renderer.create_model(&mesh).unwrap(), image_id)),
|
||||
}
|
||||
mesh.clear();
|
||||
|
||||
// Update the scizzor and produce a command.
|
||||
current_scizzor = new_scizzor;
|
||||
self.draw_commands.push(DrawCommand::Scissor(new_scizzor));
|
||||
}
|
||||
|
||||
// Functions for converting for conrod scalar coords to GL vertex coords (-1.0 to 1.0)
|
||||
let vx = |x: f64| (x / ui.win_w * 2.0) as f32;
|
||||
let vy = |y: f64| (y / ui.win_h * 2.0) as f32;
|
||||
let gl_aabr = |rect: conrod_core::Rect| {
|
||||
let (l, r, b, t) = rect.l_r_b_t();
|
||||
Aabr {
|
||||
min: Vec2::new(vx(l), vy(b)),
|
||||
max: Vec2::new(vx(r), vy(t)),
|
||||
}
|
||||
};
|
||||
|
||||
use conrod_core::render::PrimitiveKind;
|
||||
match kind {
|
||||
@ -255,13 +327,13 @@ impl Ui {
|
||||
Some(image_id) if image_id == new_image_id => (),
|
||||
// If we were in the `Plain` drawing state, switch to Image drawing state.
|
||||
None => {
|
||||
self.draw_commands.push(DrawCommand::Plain(renderer.create_model(&mesh).unwrap()));
|
||||
self.draw_commands.push(DrawCommand::plain(renderer.create_model(&mesh).unwrap()));
|
||||
mesh.clear();
|
||||
current_img = Some(new_image_id);
|
||||
}
|
||||
// If we were drawing a different image, switch state to draw *this* image.
|
||||
Some(image_id) => {
|
||||
self.draw_commands.push(DrawCommand::Image(renderer.create_model(&mesh).unwrap(), image_id));
|
||||
self.draw_commands.push(DrawCommand::image(renderer.create_model(&mesh).unwrap(), image_id));
|
||||
mesh.clear();
|
||||
current_img = Some(new_image_id);
|
||||
}
|
||||
@ -286,13 +358,14 @@ impl Ui {
|
||||
}
|
||||
None => (0.0, 1.0, 0.0, 1.0),
|
||||
};
|
||||
// Convert from conrod Scalar range to GL range -1.0 to 1.0.
|
||||
let (l, r, b, t) = rect.l_r_b_t();
|
||||
let (l, r, b, t) = (vx(l), vx(r), vy(b), vy(t));
|
||||
let uv = Aabr {
|
||||
min: Vec2::new(uv_l, uv_b),
|
||||
max: Vec2::new(uv_r, uv_t),
|
||||
};
|
||||
push_ui_quad_to_mesh(
|
||||
&mut mesh,
|
||||
[l, t , r, b],
|
||||
[uv_l, uv_t, uv_r, uv_b],
|
||||
gl_aabr(rect),
|
||||
uv,
|
||||
color,
|
||||
UiMode::Image,
|
||||
);
|
||||
@ -300,7 +373,7 @@ impl Ui {
|
||||
}
|
||||
PrimitiveKind::Text { color, text, font_id } => {
|
||||
switch_to_plain_state!();
|
||||
// Get screen width
|
||||
// Get screen width and height
|
||||
let (screen_w, screen_h) = renderer.get_resolution().map(|e| e as f32).into_tuple();
|
||||
// Calculate dpi factor
|
||||
let dpi_factor = screen_w / ui.win_w as f32;
|
||||
@ -326,22 +399,24 @@ impl Ui {
|
||||
|
||||
for g in positioned_glyphs {
|
||||
if let Ok(Some((uv_rect, screen_rect))) = glyph_cache.rect_for(font_id.index(), g) {
|
||||
let (uv_l, uv_r, uv_t, uv_b) = (
|
||||
uv_rect.min.x,
|
||||
uv_rect.max.x,
|
||||
uv_rect.min.y,
|
||||
uv_rect.max.y,
|
||||
);
|
||||
let (l, t, r, b) = (
|
||||
(screen_rect.min.x as f32 / screen_w - 0.5) * 2.0,
|
||||
(screen_rect.min.y as f32 / screen_h - 0.5) * -2.0,
|
||||
(screen_rect.max.x as f32 / screen_w - 0.5) * 2.0,
|
||||
(screen_rect.max.y as f32 / screen_h - 0.5) * -2.0,
|
||||
);
|
||||
let uv = Aabr {
|
||||
min: Vec2::new(uv_rect.min.x, uv_rect.max.y),
|
||||
max: Vec2::new(uv_rect.max.x, uv_rect.min.y),
|
||||
};
|
||||
let rect = Aabr {
|
||||
min: Vec2::new(
|
||||
(screen_rect.min.x as f32 / screen_w - 0.5) * 2.0,
|
||||
(screen_rect.max.y as f32 / screen_h - 0.5) * -2.0,
|
||||
),
|
||||
max: Vec2::new(
|
||||
(screen_rect.max.x as f32 / screen_w - 0.5) * 2.0,
|
||||
(screen_rect.min.y as f32 / screen_h - 0.5) * -2.0,
|
||||
),
|
||||
};
|
||||
push_ui_quad_to_mesh(
|
||||
&mut mesh,
|
||||
[l, t , r, b],
|
||||
[uv_l, uv_t, uv_r, uv_b],
|
||||
rect,
|
||||
uv,
|
||||
color,
|
||||
UiMode::Text,
|
||||
);
|
||||
@ -358,13 +433,13 @@ impl Ui {
|
||||
|
||||
switch_to_plain_state!();
|
||||
|
||||
// Convert from conrod Scalar range to GL range -1.0 to 1.0.
|
||||
let (l, r, b, t) = rect.l_r_b_t();
|
||||
let (l, r, b, t) = (vx(l), vx(r), vy(b), vy(t));
|
||||
push_ui_quad_to_mesh(
|
||||
&mut mesh,
|
||||
[l, t , r, b],
|
||||
[0.0, 0.0, 0.0, 0.0],
|
||||
gl_aabr(rect),
|
||||
Aabr {
|
||||
min: Vec2::new(0.0, 0.0),
|
||||
max: Vec2::new(0.0, 0.0),
|
||||
},
|
||||
color,
|
||||
UiMode::Geometry,
|
||||
);
|
||||
@ -401,12 +476,12 @@ impl Ui {
|
||||
//PrimitiveKind::TrianglesMultiColor {..} => {println!("primitive kind multicolor with id {:?}", id);}
|
||||
}
|
||||
}
|
||||
// Enter the final command.
|
||||
// Enter the final command
|
||||
match current_img {
|
||||
None =>
|
||||
self.draw_commands.push(DrawCommand::Plain(renderer.create_model(&mesh).unwrap())),
|
||||
self.draw_commands.push(DrawCommand::plain(renderer.create_model(&mesh).unwrap())),
|
||||
Some(image_id) =>
|
||||
self.draw_commands.push(DrawCommand::Image(renderer.create_model(&mesh).unwrap(), image_id)),
|
||||
self.draw_commands.push(DrawCommand::image(renderer.create_model(&mesh).unwrap(), image_id)),
|
||||
}
|
||||
|
||||
// Handle window resizing
|
||||
@ -419,17 +494,32 @@ impl Ui {
|
||||
}
|
||||
|
||||
pub fn render(&self, renderer: &mut Renderer) {
|
||||
let mut scissor = default_scissor(renderer);
|
||||
for draw_command in self.draw_commands.iter() {
|
||||
match draw_command {
|
||||
DrawCommand::Image(model, image_id) => {
|
||||
let tex = self.image_map.get(&image_id).expect("Image does not exist in image map");
|
||||
renderer.render_ui_element(&model, &tex);
|
||||
},
|
||||
DrawCommand::Plain(model) => {
|
||||
let tex = self.cache.glyph_cache_tex();
|
||||
renderer.render_ui_element(&model, &tex);
|
||||
},
|
||||
DrawCommand::Scissor(scizzor) => {
|
||||
scissor = *scizzor;
|
||||
}
|
||||
DrawCommand::Draw { kind, model } => {
|
||||
let tex = match kind {
|
||||
DrawKind::Image(image_id) => {
|
||||
self.image_map.get(&image_id).expect("Image does not exist in image map")
|
||||
}
|
||||
DrawKind::Plain => {
|
||||
self.cache.glyph_cache_tex()
|
||||
}
|
||||
};
|
||||
renderer.render_ui_element(&model, &tex, scissor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn default_scissor(renderer: &mut Renderer) -> Aabr<u16> {
|
||||
let (screen_w, screen_h) = renderer.get_resolution().map(|e| e as u16).into_tuple();
|
||||
Aabr {
|
||||
min: Vec2 { x: 0, y: 0 },
|
||||
max: Vec2 { x: screen_w, y: screen_h }
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user