Skip to content

Commit

Permalink
feat: vanquished the demons
Browse files Browse the repository at this point in the history
  • Loading branch information
simbleau committed Jan 24, 2024
1 parent 512d16b commit 79a2f9e
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 104 deletions.
12 changes: 5 additions & 7 deletions demo/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use bevy::{asset::AssetMetaCheck, prelude::*};
use bevy_egui::EguiPlugin;
use bevy_vello::{
debug::DebugVisualizations, AnimationDirection, AnimationLoopBehavior, AnimationPlayMode,
AnimationState, AnimationTransition, ColorPaletteSwap, LottiePlayer, PlaybackSettings,
VelloAsset, VelloAssetBundle, VelloPlugin, VelloText, VelloTextBundle,
debug::DebugVisualizations, AnimationDirection, AnimationLoopBehavior, AnimationState,
AnimationTransition, ColorPaletteSwap, LottiePlayer, PlaybackSettings, VelloAsset,
VelloAssetBundle, VelloPlugin, VelloText, VelloTextBundle,
};

fn main() {
Expand Down Expand Up @@ -93,17 +93,15 @@ fn setup_vector_graphics(mut commands: Commands, asset_server: ResMut<AssetServe
direction: AnimationDirection::Normal,
looping: AnimationLoopBehavior::None,
..default()
})
.reset_playhead_on_transition(false),
}),
)
.with_state(
AnimationState::new("rev")
.with_playback_settings(PlaybackSettings {
direction: AnimationDirection::Reverse,
..default()
})
.with_transition(AnimationTransition::OnComplete { state: "stopped" })
.reset_playhead_on_transition(true),
.with_transition(AnimationTransition::OnComplete { state: "stopped" }),
),
);
}
Expand Down
92 changes: 69 additions & 23 deletions src/animation_controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ use crate::{
playback_settings::{AnimationLoopBehavior, AnimationPlayMode},
AnimationDirection, PlaybackSettings, VelloAsset,
};
use bevy::{
prelude::*,
render::{Render, RenderSet},
utils::hashbrown::HashMap,
};
use bevy::{prelude::*, utils::hashbrown::HashMap};
use vello_svg::usvg::strict_num::Ulps;
use vellottie::Composition;

#[derive(Component, Default, Debug)]
pub struct LottiePlayer {
Expand Down Expand Up @@ -135,7 +133,7 @@ impl AnimationState {
asset: Default::default(),
playback_settings: None,
transitions: vec![],
reset_playhead_on_transition: true,
reset_playhead_on_transition: false,
}
}

