Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update ui_material example to be a slider instead #14031

Merged
merged 5 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 0 additions & 20 deletions assets/shaders/circle_shader.wgsl

This file was deleted.

18 changes: 18 additions & 0 deletions assets/shaders/custom_ui_material.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// This shader draws a circle with a given input color
#import bevy_ui::ui_vertex_output::UiVertexOutput

@group(1) @binding(0) var<uniform> color: vec4<f32>;
@group(1) @binding(1) var<uniform> slider: f32;
@group(1) @binding(2) var material_color_texture: texture_2d<f32>;
@group(1) @binding(3) var material_color_sampler: sampler;


@fragment
fn fragment(in: UiVertexOutput) -> @location(0) vec4<f32> {
if in.uv.x < slider {
let output_color = textureSample(material_color_texture, material_color_sampler, in.uv) * color;
return output_color;
} else {
return vec4(0.0);
}
}
53 changes: 40 additions & 13 deletions examples/ui/ui_material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,22 @@ use bevy::reflect::TypePath;
use bevy::render::render_resource::*;

/// This example uses a shader source file from the assets subdirectory
const SHADER_ASSET_PATH: &str = "shaders/circle_shader.wgsl";
const SHADER_ASSET_PATH: &str = "shaders/custom_ui_material.wgsl";

fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(UiMaterialPlugin::<CustomUiMaterial>::default())
.add_systems(Startup, setup)
.add_systems(Update, update)
.add_systems(Update, animate)
.run();
}

fn update(time: Res<Time>, mut ui_materials: ResMut<Assets<CustomUiMaterial>>) {
for (_, material) in ui_materials.iter_mut() {
// rainbow color effect
let new_color = Color::hsl((time.elapsed_seconds() * 60.0) % 360.0, 1., 0.5);
material.color = LinearRgba::from(new_color).to_f32_array().into();
}
}

fn setup(mut commands: Commands, mut ui_materials: ResMut<Assets<CustomUiMaterial>>) {
fn setup(
mut commands: Commands,
mut ui_materials: ResMut<Assets<CustomUiMaterial>>,
asset_server: Res<AssetServer>,
) {
// Camera so we can see UI
commands.spawn(Camera2dBundle::default());

Expand All @@ -40,15 +36,18 @@ fn setup(mut commands: Commands, mut ui_materials: ResMut<Assets<CustomUiMateria
..default()
})
.with_children(|parent| {
let banner_scale_factor = 0.5;
parent.spawn(MaterialNodeBundle {
style: Style {
position_type: PositionType::Absolute,
width: Val::Px(250.0),
height: Val::Px(250.0),
width: Val::Px(905.0 * banner_scale_factor),
height: Val::Px(363.0 * banner_scale_factor),
..default()
},
material: ui_materials.add(CustomUiMaterial {
color: LinearRgba::WHITE.to_f32_array().into(),
slider: 0.5,
color_texture: asset_server.load("branding/banner.png"),
}),
..default()
});
Expand All @@ -57,12 +56,40 @@ fn setup(mut commands: Commands, mut ui_materials: ResMut<Assets<CustomUiMateria

#[derive(AsBindGroup, Asset, TypePath, Debug, Clone)]
struct CustomUiMaterial {
/// Color multiplied with the image
#[uniform(0)]
color: Vec4,
/// Represents how much of the image is visible
/// Goes from 0 to 1
#[uniform(1)]
slider: f32,
/// Image used to represent the slider
#[texture(2)]
#[sampler(3)]
color_texture: Handle<Image>,
}

impl UiMaterial for CustomUiMaterial {
fn fragment_shader() -> ShaderRef {
SHADER_ASSET_PATH.into()
}
}

// Fills the slider slowly over 2 seconds and resets it
// Also updates the color of the image to a rainbow color
fn animate(
mut materials: ResMut<Assets<CustomUiMaterial>>,
q: Query<&Handle<CustomUiMaterial>>,
time: Res<Time>,
) {
let duration = 2.0;
for handle in &q {
if let Some(material) = materials.get_mut(handle) {
// rainbow color effect
let new_color = Color::hsl((time.elapsed_seconds() * 60.0) % 360.0, 1., 0.5);
material.color = LinearRgba::from(new_color).to_f32_array().into();
material.slider =
((time.elapsed_seconds() % (duration * 2.0)) - duration).abs() / duration;
}
}
}