Added ui utilities
parent
1ae8e6c5a8
commit
62d63be55e
|
@ -0,0 +1,18 @@
|
||||||
|
mod spriteimage;
|
||||||
|
mod spritetextarea;
|
||||||
|
|
||||||
|
pub(super) use spriteimage::SpriteImage;
|
||||||
|
pub(super) use spritetextarea::SpriteTextArea;
|
||||||
|
|
||||||
|
use nalgebra::{Point2, Vector2};
|
||||||
|
|
||||||
|
/// Represents a rectangular region inside a sprite.
|
||||||
|
pub(crate) struct SpriteRect {
|
||||||
|
/// The position of the top-left corner of this rectangle, in fractional units.
|
||||||
|
/// (0.0 is left edge of sprite, 1.0 is right edge)
|
||||||
|
pub pos: Point2<f32>,
|
||||||
|
|
||||||
|
/// The width and height of this rectangle, in fractional units.
|
||||||
|
/// 1.0 will be as tall as the sprite, 0.5 will be half as tall
|
||||||
|
pub dim: Vector2<f32>,
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
use galactica_content::SpriteHandle;
|
||||||
|
use galactica_util::to_radians;
|
||||||
|
use nalgebra::{Point2, Vector2};
|
||||||
|
|
||||||
|
use super::SpriteRect;
|
||||||
|
use crate::{vertexbuffer::types::UiInstance, PositionAnchor, RenderState};
|
||||||
|
|
||||||
|
pub struct SpriteImage {
|
||||||
|
parent: SpriteHandle,
|
||||||
|
parent_position: Point2<f32>,
|
||||||
|
parent_size: f32,
|
||||||
|
|
||||||
|
inner: SpriteHandle,
|
||||||
|
mask: SpriteHandle,
|
||||||
|
rect: SpriteRect,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SpriteImage {
|
||||||
|
pub fn new(
|
||||||
|
parent: SpriteHandle,
|
||||||
|
parent_position: Point2<f32>,
|
||||||
|
parent_size: f32,
|
||||||
|
inner: SpriteHandle,
|
||||||
|
mask: SpriteHandle,
|
||||||
|
rect: SpriteRect,
|
||||||
|
) -> Self {
|
||||||
|
return Self {
|
||||||
|
parent,
|
||||||
|
parent_position,
|
||||||
|
parent_size,
|
||||||
|
inner,
|
||||||
|
mask,
|
||||||
|
rect,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add this image to the gpu sprite buffer
|
||||||
|
pub fn push_to_buffer(&self, state: &mut RenderState) {
|
||||||
|
let h = self.parent_size;
|
||||||
|
let w = self.parent.aspect * h;
|
||||||
|
|
||||||
|
let zero = Point2::new(
|
||||||
|
self.parent_position.x - (w / 2.0),
|
||||||
|
self.parent_position.y + (h / 2.0),
|
||||||
|
);
|
||||||
|
|
||||||
|
let pos = zero + Vector2::new(self.rect.pos.x * w, -self.rect.pos.y * h);
|
||||||
|
let dim = Vector2::new(self.rect.dim.x * w, self.rect.dim.y * h);
|
||||||
|
|
||||||
|
state.push_ui_buffer(UiInstance {
|
||||||
|
anchor: PositionAnchor::CNw.to_int(),
|
||||||
|
position: pos.into(),
|
||||||
|
angle: to_radians(90.0),
|
||||||
|
size: dim.y,
|
||||||
|
color: [1.0, 1.0, 1.0, 1.0],
|
||||||
|
sprite_index: self.inner.get_index(),
|
||||||
|
mask_index: [1, self.mask.get_index()],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
use galactica_content::SpriteHandle;
|
||||||
|
use glyphon::{cosmic_text::Align, Attrs, Buffer, Color, Metrics, Shaping, TextArea, TextBounds};
|
||||||
|
use nalgebra::{Point2, Vector2};
|
||||||
|
|
||||||
|
use super::SpriteRect;
|
||||||
|
use crate::RenderState;
|
||||||
|
|
||||||
|
/// Represents a text area inside a sprite.
|
||||||
|
pub(crate) struct SpriteTextArea {
|
||||||
|
/// Parent sprite
|
||||||
|
sprite: SpriteHandle,
|
||||||
|
|
||||||
|
/// Position of parent sprite's center, in logical pixels,
|
||||||
|
/// with 0, 0 at the center of the screen
|
||||||
|
sprite_position: Point2<f32>,
|
||||||
|
|
||||||
|
/// Height of parent sprite, in logical pixels
|
||||||
|
sprite_size: f32,
|
||||||
|
|
||||||
|
/// Bounds of text area
|
||||||
|
rect: SpriteRect,
|
||||||
|
|
||||||
|
/// Text buffer
|
||||||
|
buffer: Buffer,
|
||||||
|
|
||||||
|
/// Text color
|
||||||
|
color: Color,
|
||||||
|
|
||||||
|
/// Text alignment
|
||||||
|
align: Align,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SpriteTextArea {
|
||||||
|
pub fn new(
|
||||||
|
state: &mut RenderState,
|
||||||
|
sprite: SpriteHandle,
|
||||||
|
sprite_position: Point2<f32>,
|
||||||
|
sprite_size: f32,
|
||||||
|
rect: SpriteRect,
|
||||||
|
text_metrics: Metrics,
|
||||||
|
color: Color,
|
||||||
|
align: Align,
|
||||||
|
) -> Self {
|
||||||
|
let mut s = Self {
|
||||||
|
buffer: Buffer::new(&mut state.text_font_system, text_metrics),
|
||||||
|
sprite_size: f32::NAN,
|
||||||
|
sprite,
|
||||||
|
sprite_position,
|
||||||
|
rect,
|
||||||
|
align,
|
||||||
|
color,
|
||||||
|
};
|
||||||
|
s.set_size(state, sprite_size);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_size(&mut self, state: &mut RenderState, sprite_size: f32) {
|
||||||
|
self.sprite_size = sprite_size;
|
||||||
|
self.buffer.set_size(
|
||||||
|
&mut state.text_font_system,
|
||||||
|
(self.rect.dim.x * self.sprite_size) * state.window.scale_factor() as f32,
|
||||||
|
(self.rect.dim.y * self.sprite_size * self.sprite.aspect)
|
||||||
|
* state.window.scale_factor() as f32,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_text(&mut self, state: &mut RenderState, text: &str, attrs: Attrs) {
|
||||||
|
self.buffer
|
||||||
|
.set_text(&mut state.text_font_system, text, attrs, Shaping::Advanced);
|
||||||
|
|
||||||
|
for l in &mut self.buffer.lines {
|
||||||
|
l.set_align(Some(self.align));
|
||||||
|
}
|
||||||
|
self.buffer.shape_until_scroll(&mut state.text_font_system);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_textarea(&self, state: &RenderState) -> TextArea {
|
||||||
|
let h = self.sprite_size;
|
||||||
|
let w = self.sprite.aspect * h;
|
||||||
|
|
||||||
|
// Glypon works with physical pixels, so we must convert
|
||||||
|
let fac = state.window.scale_factor() as f32;
|
||||||
|
|
||||||
|
// All the units below are in logical pixels
|
||||||
|
let zero = Vector2::new(
|
||||||
|
(state.window_size.width as f32 / (2.0 * fac)) - (w / 2.0) + self.sprite_position.x,
|
||||||
|
(state.window_size.height as f32 / (2.0 * fac)) - (h / 2.0) - self.sprite_position.y,
|
||||||
|
);
|
||||||
|
let corner_ne = zero + Vector2::new(self.rect.pos.x * w, self.rect.pos.y * h);
|
||||||
|
let corner_sw = corner_ne + Vector2::new(self.rect.dim.x * w, self.rect.dim.y * h);
|
||||||
|
|
||||||
|
TextArea {
|
||||||
|
buffer: &self.buffer,
|
||||||
|
top: corner_ne.y * fac,
|
||||||
|
left: corner_ne.x * fac,
|
||||||
|
scale: 1.0,
|
||||||
|
bounds: TextBounds {
|
||||||
|
top: (corner_ne.y * fac) as i32,
|
||||||
|
bottom: (corner_sw.y * fac) as i32,
|
||||||
|
left: (corner_ne.x * fac) as i32,
|
||||||
|
right: (corner_sw.x * fac) as i32,
|
||||||
|
},
|
||||||
|
default_color: self.color,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue