Skip to content
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
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ This release supports Bevy version 0.14 and has an [MSRV][] of 1.80.
### Changed

- bevy_vello now uses Bevy 0.15
- `VelloAsset` assets have been separated into `VelloSvg` and `VelloLottie`
- `VelloAssetBundle` has been separated into `VelloSvgBundle` and `VelloLottieBundle`
- `Handle<VelloAsset>` has been separated into `VelloSvgHandle` and `VelloLottieHandle`
- `VelloAssetAnchor` has been separated into `VelloSvgAnchor` and `VelloLottieAnchor`
- The license on bevy_vello no longer includes OFL 1.1

### Fixed
Expand Down Expand Up @@ -265,4 +269,4 @@ This release supports Bevy version 0.13 and has an [MSRV][] of 1.77.
[0.1.1]: https://github.com/linebender/bevy_vello/compare/v0.1.0...v0.1.1
[0.1.0]: https://github.com/linebender/bevy_vello/releases/tag/v0.1.0

[MSRV]: README.md#minimum-supported-rust-version-msrv
[MSRV]: README.md#minimum-supported-rust-version-msrv
21 changes: 8 additions & 13 deletions examples/demo/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,8 @@ fn main() {
fn setup_vector_graphics(mut commands: Commands, asset_server: ResMut<AssetServer>) {
commands.spawn((Camera2d, bevy_pancam::PanCam::default()));
commands
.spawn(VelloAssetBundle {
asset: VelloAssetHandle(
asset_server.load::<VelloAsset>("embedded://demo/assets/calendar.json"),
),
.spawn(VelloLottieBundle {
asset: VelloLottieHandle(asset_server.load("embedded://demo/assets/calendar.json")),
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 0.0))
.with_scale(Vec3::splat(20.0)),
debug_visualizations: DebugVisualizations::Visible,
Expand Down Expand Up @@ -74,19 +72,16 @@ fn setup_vector_graphics(mut commands: Commands, asset_server: ResMut<AssetServe
}

fn print_metadata(
mut asset_ev: EventReader<AssetEvent<VelloAsset>>,
assets: Res<Assets<VelloAsset>>,
mut asset_ev: EventReader<AssetEvent<VelloLottie>>,
assets: Res<Assets<VelloLottie>>,
) {
for ev in asset_ev.read() {
if let AssetEvent::LoadedWithDependencies { id } = ev {
let asset = assets.get(*id).unwrap();
#[allow(irrefutable_let_patterns)]
if let VectorFile::Lottie(composition) = &asset.file {
info!(
"Animated asset loaded. Layers:\n{:#?}",
composition.as_ref().get_layers().collect::<Vec<_>>()
);
}
info!(
"Animated asset loaded. Layers:\n{:#?}",
asset.composition.as_ref().get_layers().collect::<Vec<_>>()
);
}
}
}
12 changes: 4 additions & 8 deletions examples/demo/src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,17 @@ pub fn controls_ui(
&mut Playhead,
&mut PlaybackOptions,
&mut Theme,
&VelloAssetHandle,
&VelloLottieHandle,
)>,
assets: Res<Assets<VelloAsset>>,
assets: Res<Assets<VelloLottie>>,
) {
let Ok((mut player, mut playhead, mut options, mut theme, handle)) = player.get_single_mut()
else {
return;
};

let asset = assets.get(handle.id()).unwrap();
#[allow(irrefutable_let_patterns)]
let VectorFile::Lottie(composition) = &asset.file
else {
return;
};
let composition = asset.composition.as_ref();

let window = egui::Window::new("Controls")
.resizable(false)
Expand Down Expand Up @@ -250,7 +246,7 @@ pub fn controls_ui(
});

ui.heading("Theme");
for layer in composition.as_ref().get_layers() {
for layer in composition.get_layers() {
let color = theme.get_mut(layer).cloned().unwrap_or_default();
let color = color.to_srgba().to_u8_array();
let mut color32 =
Expand Down
39 changes: 29 additions & 10 deletions examples/drag_n_drop/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use bevy::{
prelude::*,
};
use bevy_vello::{prelude::*, VelloPlugin};
use std::ffi::OsStr;

fn main() {
let mut app = App::new();
Expand All @@ -19,10 +20,9 @@ fn main() {

fn setup_vector_graphics(mut commands: Commands, asset_server: ResMut<AssetServer>) {
commands.spawn(Camera2d);
commands.spawn(VelloAssetBundle {
asset: VelloAssetHandle(
asset_server.load::<VelloAsset>("embedded://drag_n_drop/assets/fountain.svg"),
),

commands.spawn(VelloSvgBundle {
asset: VelloSvgHandle(asset_server.load("embedded://drag_n_drop/assets/fountain.svg")),
debug_visualizations: DebugVisualizations::Visible,
transform: Transform::from_scale(Vec3::splat(5.0)),
..default()
Expand All @@ -32,18 +32,37 @@ fn setup_vector_graphics(mut commands: Commands, asset_server: ResMut<AssetServe
/// Drag and drop any SVG or Lottie JSON asset into the window and change the
/// displayed asset
fn drag_and_drop(
mut query: Query<&mut VelloAssetHandle>,
mut commands: Commands,
query_lottie: Option<Single<Entity, With<VelloLottieHandle>>>,
query_svg: Option<Single<Entity, With<VelloSvgHandle>>>,
asset_server: ResMut<AssetServer>,
mut dnd_evr: EventReader<FileDragAndDrop>,
) {
let Ok(mut asset) = query.get_single_mut() else {
return;
};
for ev in dnd_evr.read() {
if let Some(ref svg) = query_svg {
commands.entity(**svg).despawn();
}
if let Some(ref lottie) = query_lottie {
commands.entity(**lottie).despawn();
}
let FileDragAndDrop::DroppedFile { path_buf, .. } = ev else {
continue;
};
let new_handle = VelloAssetHandle(asset_server.load(path_buf.clone()));
*asset = new_handle;
let Some(ext) = path_buf.extension() else {
continue;
};
let svg_ext = OsStr::new("svg");
let lottie_ext = OsStr::new("json");
if ext == svg_ext {
commands.spawn(VelloSvgBundle {
asset: VelloSvgHandle(asset_server.load(path_buf.clone())),
..default()
});
} else if ext == lottie_ext {
commands.spawn(VelloLottieBundle {
asset: VelloLottieHandle(asset_server.load(path_buf.clone())),
..default()
});
}
}
}
4 changes: 2 additions & 2 deletions examples/lottie/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ fn load_lottie(mut commands: Commands, asset_server: ResMut<AssetServer>) {
commands.spawn(Camera2d);

// Yes, it's this simple.
commands.spawn(VelloAssetBundle {
asset: VelloAssetHandle(asset_server.load("embedded://lottie/assets/Tiger.json")),
commands.spawn(VelloLottieBundle {
asset: VelloLottieHandle(asset_server.load("embedded://lottie/assets/Tiger.json")),
debug_visualizations: DebugVisualizations::Visible,
transform: Transform::from_scale(Vec3::splat(0.5)),
..default()
Expand Down
4 changes: 2 additions & 2 deletions examples/svg/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ fn load_svg(mut commands: Commands, asset_server: ResMut<AssetServer>) {
commands.spawn(Camera2d);

// Yes, it's this simple.
commands.spawn(VelloAssetBundle {
asset: VelloAssetHandle(asset_server.load("embedded://svg/assets/fountain.svg")),
commands.spawn(VelloSvgBundle {
asset: VelloSvgHandle(asset_server.load("embedded://svg/assets/fountain.svg")),
debug_visualizations: DebugVisualizations::Visible,
transform: Transform::from_scale(Vec3::splat(5.0)),
..default()
Expand Down
92 changes: 80 additions & 12 deletions src/debug.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
//! Logic for rendering debug visualizations
use crate::{
text::VelloTextAnchor, CoordinateSpace, VelloAsset, VelloAssetAnchor, VelloAssetHandle,
VelloFont, VelloTextSection,
};
use crate::prelude::*;
use bevy::{color::palettes::css, math::Vec3Swizzles, prelude::*};

const RED_X_SIZE: f32 = 8.0;
Expand All @@ -11,7 +8,15 @@ pub struct DebugVisualizationsPlugin;

impl Plugin for DebugVisualizationsPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Update, (render_asset_debug, render_text_debug));
// TODO: Would be great if we could render scene debug, but Vello doesn't tell us the AABB or BB.

app.add_systems(Update, render_text_debug);

#[cfg(feature = "svg")]
app.add_systems(Update, render_svg_debug);

#[cfg(feature = "lottie")]
app.add_systems(Update, render_lottie_debug);
}
}

Expand All @@ -23,19 +28,81 @@ pub enum DebugVisualizations {
Visible,
}

/// A system to render debug visualizations for `VelloAsset`.
fn render_asset_debug(
#[cfg(feature = "svg")]
/// A system to render debug visualizations for SVGs.
fn render_svg_debug(
query_vectors: Query<
(
&VelloSvgHandle,
&VelloSvgAnchor,
&GlobalTransform,
&CoordinateSpace,
&DebugVisualizations,
),
Without<Node>,
>,
assets: Res<Assets<VelloSvg>>,
query_cam: Query<(&Camera, &GlobalTransform, &OrthographicProjection), With<Camera2d>>,
mut gizmos: Gizmos,
) {
let Ok((camera, view, projection)) = query_cam.get_single() else {
return;
};

// Show vectors
for (asset, asset_anchor, gtransform, space, _) in query_vectors
.iter()
.filter(|(_, _, _, _, d)| **d == DebugVisualizations::Visible)
{
if let Some(asset) = assets.get(asset.id()) {
match space {
CoordinateSpace::WorldSpace => {
// Origin
let origin = gtransform.translation().xy();
draw_origin(&mut gizmos, projection, origin);
// Bounding box
let gtransform = &asset_anchor.compute(asset.width, asset.height, gtransform);
let rect_center = gtransform.translation().xy();
let rect = asset.bb_in_world_space(gtransform);
draw_bounding_box(&mut gizmos, rect_center, rect.size());
}
CoordinateSpace::ScreenSpace => {
// Origin
let origin = gtransform.translation().xy();
let Ok(origin) = camera.viewport_to_world_2d(view, origin) else {
continue;
};
draw_origin(&mut gizmos, projection, origin);
// Bounding box
let gtransform = &asset_anchor.compute(asset.width, asset.height, gtransform);
let rect_center = gtransform.translation().xy();
let Ok(rect_center) = camera.viewport_to_world_2d(view, rect_center) else {
continue;
};
let Some(rect) = asset.bb_in_screen_space(gtransform, camera, view) else {
continue;
};
draw_bounding_box(&mut gizmos, rect_center, rect.size());
}
}
}
}
}

#[cfg(feature = "lottie")]
/// A system to render debug visualizations for SVGs.
fn render_lottie_debug(
query_vectors: Query<
(
&VelloAssetHandle,
&VelloAssetAnchor,
&VelloLottieHandle,
&VelloLottieAnchor,
&GlobalTransform,
&CoordinateSpace,
&DebugVisualizations,
),
Without<Node>,
>,
assets: Res<Assets<VelloAsset>>,
assets: Res<Assets<VelloLottie>>,
query_cam: Query<(&Camera, &GlobalTransform, &OrthographicProjection), With<Camera2d>>,
mut gizmos: Gizmos,
) {
Expand All @@ -55,7 +122,7 @@ fn render_asset_debug(
let origin = gtransform.translation().xy();
draw_origin(&mut gizmos, projection, origin);
// Bounding box
let gtransform = &asset_anchor.compute(asset, gtransform);
let gtransform = &asset_anchor.compute(asset.width, asset.height, gtransform);
let rect_center = gtransform.translation().xy();
let rect = asset.bb_in_world_space(gtransform);
draw_bounding_box(&mut gizmos, rect_center, rect.size());
Expand All @@ -68,7 +135,7 @@ fn render_asset_debug(
};
draw_origin(&mut gizmos, projection, origin);
// Bounding box
let gtransform = &asset_anchor.compute(asset, gtransform);
let gtransform = &asset_anchor.compute(asset.width, asset.height, gtransform);
let rect_center = gtransform.translation().xy();
let Ok(rect_center) = camera.viewport_to_world_2d(view, rect_center) else {
continue;
Expand Down Expand Up @@ -222,6 +289,7 @@ fn draw_origin(gizmos: &mut Gizmos, projection: &OrthographicProjection, origin:
gizmos.line_2d(from, to, css::RED);
}

#[cfg(any(feature = "svg", feature = "lottie"))]
/// A helper method to draw the bounding box
fn draw_bounding_box(gizmos: &mut Gizmos, position: Vec2, size: Vec2) {
gizmos.rect_2d(
Expand Down
Loading