use crate::{
define_widget, font::default::get_default_font, Anchor, FontAsset, FontHandle, Stretch, UiText,
UiTransform, WidgetId, Widgets,
};
use amethyst_assets::{AssetStorage, Loader};
use amethyst_core::ecs::{
prelude::{Entities, Entity, Read, ReadExpect, World, WriteExpect, WriteStorage},
shred::{ResourceId, SystemData},
};
const DEFAULT_Z: f32 = 1.0;
const DEFAULT_WIDTH: f32 = 128.0;
const DEFAULT_HEIGHT: f32 = 64.0;
const DEFAULT_TXT_COLOR: [f32; 4] = [0.0, 0.0, 0.0, 1.0];
define_widget!(UiLabel =>
entities: [text_entity]
components: [
(has UiTransform as position on text_entity),
(has UiText as text on text_entity)
]
);
#[allow(missing_debug_implementations)]
#[derive(SystemData)]
pub struct UiLabelBuilderResources<'a, I: WidgetId = u32>
where
I: WidgetId,
{
font_asset: Read<'a, AssetStorage<FontAsset>>,
loader: ReadExpect<'a, Loader>,
entities: Entities<'a>,
text: WriteStorage<'a, UiText>,
transform: WriteStorage<'a, UiTransform>,
label_widgets: WriteExpect<'a, Widgets<UiLabel, I>>,
}
#[derive(Debug)]
pub struct UiLabelBuilder<I = u32>
where
I: WidgetId,
{
id: Option<I>,
x: f32,
y: f32,
z: f32,
width: f32,
height: f32,
anchor: Anchor,
stretch: Stretch,
text: String,
text_color: [f32; 4],
font: Option<FontHandle>,
font_size: f32,
parent: Option<Entity>,
}
impl<'a, I> Default for UiLabelBuilder<I>
where
I: WidgetId + 'static,
{
fn default() -> Self {
UiLabelBuilder {
id: None,
x: 0.,
y: 0.,
z: DEFAULT_Z,
width: DEFAULT_WIDTH,
height: DEFAULT_HEIGHT,
anchor: Anchor::TopLeft,
stretch: Stretch::NoStretch,
text: "".to_string(),
text_color: DEFAULT_TXT_COLOR,
font: None,
font_size: 32.,
parent: None,
}
}
}
impl<'a, I> UiLabelBuilder<I>
where
I: WidgetId + 'static,
{
pub fn new<S: ToString>(text: S) -> UiLabelBuilder<I> {
let mut builder = UiLabelBuilder::default();
builder.text = text.to_string();
builder
}
pub fn with_id(mut self, id: I) -> Self {
self.id = Some(id);
self
}
pub fn with_size(mut self, width: f32, height: f32) -> Self {
self.width = width;
self.height = height;
self
}
pub fn with_position(mut self, x: f32, y: f32) -> Self {
self.x = x;
self.y = y;
self
}
pub fn with_anchor(mut self, anchor: Anchor) -> Self {
self.anchor = anchor;
self
}
pub fn with_stretch(mut self, stretch: Stretch) -> Self {
self.stretch = stretch;
self
}
pub fn with_text<S>(mut self, text: S) -> Self
where
S: ToString,
{
self.text = text.to_string();
self
}
pub fn with_text_color(mut self, text_color: [f32; 4]) -> Self {
self.text_color = text_color;
self
}
pub fn with_font(mut self, font: FontHandle) -> Self {
self.font = Some(font);
self
}
pub fn with_font_size(mut self, size: f32) -> Self {
self.font_size = size;
self
}
pub fn with_parent(mut self, parent: Entity) -> Self {
self.parent = Some(parent);
self
}
pub fn build(self, mut res: UiLabelBuilderResources<'a, I>) -> (I, UiLabel) {
let text_entity = res.entities.create();
let widget = UiLabel::new(text_entity);
let id = {
let widget = widget.clone();
if let Some(id) = self.id {
let added_id = id.clone();
res.label_widgets.add_with_id(id, widget);
added_id
} else {
res.label_widgets.add(widget)
}
};
res.transform
.insert(
text_entity,
UiTransform::new(
format!("{}_label", id),
self.anchor,
Anchor::Middle,
self.x,
self.y,
self.z,
self.width,
self.height,
)
.with_stretch(self.stretch),
)
.expect("Unreachable: Inserting newly created entity");
let font_handle = self
.font
.unwrap_or_else(|| get_default_font(&res.loader, &res.font_asset));
res.text
.insert(
text_entity,
UiText::new(font_handle, self.text, self.text_color, self.font_size),
)
.expect("Unreachable: Inserting newly created entity");
(id, widget)
}
pub fn build_from_world(self, world: &World) -> (I, UiLabel) {
self.build(UiLabelBuilderResources::<I>::fetch(&world))
}
}