Components / effects
CinematicEffect builder
A semantic one-shot effect with an optional prepared dotLottie clip.
A builder is RenderOnce. Construct and mount it in one expression.
use gpui_kit::effects::CinematicEffect;
Reviewed in cinematic-effects.
Construct
new(ident: impl Into<Ident>, plan: EffectPlan) -> Self
Options
Chain onto the value.
clip(clip: Rc<dyn DotLottieClip>) -> Self
resolved(clip: Result<Rc<dyn DotLottieClip>, DotLottieError>) -> Self
unavailable(error: DotLottieError) -> Self
sample_at(elapsed: Duration) -> Self
Example · cinematic-effects
fn cinematic_effects(_window: &mut Window, cx: &mut App) -> AnyElement {
let theme = cx.theme().clone();
let clip: Rc<dyn DotLottieClip> = Rc::new(SceneCinematicClip);
let mut planner = EffectPlanner::new(EffectPolicy::new(EffectQuality::Cinematic));
let success = planner.plan(
EffectEvent::new(
"scene-cinematic-success",
"cinematic-effects",
"success",
VisualCue::Success,
),
1,
false,
);
let handoff = planner.plan(
EffectEvent::new(
"scene-cinematic-handoff",
"cinematic-effects",
"handoff",
VisualCue::Handoff,
),
1,
false,
);
let reward = planner.plan(
EffectEvent::new(
"scene-cinematic-reward",
"cinematic-effects",
"reward",
VisualCue::Reward,
),
1,
false,
);
let mut static_planner = EffectPlanner::new(EffectPolicy::new(EffectQuality::Cinematic));
let static_reward = static_planner.plan(
EffectEvent::new(
"scene-cinematic-static",
"cinematic-effects-static",
"reward",
VisualCue::Reward,
),
1,
true,
);
let card = |title: &'static str, detail: &'static str, effect: AnyElement| {
div()
.column()
.w(px(372.0))
.h(px(228.0))
.radius(&theme, Radius::Card)
.overflow_hidden()
.bg(theme.colors.sunken)
.child(div().relative().w_full().h(px(154.0)).child(effect))
.child(
div()
.column()
.gap_token(&theme, Space::Xs)
.px_token(&theme, Space::Md)
.py_token(&theme, Space::Sm)
.child(crate::foundation::text(&theme, TypeScale::Label, title))
.child(
crate::foundation::text(&theme, TypeScale::Caption, detail)
.text_color(theme.colors.text_muted),
),
)
};
stack(&theme)
.w(px(808.0))
.child(crate::foundation::text(
&theme,
TypeScale::Subtitle,
"Semantic cinematic effects",
))
.child(caption(
&theme,
"events choose recipes; hosts resolve bytes and own playback requests",
))
.child(
row(&theme)
.gap_token(&theme, Space::Md)
.child(card(
"Handoff · deterministic sample",
"A resolved clip sampled at 575 ms; RTL mirrors its directional trail.",
CinematicEffect::new("scene.cinematic.handoff", handoff)
.clip(clip.clone())
.sample_at(Duration::from_millis(575))
.into_any_element(),
))
.child(card(
"Success · runtime unavailable",
"The semantic recipe falls back to the policy-owned particle burst.",
CinematicEffect::new("scene.cinematic.success", success)
.unavailable(DotLottieError::new(
DotLottieErrorKind::RuntimeUnavailable,
"dotLottie backend is not installed",
))
.sample_at(Duration::from_millis(520))
.into_any_element(),
)),
)
.child(
row(&theme)
.gap_token(&theme, Space::Md)
.child(card(
"Reward · invalid asset fallback",
"A refused archive stays explicit while a bounded particle recipe renders.",
CinematicEffect::new("scene.cinematic.invalid", reward)
.unavailable(DotLottieError::new(
DotLottieErrorKind::ArchiveInvalid,
"animation archive did not pass validation",
))
.sample_at(Duration::from_millis(620))
.into_any_element(),
))
.child(card(
"Reward · reduced-motion poster",
"The same recipe becomes a deterministic poster with no frame timeline.",
CinematicEffect::new("scene.cinematic.poster", static_reward)
.clip(clip)
.into_any_element(),
)),
)
.into_any_element()
}