Skip to content

Commit

Permalink
feat: avoid composition clones
Browse files Browse the repository at this point in the history
  • Loading branch information
simbleau committed Jan 19, 2024
1 parent 8ea3644 commit 70bec16
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 44 deletions.
15 changes: 12 additions & 3 deletions demo/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
# Usage

```shell
cargo run -p demo
```
Native:

```shell
cargo run -p demo
```

WASM:

```shell
cargo install trunk
trunk serve
```

We provide some example assets in [assets].

Expand Down
51 changes: 33 additions & 18 deletions demo/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,30 @@ use bevy_vello::{
fn main() {
App::new()
.insert_resource(AssetMetaCheck::Never)
.add_plugins(DefaultPlugins.set(AssetPlugin { ..default() }))
.add_plugins(DefaultPlugins)
.add_plugins(VelloPlugin)
.add_systems(Startup, setup_vector_graphics)
.add_systems(Update, (camera_system, drag_and_drop, print_metadata))
.add_systems(
Update,
(
camera_system,
drag_and_drop,
print_metadata,
dynamic_color_remapping,
),
)
.run();
}

fn setup_vector_graphics(mut commands: Commands, asset_server: ResMut<AssetServer>) {
commands.spawn(Camera2dBundle::default());
commands
.spawn(VelloVectorBundle {
origin: bevy_vello::Origin::Center,
// Can only load *.json (Lottie animations) and *.svg (static vector graphics)
vector: asset_server.load("../assets/squid.json"),
debug_visualizations: DebugVisualizations::Visible,
..default()
})
// Remap the sucker colors to green!
.insert({
const SUCKERS: Color = Color::rgba(0.0, 1.0, 0.0, 1.0);
ColorPaletteSwap::empty()
.add("suckers ", SUCKERS)
.add("suckers Flip", SUCKERS)
});

commands.spawn(VelloVectorBundle {
origin: bevy_vello::Origin::Center,
// Can only load *.json (Lottie animations) and *.svg (static vector graphics)
vector: asset_server.load("../assets/squid.json"),
debug_visualizations: DebugVisualizations::Visible,
..default()
});
commands.spawn(VelloTextBundle {
font: asset_server.load("../assets/Rubik-Medium.vttf"),
text: VelloText {
Expand All @@ -42,6 +41,22 @@ fn setup_vector_graphics(mut commands: Commands, asset_server: ResMut<AssetServe
});
}

fn dynamic_color_remapping(
mut commands: Commands,
mut q: Query<Entity, With<Handle<VelloVector>>>,
time: Res<Time>,
) {
for e in q.iter_mut() {
commands.entity(e).insert({
const CYCLE_SECONDS: f32 = 3.0;
let color = Color::hsl(time.elapsed_seconds() % CYCLE_SECONDS * 360.0, 1.0, 0.5);
ColorPaletteSwap::empty()
.add("suckers ", color)
.add("suckers Flip", color)
});
}
}

fn print_metadata(
mut asset_ev: EventReader<AssetEvent<VelloVector>>,
assets: Res<Assets<VelloVector>>,
Expand Down
5 changes: 4 additions & 1 deletion src/assets/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ pub fn load_lottie_from_bytes(bytes: &[u8]) -> Result<VelloVector, VectorLoaderE
let height = composition.height as f32;

let vello_vector = VelloVector {
data: Vector::Animated(composition),
data: Vector::Animated {
original: Arc::new(composition),
dirty: None,
},
local_transform_bottom_center: compute_local_transform(width, height),
local_transform_center: compute_local_transform_center(width, height),
width,
Expand Down
11 changes: 8 additions & 3 deletions src/assets/vector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ use vello::SceneFragment;
#[derive(Clone)]
pub enum Vector {
Static(Arc<SceneFragment>),
Animated(vellottie::Composition),
Animated {
/// The original copy
original: Arc<vellottie::Composition>,
/// A modified copy, used for color swapping
dirty: Option<vellottie::Composition>,
},
}

#[derive(Asset, TypePath, Clone)]
Expand Down Expand Up @@ -84,9 +89,9 @@ impl VelloVector {
/// Gets the lottie metadata (if vector is a lottie), an object used for inspecting
/// this vector's layers and shapes
pub fn metadata(&self) -> Option<Metadata> {
if let Vector::Animated(composition) = &self.data {
if let Vector::Animated { original, .. } = &self.data {
Some(Metadata {
composition: composition.clone(),
composition: original.clone(),
})
} else {
None
Expand Down
15 changes: 2 additions & 13 deletions src/metadata.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use std::sync::Arc;
use vellottie::Composition;

/// Metadata used for introspection and color swapping.
pub struct Metadata {
pub(crate) composition: Composition,
pub(crate) composition: Arc<Composition>,
}

impl Metadata {
Expand All @@ -13,16 +14,4 @@ impl Metadata {
.map(|l| l.name.clone())
.collect()
}

pub fn get_layer_shapes(&self, layer: &str) -> Option<usize> {
match self.composition.layers.iter().find(|l| l.name.eq(&layer)) {
Some(layer) => {
let vellottie::runtime::model::Content::Shape(ref shapes) = layer.content else {
return None;
};
Some(shapes.iter().len())
}
None => None,
}
}
}
18 changes: 13 additions & 5 deletions src/renderer/prepare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,16 +169,23 @@ pub fn prepare_vector_composition_edits(mut render_vectors: Query<&mut Extracted
..
} = render_vector.as_mut();

// Continue if there are no colors
let Some(ColorPaletteSwap { ref colors }) = color_swaps else {
// Perform recolors!
// TODO: Recoloring SVGs
let Vector::Animated {
ref original,
ref mut dirty,
} = render_data.data
else {
continue 'vectors;
};

// Perform recolors!
// TODO: Recoloring SVGs
let Vector::Animated(ref mut composition) = render_data.data else {
// Continue if there are no colors
let Some(ColorPaletteSwap { ref colors }) = color_swaps else {
dirty.take();
continue 'vectors;
};

let mut composition = vellottie::Composition::clone(original);
'layers: for layer in composition.layers.iter_mut() {
// Continue if this layer doesn't have a color swap
let Some(target_color) = colors.get(&layer.name) else {
Expand Down Expand Up @@ -217,6 +224,7 @@ pub fn prepare_vector_composition_edits(mut render_vectors: Query<&mut Extracted
}
}
}
dirty.replace(composition);
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/renderer/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ pub fn render_scene(
Vector::Static(fragment) => {
builder.append(fragment, Some(affine));
}
Vector::Animated(composition) => {
Vector::Animated { original, dirty } => {
let composition = dirty.as_ref().unwrap_or(original);
velato_renderer.0.render(
composition,
time.elapsed_seconds(),
Expand Down

0 comments on commit 70bec16

Please sign in to comment.