mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 04:33:37 +00:00
ui textures
This commit is contained in:
parent
08c6679f38
commit
1056b79abf
10 changed files with 159 additions and 71 deletions
55
crates/bevy_ui/src/color_material.rs
Normal file
55
crates/bevy_ui/src/color_material.rs
Normal file
|
@ -0,0 +1,55 @@
|
|||
use bevy_asset::{self, Handle};
|
||||
use bevy_derive::Uniforms;
|
||||
use bevy_render::{colors, texture::Texture, Color};
|
||||
|
||||
#[derive(Uniforms)]
|
||||
#[module(meta = false)]
|
||||
pub struct ColorMaterial {
|
||||
pub color: Color,
|
||||
#[uniform(shader_def)]
|
||||
pub texture: Option<Handle<Texture>>,
|
||||
}
|
||||
|
||||
impl ColorMaterial {
|
||||
pub fn color(color: Color) -> Self {
|
||||
ColorMaterial {
|
||||
color,
|
||||
texture: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn texture(texture: Handle<Texture>) -> Self {
|
||||
ColorMaterial {
|
||||
color: colors::WHITE,
|
||||
texture: Some(texture),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn modulated_texture(texture: Handle<Texture>, color: Color) -> Self {
|
||||
ColorMaterial {
|
||||
color,
|
||||
texture: Some(texture),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ColorMaterial {
|
||||
fn default() -> Self {
|
||||
ColorMaterial {
|
||||
color: Color::rgb(1.0, 1.0, 1.0),
|
||||
texture: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Color> for ColorMaterial {
|
||||
fn from(color: Color) -> Self {
|
||||
ColorMaterial::color(color)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Handle<Texture>> for ColorMaterial {
|
||||
fn from(texture: Handle<Texture>) -> Self {
|
||||
ColorMaterial::texture(texture)
|
||||
}
|
||||
}
|
|
@ -1,15 +1,16 @@
|
|||
use super::Node;
|
||||
use crate::{render::UI_PIPELINE_HANDLE, ColorMaterial, Rect, QUAD_HANDLE};
|
||||
use bevy_asset::Handle;
|
||||
use bevy_derive::EntityArchetype;
|
||||
use bevy_render::{mesh::Mesh, Renderable};
|
||||
use crate::{Rect, render::UI_PIPELINE_HANDLE, QUAD_HANDLE};
|
||||
use bevy_asset::Handle;
|
||||
|
||||
#[derive(EntityArchetype)]
|
||||
#[module(meta = false)]
|
||||
pub struct UiEntity {
|
||||
pub node: Node,
|
||||
pub rect: Rect,
|
||||
pub mesh: Handle<Mesh>, // TODO: maybe abstract this out
|
||||
pub mesh: Handle<Mesh>, // TODO: maybe abstract this out
|
||||
pub material: Handle<ColorMaterial>,
|
||||
pub renderable: Renderable,
|
||||
}
|
||||
|
||||
|
@ -19,12 +20,11 @@ impl Default for UiEntity {
|
|||
node: Default::default(),
|
||||
rect: Default::default(),
|
||||
mesh: QUAD_HANDLE,
|
||||
material: Default::default(),
|
||||
renderable: Renderable {
|
||||
pipelines: vec![
|
||||
UI_PIPELINE_HANDLE
|
||||
],
|
||||
pipelines: vec![UI_PIPELINE_HANDLE],
|
||||
..Default::default()
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
mod anchors;
|
||||
mod color_material;
|
||||
pub mod entity;
|
||||
mod margins;
|
||||
mod node;
|
||||
|
@ -7,34 +8,52 @@ mod render;
|
|||
mod ui_update_system;
|
||||
|
||||
pub use anchors::*;
|
||||
pub use color_material::*;
|
||||
pub use margins::*;
|
||||
pub use node::*;
|
||||
pub use rect::*;
|
||||
pub use render::*;
|
||||
pub use ui_update_system::*;
|
||||
|
||||
use bevy_app::{AppBuilder, AppPlugin};
|
||||
use bevy_render::{mesh::{shape::Quad, Mesh}, render_graph::RenderGraph};
|
||||
use bevy_app::{stage, AppBuilder, AppPlugin};
|
||||
use bevy_asset::{AssetStorage, Handle};
|
||||
use bevy_render::{
|
||||
mesh::{shape::Quad, Mesh},
|
||||
render_graph::RenderGraph,
|
||||
shader::asset_handle_shader_def_system,
|
||||
};
|
||||
use glam::Vec2;
|
||||
use legion::prelude::IntoSystem;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct UiPlugin;
|
||||
|
||||
pub const QUAD_HANDLE: Handle<Mesh> = Handle::from_bytes([179, 41, 129, 128, 95, 217, 79, 194, 167, 95, 107, 115, 97, 151, 20, 62]);
|
||||
pub const QUAD_HANDLE: Handle<Mesh> = Handle::from_bytes([
|
||||
179, 41, 129, 128, 95, 217, 79, 194, 167, 95, 107, 115, 97, 151, 20, 62,
|
||||
]);
|
||||
|
||||
impl AppPlugin for UiPlugin {
|
||||
fn build(&self, app: &mut AppBuilder) {
|
||||
let mut color_materials = AssetStorage::<ColorMaterial>::new();
|
||||
color_materials.add_default(ColorMaterial::default());
|
||||
|
||||
{
|
||||
let mut render_graph = app.resources().get_mut::<RenderGraph>().unwrap();
|
||||
render_graph.add_ui_graph(app.resources());
|
||||
app.add_resource(color_materials)
|
||||
.add_system_to_stage(
|
||||
stage::POST_UPDATE,
|
||||
asset_handle_shader_def_system::<ColorMaterial>.system(),
|
||||
)
|
||||
.add_system(ui_update_system());
|
||||
|
||||
let mut meshes = app.resources().get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||
meshes.add_with_handle(QUAD_HANDLE, Mesh::from(Quad {
|
||||
let resources = app.resources();
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
render_graph.add_ui_graph(resources);
|
||||
|
||||
let mut meshes = resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||
meshes.add_with_handle(
|
||||
QUAD_HANDLE,
|
||||
Mesh::from(Quad {
|
||||
size: Vec2::new(1.0, 1.0),
|
||||
}));
|
||||
}
|
||||
app.add_system(ui_update_system());
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use bevy_core::bytes::GetBytes;
|
||||
use bevy_derive::Uniform;
|
||||
use bevy_render::Color;
|
||||
use glam::Vec2;
|
||||
use zerocopy::AsBytes;
|
||||
#[repr(C)]
|
||||
|
@ -9,7 +8,6 @@ use zerocopy::AsBytes;
|
|||
pub struct Rect {
|
||||
pub position: Vec2,
|
||||
pub size: Vec2,
|
||||
pub color: Color,
|
||||
pub z_index: f32,
|
||||
}
|
||||
|
||||
|
|
|
@ -2,12 +2,12 @@ use bevy_asset::{AssetStorage, Handle};
|
|||
use bevy_render::{
|
||||
draw_target::AssignedMeshesDrawTarget,
|
||||
pipeline::{state_descriptors::*, PipelineDescriptor},
|
||||
render_graph::{nodes::{UniformNode, PassNode}, RenderGraph},
|
||||
render_graph::{nodes::{UniformNode, PassNode, AssetUniformNode}, RenderGraph},
|
||||
shader::{Shader, ShaderStage, ShaderStages},
|
||||
texture::TextureFormat, base_render_graph,
|
||||
};
|
||||
use legion::prelude::Resources;
|
||||
use crate::Rect;
|
||||
use crate::{ColorMaterial, Rect};
|
||||
|
||||
pub const UI_PIPELINE_HANDLE: Handle<PipelineDescriptor> =
|
||||
Handle::from_bytes([
|
||||
|
@ -65,6 +65,8 @@ pub trait UiRenderGraphBuilder {
|
|||
|
||||
impl UiRenderGraphBuilder for RenderGraph {
|
||||
fn add_ui_graph(&mut self, resources: &Resources) -> &mut Self {
|
||||
self.add_system_node_named("color_material", AssetUniformNode::<ColorMaterial>::new(false), resources);
|
||||
self.add_node_edge("color_material", base_render_graph::node::MAIN_PASS).unwrap();
|
||||
self.add_system_node_named("rect", UniformNode::<Rect>::new(false), resources);
|
||||
self.add_node_edge("rect", base_render_graph::node::MAIN_PASS).unwrap();
|
||||
let mut pipelines = resources.get_mut::<AssetStorage<PipelineDescriptor>>().unwrap();
|
||||
|
|
|
@ -1,9 +1,24 @@
|
|||
#version 450
|
||||
|
||||
layout(location = 0) in vec4 v_Color;
|
||||
layout(location = 0) in vec2 v_Uv;
|
||||
|
||||
layout(location = 0) out vec4 o_Target;
|
||||
|
||||
layout(set = 2, binding = 0) uniform ColorMaterial_color {
|
||||
vec4 Color;
|
||||
};
|
||||
|
||||
# ifdef COLORMATERIAL_TEXTURE
|
||||
layout(set = 3, binding = 0) uniform texture2D ColorMaterial_texture;
|
||||
layout(set = 3, binding = 1) uniform sampler ColorMaterial_texture_sampler;
|
||||
# endif
|
||||
|
||||
void main() {
|
||||
o_Target = v_Color;
|
||||
vec4 color = Color;
|
||||
# ifdef COLORMATERIAL_TEXTURE
|
||||
color *= texture(
|
||||
sampler2D(ColorMaterial_texture, ColorMaterial_texture_sampler),
|
||||
v_Uv);
|
||||
# endif
|
||||
o_Target = color;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ layout(location = 0) in vec3 Vertex_Position;
|
|||
layout(location = 1) in vec3 Vertex_Normal;
|
||||
layout(location = 2) in vec2 Vertex_Uv;
|
||||
|
||||
layout(location = 0) out vec4 v_Color;
|
||||
layout(location = 0) out vec2 v_Uv;
|
||||
|
||||
layout(set = 0, binding = 0) uniform Camera2d {
|
||||
mat4 ViewProj;
|
||||
|
@ -13,12 +13,11 @@ layout(set = 0, binding = 0) uniform Camera2d {
|
|||
layout(set = 1, binding = 0) uniform Rect {
|
||||
vec2 Rect_Position;
|
||||
vec2 Rect_Size;
|
||||
vec4 Rect_Color;
|
||||
float Rect_ZIndex;
|
||||
};
|
||||
|
||||
void main() {
|
||||
v_Color = Rect_Color;
|
||||
v_Uv = Vertex_Uv;
|
||||
vec3 position = Vertex_Position * vec3(Rect_Size, 0.0);
|
||||
position = position + vec3(Rect_Position + Rect_Size / 2.0, -Rect_ZIndex);
|
||||
gl_Position = ViewProj * vec4(position, 1.0);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use bevy::prelude::*;
|
||||
use bevy_ui::Rect;
|
||||
|
||||
fn main() {
|
||||
App::build()
|
||||
|
@ -19,6 +18,18 @@ fn setup(world: &mut World, resources: &mut Resources) {
|
|||
..Default::default()
|
||||
});
|
||||
|
||||
let mut texture_storage = resources.get_mut::<AssetStorage<Texture>>().unwrap();
|
||||
let texture_path = concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/assets/branding/bevy_logo_dark_big.png"
|
||||
);
|
||||
let texture = Texture::load(TextureType::Png(texture_path.to_string()));
|
||||
let aspect = texture.height as f32 / texture.width as f32;
|
||||
let texture_handle = texture_storage.add(texture);
|
||||
|
||||
let mut color_materials = resources.get_mut::<AssetStorage<ColorMaterial>>().unwrap();
|
||||
let blue_material_handle = color_materials.add(Color::rgb(0.6, 0.6, 1.0).into());
|
||||
|
||||
world
|
||||
.build()
|
||||
// cube
|
||||
|
@ -53,10 +64,7 @@ fn setup(world: &mut World, resources: &mut Resources) {
|
|||
Anchors::new(0.0, 0.0, 0.0, 1.0),
|
||||
Margins::new(10.0, 200.0, 10.0, 10.0),
|
||||
),
|
||||
rect: Rect {
|
||||
color: Color::rgb(0.02, 0.02, 0.02),
|
||||
..Default::default()
|
||||
},
|
||||
material: color_materials.add(Color::rgb(0.02, 0.02, 0.02).into()),
|
||||
..Default::default()
|
||||
})
|
||||
// top right anchor with vertical fill
|
||||
|
@ -66,10 +74,7 @@ fn setup(world: &mut World, resources: &mut Resources) {
|
|||
Anchors::new(1.0, 1.0, 0.0, 1.0),
|
||||
Margins::new(10.0, 100.0, 50.0, 100.0),
|
||||
),
|
||||
rect: Rect {
|
||||
color: Color::rgb(0.02, 0.02, 0.02),
|
||||
..Default::default()
|
||||
},
|
||||
material: color_materials.add(Color::rgb(0.02, 0.02, 0.02).into()),
|
||||
..Default::default()
|
||||
})
|
||||
// render order test: reddest in the back, whitest in the front
|
||||
|
@ -79,10 +84,7 @@ fn setup(world: &mut World, resources: &mut Resources) {
|
|||
Anchors::new(0.5, 0.5, 0.5, 0.5),
|
||||
Margins::new(0.0, 100.0, 0.0, 100.0),
|
||||
),
|
||||
rect: Rect {
|
||||
color: Color::rgb(1.0, 0.00, 0.0),
|
||||
..Default::default()
|
||||
},
|
||||
material: color_materials.add(Color::rgb(1.0, 0.0, 0.0).into()),
|
||||
..Default::default()
|
||||
})
|
||||
.add_entity(UiEntity {
|
||||
|
@ -91,10 +93,7 @@ fn setup(world: &mut World, resources: &mut Resources) {
|
|||
Anchors::new(0.5, 0.5, 0.5, 0.5),
|
||||
Margins::new(0.0, 100.0, 0.0, 100.0),
|
||||
),
|
||||
rect: Rect {
|
||||
color: Color::rgb(1.0, 0.3, 0.3),
|
||||
..Default::default()
|
||||
},
|
||||
material: color_materials.add(Color::rgb(1.0, 0.3, 0.3).into()),
|
||||
..Default::default()
|
||||
})
|
||||
.add_entity(UiEntity {
|
||||
|
@ -103,10 +102,7 @@ fn setup(world: &mut World, resources: &mut Resources) {
|
|||
Anchors::new(0.5, 0.5, 0.5, 0.5),
|
||||
Margins::new(0.0, 100.0, 0.0, 100.0),
|
||||
),
|
||||
rect: Rect {
|
||||
color: Color::rgb(1.0, 0.5, 0.5),
|
||||
..Default::default()
|
||||
},
|
||||
material: color_materials.add(Color::rgb(1.0, 0.5, 0.5).into()),
|
||||
..Default::default()
|
||||
})
|
||||
.add_entity(UiEntity {
|
||||
|
@ -115,10 +111,7 @@ fn setup(world: &mut World, resources: &mut Resources) {
|
|||
Anchors::new(0.5, 0.5, 0.5, 0.5),
|
||||
Margins::new(0.0, 100.0, 0.0, 100.0),
|
||||
),
|
||||
rect: Rect {
|
||||
color: Color::rgb(1.0, 0.7, 0.7),
|
||||
..Default::default()
|
||||
},
|
||||
material: color_materials.add(Color::rgb(1.0, 0.7, 0.7).into()),
|
||||
..Default::default()
|
||||
})
|
||||
// parenting
|
||||
|
@ -128,10 +121,7 @@ fn setup(world: &mut World, resources: &mut Resources) {
|
|||
Anchors::new(0.0, 0.0, 0.0, 0.0),
|
||||
Margins::new(0.0, 200.0, 0.0, 200.0),
|
||||
),
|
||||
rect: Rect {
|
||||
color: Color::rgb(0.1, 0.1, 1.0),
|
||||
..Default::default()
|
||||
},
|
||||
material: color_materials.add(Color::rgb(0.1, 0.1, 1.0).into()),
|
||||
..Default::default()
|
||||
})
|
||||
.add_children(|builder| {
|
||||
|
@ -141,10 +131,7 @@ fn setup(world: &mut World, resources: &mut Resources) {
|
|||
Anchors::new(0.0, 1.0, 0.0, 1.0),
|
||||
Margins::new(20.0, 20.0, 20.0, 20.0),
|
||||
),
|
||||
rect: Rect {
|
||||
color: Color::rgb(0.6, 0.6, 1.0),
|
||||
..Default::default()
|
||||
},
|
||||
material: blue_material_handle,
|
||||
..Default::default()
|
||||
});
|
||||
})
|
||||
|
@ -155,10 +142,17 @@ fn setup(world: &mut World, resources: &mut Resources) {
|
|||
Anchors::new(0.5, 0.5, 0.5, 0.5),
|
||||
Margins::new(0.0, 100.0, 0.0, 100.0),
|
||||
),
|
||||
rect: Rect {
|
||||
color: Color::rgba(1.0, 0.9, 0.9, 0.4),
|
||||
..Default::default()
|
||||
},
|
||||
material: color_materials.add(Color::rgba(1.0, 0.9, 0.9, 0.4).into()),
|
||||
..Default::default()
|
||||
})
|
||||
// texture
|
||||
.add_entity(UiEntity {
|
||||
node: Node::new(
|
||||
math::vec2(400.0, 100.0),
|
||||
Anchors::new(0.0, 0.0, 0.0, 0.0),
|
||||
Margins::new(0.0, 500.0, 0.0, 500.0 * aspect),
|
||||
),
|
||||
material: color_materials.add(ColorMaterial::texture(texture_handle)),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use bevy::prelude::*;
|
||||
use bevy_ui::Rect;
|
||||
use bevy_ui::{ColorMaterial, Rect};
|
||||
|
||||
fn main() {
|
||||
App::build()
|
||||
.add_default_plugins()
|
||||
.add_startup_system(setup)
|
||||
.add_system(move_system.system())
|
||||
.add_system(placement_system.system())
|
||||
.add_plugin(DiagnosticsPlugin {
|
||||
print_diagnostics: true,
|
||||
..Default::default()
|
||||
|
@ -13,8 +13,14 @@ fn main() {
|
|||
.run();
|
||||
}
|
||||
|
||||
fn move_system(time: Resource<Time>, mut node: RefMut<Node>, rect: Ref<Rect>) {
|
||||
if rect.color.r > 0.2 {
|
||||
fn placement_system(
|
||||
time: Resource<Time>,
|
||||
materials: Resource<AssetStorage<ColorMaterial>>,
|
||||
mut node: RefMut<Node>,
|
||||
material_handle: Ref<Handle<ColorMaterial>>,
|
||||
) {
|
||||
let material = materials.get(&material_handle).unwrap();
|
||||
if material.color.r > 0.2 {
|
||||
node.position += Vec2::new(0.1 * time.delta_seconds, 0.0);
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +44,7 @@ fn setup(world: &mut World, _resources: &mut Resources) {
|
|||
Margins::new(0.0, 100.0, 0.0, 100.0),
|
||||
),
|
||||
rect: Rect {
|
||||
color: Color::rgb(0.0 + i as f32 / count as f32, 0.1, 0.1),
|
||||
// color: Color::rgb(0.0 + i as f32 / count as f32, 0.1, 0.1),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
|
|
|
@ -32,7 +32,7 @@ pub use crate::render::{
|
|||
#[cfg(feature = "transform")]
|
||||
pub use crate::transform::prelude::*;
|
||||
#[cfg(feature = "ui")]
|
||||
pub use crate::ui::{entity::*, Anchors, Margins, Node};
|
||||
pub use crate::ui::{entity::*, Anchors, Margins, Node, ColorMaterial};
|
||||
#[cfg(feature = "window")]
|
||||
pub use crate::window::{Window, WindowDescriptor, WindowPlugin, Windows};
|
||||
pub use crate::{
|
||||
|
|
Loading…
Reference in a new issue