Expand Down Expand Up @@ -168,8 +166,8 @@ impl Plugin for AnimationControllerPlugin {
Update,
(
systems::advance_playheads,
systems::set_state,
systems::run_transitions,
systems::set_state,
)
.chain(),
);
Expand All @@ -178,7 +176,10 @@ impl Plugin for AnimationControllerPlugin {

pub mod systems {
use super::{AnimationTransition, LottiePlayer};
use crate::{PlaybackSettings, Vector, VelloAsset};
use crate::{
animation_controller::calculate_playhead, AnimationDirection, PlaybackSettings, Vector,
VelloAsset,
};
use bevy::{prelude::*, utils::Instant};

/// Advance all the playheads in the scene
Expand Down Expand Up @@ -206,10 +207,9 @@ pub mod systems {
let VelloAsset {
data:
Vector::Lottie {
original,
colored: _, // Set on render
composition,
first_frame, // Set on render
playhead,
rendered_frames,
},
..
} = asset
Expand All @@ -221,18 +221,23 @@ pub mod systems {
first_frame.replace(Instant::now());
}

// Move playhead
let elapsed_frames = dt * playback_settings.speed * original.frame_rate;
*playhead += elapsed_frames;
// Move frames to control playhead
let elapsed_frames = dt * playback_settings.speed * composition.frame_rate;
*rendered_frames += elapsed_frames;
}
}

pub fn set_state(
mut commands: Commands,
mut query_sm: Query<(Entity, &mut LottiePlayer, &mut Handle<VelloAsset>)>,
mut query_sm: Query<(
Entity,
&mut LottiePlayer,
Option<&PlaybackSettings>,
&mut Handle<VelloAsset>,
)>,
mut assets: ResMut<Assets<VelloAsset>>,
) {
for (entity, mut controller, mut cur_handle) in query_sm.iter_mut() {
for (entity, mut controller, current_settings, mut cur_handle) in query_sm.iter_mut() {
let Some(next_state) = controller.pending_next_state.take() else {
continue;
};
Expand All @@ -259,14 +264,30 @@ pub mod systems {
first_frame.take();
}
Vector::Lottie {
original,
colored: _,
composition,
first_frame,
playhead,
rendered_frames,
} => {
first_frame.take();
if controller.state().reset_playhead_on_transition {
*playhead = original.frames.start;
*rendered_frames = 0.0;
} else {
// Reset loops
let playhead = calculate_playhead(
*rendered_frames,
composition,
&current_settings.cloned().unwrap_or_default(),
);
// Need to reset to the correct frame
if target_state
.playback_settings
.as_ref()
.is_some_and(|pb| pb.direction == AnimationDirection::Reverse)
{
*rendered_frames = composition.frames.end - playhead;
} else {
*rendered_frames %= composition.frames.end - composition.frames.start;
}
}
}
}
Expand Down Expand Up @@ -342,10 +363,10 @@ pub mod systems {
match &current_asset.data {
crate::Vector::Svg {..} => warn!("invalid state: '{}', `OnComplete` is only valid for Lottie files. Use `OnAfter` for SVG.", controller.state().id),
crate::Vector::Lottie {
original: composition,
playhead, ..
composition,
rendered_frames, ..
} => {
if *playhead >= composition.frames.end {
if *rendered_frames >= composition.frames.end - composition.frames.start {
controller.pending_next_state = Some(state);
break;
}
Expand Down Expand Up @@ -388,3 +409,28 @@ pub mod systems {
}
}
}

pub(crate) fn calculate_playhead(
rendered_frames: f32,
composition: &Composition,
playback_settings: &PlaybackSettings,
) -> f32 {
let start_frame = playback_settings
.segments
.start
.max(composition.frames.start);
let end_frame = playback_settings.segments.end.min(composition.frames.end);
let length = end_frame - start_frame;

let frame = match playback_settings.looping {
crate::AnimationLoopBehavior::None => rendered_frames.min(length),
crate::AnimationLoopBehavior::Amount(_) => todo!(),
crate::AnimationLoopBehavior::Loop => rendered_frames % length,
};
let playhead = match playback_settings.direction {
AnimationDirection::Normal => (start_frame + frame).min(end_frame.prev()),
AnimationDirection::Reverse => (end_frame - frame).min(end_frame.prev()),
};
error!("rendered_frames: {rendered_frames}, frame: {frame}, playhead: {playhead}");
playhead
}
5 changes: 2 additions & 3 deletions src/assets/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,8 @@ pub fn load_lottie_from_bytes(bytes: &[u8]) -> Result<VelloAsset, VectorLoaderEr

let vello_vector = VelloAsset {
data: Vector::Lottie {
playhead: composition.frames.start,
original: Arc::new(composition),
colored: None,
composition: Arc::new(composition),
rendered_frames: 0.0,
first_frame: None,
},
local_transform_bottom_center: compute_local_transform(width, height),
Expand Down
10 changes: 4 additions & 6 deletions src/assets/vector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,11 @@ pub enum Vector {
},
Lottie {
/// The original image encoding
original: Arc<vellottie::Composition>,
/// A modified copy, used for color swapping
colored: Option<vellottie::Composition>,
composition: Arc<vellottie::Composition>,
/// The time we started rendering this asset
first_frame: Option<Instant>,
/// The last frame rendered
playhead: f32,
rendered_frames: f32,
},
}

Expand Down Expand Up @@ -99,9 +97,9 @@ impl VelloAsset {
/// 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::Lottie { original, .. } = &self.data {
if let Vector::Lottie { composition, .. } = &self.data {
Some(Metadata {
composition: original.clone(),
composition: composition.clone(),
})
} else {
None
Expand Down
1 change: 0 additions & 1 deletion src/renderer/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ impl Plugin for VelloRenderPlugin {
Render,
(
prepare::prepare_vector_affines,
prepare::prepare_recoloring,
prepare::prepare_text_affines,
)
.in_set(RenderSet::Prepare),
Expand Down
31 changes: 1 addition & 30 deletions src/renderer/prepare.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::extract::{ExtractedPixelScale, ExtractedRenderText, ExtractedRenderVector};
use crate::{assets::vector::VelloAsset, CoordinateSpace, Vector};
use crate::{assets::vector::VelloAsset, CoordinateSpace};
use bevy::{
prelude::*,
render::{camera::ExtractedCamera, render_asset::RenderAssets, view::ExtractedView},
Expand Down Expand Up @@ -162,32 +162,3 @@ pub fn prepare_text_affines(
.insert(PreparedAffine(Affine::new(transform)));
}
}

pub fn prepare_recoloring(mut render_vectors: Query<&mut ExtractedRenderVector>) {
for mut render_vector in render_vectors.iter_mut() {
// Get vector and color swap or there's no use continuing...
let ExtractedRenderVector {
asset, color_swaps, ..
} = render_vector.as_mut();

// Perform recolors!
// TODO: Recoloring SVGs
let Vector::Lottie {
ref original,
ref mut colored,
..
} = asset.data
else {
continue;
};

// Continue if there are no colors
let Some(color_swaps) = color_swaps else {
colored.take();
continue;
};

let colored_composition = color_swaps.create(original);
colored.replace(colored_composition);
}
}
55 changes: 21 additions & 34 deletions src/renderer/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ use super::{
BevyVelloRenderer, LottieRenderer, SSRenderTarget,
};
use crate::{
animation_controller::calculate_playhead,
assets::vector::{Vector, VelloAsset},
font::VelloFont,
AnimationDirection, CoordinateSpace,
CoordinateSpace,
};
use bevy::{
prelude::*,
Expand All @@ -17,7 +18,6 @@ use bevy::{
},
};
use vello::{RenderParams, Scene, SceneBuilder};
use vello_svg::usvg::strict_num::Ulps;

#[derive(Clone)]
pub struct ExtractedVectorAssetData {
Expand Down Expand Up @@ -144,6 +144,7 @@ pub fn render_scene(
RenderItem::Vector(ExtractedRenderVector {
asset,
playback_settings,
color_swaps,
..
}) => match &asset.data {
Vector::Svg {
Expand All @@ -152,40 +153,26 @@ pub fn render_scene(
builder.append(fragment, Some(affine));
}
Vector::Lottie {
original,
colored,
playhead,
composition,
rendered_frames,
first_frame: _,
} => {
let composition = colored.as_ref().unwrap_or(original);
let t = {
let start_frame =
playback_settings.segments.start.max(original.frames.start);
let end_frame = playback_settings.segments.end.min(original.frames.end);
let length = end_frame - start_frame;

let frame = match playback_settings.looping {
crate::AnimationLoopBehavior::None => {
playhead.clamp(start_frame, end_frame)
}
crate::AnimationLoopBehavior::Amount(_) => todo!(),
crate::AnimationLoopBehavior::Loop => playhead % length,
};
let normal_frame = match playback_settings.direction {
AnimationDirection::Normal => {
(start_frame + frame).min(end_frame.prev())
}
AnimationDirection::Reverse => {
(end_frame - frame).min(end_frame.prev())
}
};
let t = normal_frame / composition.frame_rate;
error!("playhead: {playhead}, frame: {frame}, normal_frame: {normal_frame}, t: {t}");
t
};
velottie_renderer
.0
.render(composition, t, affine, 1.0, &mut builder);
let t =
calculate_playhead(*rendered_frames, composition, playback_settings)
/ composition.frame_rate;
velottie_renderer.0.render(
{
color_swaps
.as_ref()
.map(|cs| cs.create(composition))
.as_ref()
.unwrap_or(composition)
},
t,
affine,
1.0,
&mut builder,
);
}
},
RenderItem::Text(ExtractedRenderText { font, text, .. }) => {
Expand Down

0 comments on commit 79a2f9e

Please sign in to comment.