Skip to content

Commit

Permalink
Add text component
Browse files Browse the repository at this point in the history
  • Loading branch information
Xaeroxe committed Oct 29, 2017
1 parent 59a568e commit c31452e
Show file tree
Hide file tree
Showing 10 changed files with 262 additions and 82 deletions.
2 changes: 1 addition & 1 deletion amethyst_renderer/src/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ impl Renderer {
let mut targets = HashMap::default();
targets.insert("".to_string(), self.main_target.clone());
for (key, value) in pipe.targets().iter().filter(|&(k, _)| !k.is_empty()) {
let (key, mut target) = TargetBuilder::new(key.clone())
let (key, target) = TargetBuilder::new(key.clone())
.with_num_color_bufs(value.color_bufs().len())
.with_depth_buf(value.depth_buf().is_some())
.build(&mut self.factory, new_size)
Expand Down
3 changes: 2 additions & 1 deletion amethyst_renderer/src/tex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ where

/// Builds and returns the new texture.
pub fn build(self, fac: &mut Factory) -> Result<Texture> {
use std::mem::size_of;
use gfx::Factory;
use gfx::format::Swizzle;
use gfx::memory::cast_slice;
Expand All @@ -159,7 +160,7 @@ where
let mut data = self.data.as_ref();

if cfg!(feature = "opengl") {
let pixel_width = (self.info.format.get_total_bits() / 8) as usize;
let pixel_width = (self.info.format.get_total_bits() / 8) as usize / size_of::<T>();
v_flip_buffer = Vec::with_capacity(data.len());
let (w, h, _, _) = self.info.kind.get_dimensions();
let w = w as usize;
Expand Down
30 changes: 20 additions & 10 deletions amethyst_ui/src/bundle.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
//! ECS rendering bundle
use amethyst_assets::{AssetStorage, Handle, Processor};
use amethyst_core::bundle::{ECSBundle, Result};
use specs::{DispatcherBuilder, World};

use super::*;

/// Rendering bundle
/// UI bundle
///
/// Will register all necessary components needed for rendering, along with any resources.
/// Will also register asset contexts with the asset `Loader`, and add systems for merging
/// `AssetFuture` into its related component.
/// Will register all necessary components and systems needed for UI, along with any resources.
///
pub struct UiBundle;
/// UiTextRenderer is registered with name "ui_text".
pub struct UiBundle {
deps: &'static [&'static str],
}

impl UiBundle {
/// Create a new render bundle
pub fn new() -> Self {
UiBundle
/// Create a new UI bundle, the dependencies given will be the dependencies for the
/// UiTextRenderer system.
pub fn new(deps: &'static [&'static str]) -> Self {
UiBundle {
deps
}
}
}

Expand All @@ -28,7 +33,12 @@ impl<'a, 'b> ECSBundle<'a, 'b> for UiBundle {
) -> Result<DispatcherBuilder<'a, 'b>> {
world.register::<UiImage>();
world.register::<UiTransform>();

Ok(builder)
world.register::<UiText>();
world.register::<Handle<FontFileAsset>>();
world.add_resource(AssetStorage::<FontFileAsset>::new());
Ok(builder
.add(UiTextRenderer, "ui_text", self.deps)
.add(Processor::<FontFileAsset>::new(), "font_processor", &[])
)
}
}
17 changes: 10 additions & 7 deletions amethyst_ui/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,33 @@ use rusttype::{Font, FontCollection};
use specs::DenseVecStorage;

/// A loaded set of fonts from a file.
pub struct FontFileAsset(Vec<Font<'static>>);
pub struct FontFileAsset(pub Vec<Font<'static>>);

pub struct FontData(Vec<Font<'static>>);

impl Asset for FontFileAsset {
type Data = Vec<Font<'static>>;
type Data = FontData;
type HandleStorage = DenseVecStorage<Handle<Self>>;
}

impl From<Vec<Font<'static>>> for FontFileAsset {
fn from(fonts: Vec<Font<'static>>) -> FontFileAsset {
FontFileAsset(fonts)
impl Into<Result<FontFileAsset, BoxedErr>> for FontData {
fn into(self) -> Result<FontFileAsset, BoxedErr> {
Ok(FontFileAsset(self.0))
}
}

/// Loads font files, supports TrueType and **some** OpenType files.
///
/// OpenType is a superset of TrueType, so if your OpenType file uses any features that don't
/// exist in TrueType this will fail.
#[derive(Clone)]
pub struct FontFormat;

impl SimpleFormat<FontFileAsset> for FontFormat {
const NAME: &'static str = "FONT";
type Options = ();

fn import(&self, bytes: Vec<u8>, _: ()) -> Result<Vec<Font<'static>>, BoxedErr> {
Ok(FontCollection::from_bytes(bytes).into_fonts().collect::<Vec<Font>>())
fn import(&self, bytes: Vec<u8>, _: ()) -> Result<FontData, BoxedErr> {
Ok(FontData(FontCollection::from_bytes(bytes).into_fonts().collect::<Vec<Font>>()))
}
}
6 changes: 0 additions & 6 deletions amethyst_ui/src/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,6 @@ use specs::{Component, DenseVecStorage};
pub struct UiImage {
/// The texture to display
pub texture: TextureHandle,

/// When this is false the image will be stretched or compressed to fit the bounding
/// `UiTransform`, if it's true then the image will retain its dimensions, either being cut off
/// if the `UiTransform` is too small, or simply not filling the space if the `UiTransform` is
/// too large.
pub preserve_aspect_ratio: bool,
}

impl Component for UiImage {
Expand Down
4 changes: 2 additions & 2 deletions amethyst_ui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ mod text;
mod transform;

pub use self::bundle::UiBundle;
pub use self::format::FontFormat;
pub use self::format::{FontFileAsset, FontFormat};
pub use self::image::UiImage;
pub use self::pass::DrawUi;
pub use self::text::UiText;
pub use self::text::{UiText, UiTextRenderer};
pub use self::transform::UiTransform;
49 changes: 32 additions & 17 deletions amethyst_ui/src/pass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ impl<'a> PassData<'a> for DrawUi {
Fetch<'a, AssetStorage<Texture>>,
ReadStorage<'a, UiImage>,
ReadStorage<'a, UiTransform>,
ReadStorage<'a, UiText>,
);
}

Expand All @@ -115,13 +116,14 @@ impl Pass for DrawUi {
fn apply<'a, 'b: 'a>(
&'a mut self,
supplier: Supplier<'a>,
(entities, screen_dimensions, mesh_storage, tex_storage, ui_image, ui_transform): (
(entities, screen_dimensions, mesh_storage, tex_storage, ui_image, ui_transform, ui_text): (
Entities<'a>,
Fetch<'a, ScreenDimensions>,
Fetch<'a, AssetStorage<Mesh>>,
Fetch<'a, AssetStorage<Texture>>,
ReadStorage<'a, UiImage>,
ReadStorage<'a, UiTransform>,
ReadStorage<'a, UiText>,
),
) -> DrawUiApply<'a> {
DrawUiApply {
Expand All @@ -131,6 +133,7 @@ impl Pass for DrawUi {
tex_storage,
ui_image,
ui_transform,
ui_text,
unit_mesh: self.mesh_handle.clone(),
cached_draw_order: &mut self.cached_draw_order,
supplier,
Expand All @@ -145,6 +148,7 @@ pub struct DrawUiApply<'a> {
tex_storage: Fetch<'a, AssetStorage<Texture>>,
ui_image: ReadStorage<'a, UiImage>,
ui_transform: ReadStorage<'a, UiTransform>,
ui_text: ReadStorage<'a, UiText>,
unit_mesh: MeshHandle,
cached_draw_order: &'a mut Vec<(f32, Entity)>,
supplier: Supplier<'a>,
Expand All @@ -164,6 +168,7 @@ impl<'a> ParallelIterator for DrawUiApply<'a> {
tex_storage,
ui_image,
ui_transform,
ui_text,
unit_mesh,
cached_draw_order,
supplier,
Expand All @@ -175,6 +180,7 @@ impl<'a> ParallelIterator for DrawUiApply<'a> {
let mesh_storage = &mesh_storage;
let tex_storage = &tex_storage;
let ui_image = &ui_image;
let ui_text = &ui_text;
let ui_transform = &ui_transform;
let unit_mesh = &unit_mesh;

Expand All @@ -191,7 +197,7 @@ impl<'a> ParallelIterator for DrawUiApply<'a> {

// Attempt to insert the new entities in sorted position. Should reduce work during
// the sorting step.
for (entity, _image, transform) in (entities, ui_image, ui_transform).join() {
for (entity, transform) in (entities, ui_transform).join() {
if cached_draw_order
.iter()
.position(|&(_z, cached_entity)| entity == cached_entity)
Expand Down Expand Up @@ -233,27 +239,36 @@ impl<'a> ParallelIterator for DrawUiApply<'a> {
{
// These are safe as we guaranteed earlier these entities are present.
let ui_transform = ui_transform.get(entity).unwrap();
let ui_image = ui_image.get(entity).unwrap();
if let Some(mesh) = mesh_storage.get(unit_mesh) {
let vbuf = match mesh.buffer(PosTex::ATTRIBUTES) {
Some(vbuf) => vbuf.clone(),
None => continue,
};
let vertex_args = VertexArgs {
proj_vec: proj_vec.into(),
coord: [ui_transform.x, ui_transform.y],
dimension: [ui_transform.width, ui_transform.height],
};
effect.update_constant_buffer("VertexArgs", &vertex_args, encoder);
effect.data.vertex_bufs.push(vbuf);
if let Some(ui_image) = ui_image.get(entity) {
if let Some(image) = tex_storage.get(&ui_image.texture) {
effect.data.textures.push(image.view().clone());
effect.data.samplers.push(image.sampler().clone());
effect.draw(mesh.slice(), encoder);
effect.clear();
}
}

if let Some(image) = tex_storage.get(&ui_image.texture) {
let vertex_args = VertexArgs {
proj_vec: proj_vec.into(),
coord: [ui_transform.x, ui_transform.y],
dimension: [ui_transform.width, ui_transform.height],
};

effect.update_constant_buffer("VertexArgs", &vertex_args, encoder);
effect.data.textures.push(image.view().clone());
effect.data.samplers.push(image.sampler().clone());

effect.data.vertex_bufs.push(vbuf);

effect.draw(mesh.slice(), encoder);
if let Some(ui_text) = ui_text.get(entity) {
if let Some(ref texture) = ui_text.texture {
if let Some(image) = tex_storage.get(texture) {
effect.data.textures.push(image.view().clone());
effect.data.samplers.push(image.sampler().clone());
effect.draw(mesh.slice(), encoder);
effect.clear();
}
}
}
}
}
Expand Down
Loading

0 comments on commit c31452e

Please sign in to comment.