Label component

This commit is contained in:
Carter Anderson 2020-05-17 18:09:29 -07:00
parent e093a3243b
commit 86c18edbfd
13 changed files with 128 additions and 31 deletions

View File

@ -84,6 +84,10 @@ impl<T> Assets<T> {
self.assets.get_mut(&handle.id)
}
pub fn get_or_insert_with(&mut self, handle: Handle<T>, insert_fn: impl FnOnce() -> T) -> &mut T {
self.assets.entry(handle.id).or_insert_with(insert_fn)
}
pub fn iter(&self) -> impl Iterator<Item = (Handle<T>, &T)> {
self.assets.iter().map(|(k, v)| (Handle::from_id(*k), v))
}

View File

@ -7,7 +7,7 @@ use std::ops::{Add, AddAssign};
use zerocopy::AsBytes;
#[repr(C)]
#[derive(Debug, Default, Clone, Copy, PartialEq, AsBytes)]
#[derive(Debug, Clone, Copy, PartialEq, AsBytes)]
pub struct Color {
pub r: f32,
pub g: f32,
@ -31,6 +31,12 @@ impl Color {
}
}
impl Default for Color {
fn default() -> Self {
Color::WHITE
}
}
impl AddAssign<Color> for Color {
fn add_assign(&mut self, rhs: Color) {
*self = Color {

View File

@ -9,6 +9,7 @@ bevy_app = { path = "../bevy_app" }
bevy_asset = { path = "../bevy_asset" }
bevy_core = { path = "../bevy_core" }
bevy_derive = { path = "../bevy_derive" }
bevy_text = { path = "../bevy_text" }
bevy_transform = { path = "../bevy_transform" }
bevy_render = { path = "../bevy_render" }
bevy_window = { path = "../bevy_window" }

View File

@ -1,5 +1,7 @@
use super::Node;
use crate::{render::UI_PIPELINE_HANDLE, sprite::Sprite, ColorMaterial, Rect, QUAD_HANDLE};
use crate::{
render::UI_PIPELINE_HANDLE, sprite::Sprite, widget::Label, ColorMaterial, Rect, QUAD_HANDLE,
};
use bevy_asset::Handle;
use bevy_derive::EntityArchetype;
use bevy_render::{mesh::Mesh, Renderable};
@ -29,6 +31,34 @@ impl Default for UiEntity {
}
}
#[derive(EntityArchetype)]
#[module(meta = false)]
pub struct LabelEntity {
pub node: Node,
pub rect: Rect,
pub mesh: Handle<Mesh>, // TODO: maybe abstract this out
pub material: Handle<ColorMaterial>,
pub renderable: Renderable,
pub label: Label,
}
impl Default for LabelEntity {
fn default() -> Self {
LabelEntity {
node: Default::default(),
rect: Default::default(),
mesh: QUAD_HANDLE,
// NOTE: labels each get their own material.
material: Handle::new(), // TODO: maybe abstract this out
renderable: Renderable {
pipelines: vec![UI_PIPELINE_HANDLE],
..Default::default()
},
label: Label::default(),
}
}
}
#[derive(EntityArchetype)]
#[module(meta = false)]
pub struct SpriteEntity {

View File

@ -1,6 +1,7 @@
mod anchors;
mod color_material;
pub mod entity;
pub mod widget;
mod margins;
mod node;
mod rect;
@ -27,6 +28,7 @@ use bevy_render::{
use glam::Vec2;
use legion::prelude::IntoSystem;
use sprite::sprite_system;
use widget::Label;
#[derive(Default)]
pub struct UiPlugin;
@ -36,12 +38,13 @@ pub const QUAD_HANDLE: Handle<Mesh> = Handle::from_u128(142404619811301375266013
impl AppPlugin for UiPlugin {
fn build(&self, app: &mut AppBuilder) {
app.add_asset::<ColorMaterial>()
.add_system_to_stage(stage::POST_UPDATE, sprite_system())
.add_system_to_stage(stage::POST_UPDATE, ui_update_system())
.add_system_to_stage(stage::POST_UPDATE, Label::label_system.system())
.add_system_to_stage(
stage::POST_UPDATE,
asset_shader_def_system::<ColorMaterial>.system(),
)
.add_system_to_stage(stage::POST_UPDATE, sprite_system())
.add_system_to_stage(stage::POST_UPDATE, ui_update_system());
);
let resources = app.resources();
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();

View File

@ -0,0 +1,51 @@
use crate::{ColorMaterial, Rect, Res, ResMut};
use bevy_asset::{Assets, Handle};
use bevy_render::{texture::Texture, Color};
use bevy_text::Font;
use legion::prelude::Com;
pub struct Label {
pub text: String,
pub color: Color,
pub font_size: f32,
pub font: Handle<Font>,
}
impl Default for Label {
fn default() -> Self {
Label {
text: String::new(),
color: Color::WHITE,
font_size: 12.0,
font: Handle::default(),
}
}
}
impl Label {
// PERF: this is horrendously inefficient. (1) new texture every frame (2) no atlas (3) new texture for every label
pub fn label_system(
mut color_materials: ResMut<Assets<ColorMaterial>>,
mut textures: ResMut<Assets<Texture>>,
fonts: Res<Assets<Font>>,
label: Com<Label>,
rect: Com<Rect>,
color_material_handle: Com<Handle<ColorMaterial>>,
) {
if let Some(font) = fonts.get(&label.font) {
let texture = font.render_text(
&label.text,
label.color,
rect.size.x() as usize,
rect.size.y() as usize,
);
let material = color_materials.get_or_insert_with(*color_material_handle, || ColorMaterial::from(Handle::<Texture>::new()));
if let Some(texture) = material.texture {
// TODO: remove texture
}
material.texture = Some(textures.add(texture));
}
}
}

View File

@ -0,0 +1,3 @@
mod label;
pub use label::*;

View File

@ -1,4 +1,4 @@
This crate is deprecated please use [shaderc-rs](https://github.com/google/shaderc-rs) instead.
BEVY NOTE: This crate is a temporary measure unit native rust shader compilation like https://github.com/gfx-rs/naga lands
BEVY NOTE: This crate is a temporary measure until native rust shader compilation like https://github.com/gfx-rs/naga lands

View File

@ -1,5 +1,4 @@
use bevy::prelude::*;
use bevy_asset::AssetServer;
fn main() {
App::build()
@ -10,7 +9,7 @@ fn main() {
fn setup(
command_buffer: &mut CommandBuffer,
asset_server: ResMut<AssetServer>,
asset_server: Res<AssetServer>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// load the mesh

View File

@ -1,5 +1,4 @@
use bevy::prelude::*;
use bevy_asset::AssetServer;
fn main() {
App::build()

View File

@ -1,5 +1,4 @@
use bevy::prelude::*;
use bevy_asset::AssetServer;
/// Hot reloading allows you to modify assets on disk and they will be "live reloaded" while your game is running.
/// This lets you immediately see the results of your changes without restarting the game.

View File

@ -1,40 +1,42 @@
use bevy::prelude::*;
use bevy::{
diagnostic::{Diagnostics, FrameTimeDiagnosticsPlugin},
prelude::*,
};
fn main() {
App::build()
.add_default_plugins()
.add_plugin(FrameTimeDiagnosticsPlugin::default())
.add_startup_system(setup.system())
.add_system(text_update_system.system())
.run();
}
fn setup(
command_buffer: &mut CommandBuffer,
asset_server: Res<AssetServer>,
mut fonts: ResMut<Assets<Font>>,
mut textures: ResMut<Assets<Texture>>,
mut materials: ResMut<Assets<ColorMaterial>>,
) {
let font_handle = asset_server
.load_sync(&mut fonts, "assets/fonts/FiraSans-Bold.ttf")
.unwrap();
let font = fonts.get(&font_handle).unwrap();
fn text_update_system(diagnostics: Res<Diagnostics>, mut label: ComMut<Label>) {
if let Some(fps) = diagnostics.get_measurement(FrameTimeDiagnosticsPlugin::FPS) {
label.text = format!("FPS: {}", fps.value.round());
}
}
let texture = font.render_text("Hello from Bevy!", Color::rgba(0.9, 0.9, 0.9, 1.0), 500, 60);
let half_width = texture.width as f32 / 2.0;
let half_height = texture.height as f32 / 2.0;
let texture_handle = textures.add(texture);
fn setup(command_buffer: &mut CommandBuffer, asset_server: Res<AssetServer>) {
let font_handle = asset_server.load("assets/fonts/FiraSans-Bold.ttf").unwrap();
command_buffer
.build()
// 2d camera
.add_entity(Camera2dEntity::default())
// texture
.add_entity(UiEntity {
.add_entity(LabelEntity {
node: Node::new(
math::vec2(0.0, 0.0),
Anchors::CENTER,
Margins::new(-half_width, half_width, -half_height, half_height),
Anchors::TOP_LEFT,
Margins::new(0.0, 250.0, 0.0, 60.0),
),
material: materials.add(ColorMaterial::texture(texture_handle)),
label: Label {
text: "FPS:".to_string(),
font: font_handle,
font_size: 60.0,
color: Color::WHITE,
},
..Default::default()
});
}

View File

@ -34,7 +34,7 @@ pub use crate::text::Font;
#[cfg(feature = "transform")]
pub use crate::transform::prelude::*;
#[cfg(feature = "ui")]
pub use crate::ui::{entity::*, Anchors, ColorMaterial, Margins, Node, Rect, Sprite};
pub use crate::ui::{entity::*, Anchors, ColorMaterial, Margins, Node, Rect, Sprite, widget::Label};
#[cfg(feature = "window")]
pub use crate::window::{Window, WindowDescriptor, WindowPlugin, Windows};
pub use crate::{