Label component
This commit is contained in:
parent
e093a3243b
commit
86c18edbfd
@ -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))
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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" }
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
|
51
crates/bevy_ui/src/widget/label.rs
Normal file
51
crates/bevy_ui/src/widget/label.rs
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
3
crates/bevy_ui/src/widget/mod.rs
Normal file
3
crates/bevy_ui/src/widget/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
mod label;
|
||||
|
||||
pub use label::*;
|
@ -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
|
@ -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
|
||||
|
@ -1,5 +1,4 @@
|
||||
use bevy::prelude::*;
|
||||
use bevy_asset::AssetServer;
|
||||
|
||||
fn main() {
|
||||
App::build()
|
||||
|
@ -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.
|
@ -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()
|
||||
});
|
||||
}
|
||||
|
@ -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::{
|
||||
|
Loading…
Reference in New Issue
Block a user