use std::{cell::RefCell, fmt, rc::Rc};
use crate::engine::d2::util::{Listener2, Value};
use super::{Behavior, Binding, BindingFunction, EaseFunction, Tween};
struct AnimatedFloatProps {
pub value: Value<f32>,
behavior: Option<Rc<dyn Behavior>>,
}
#[derive(Clone)]
pub struct AnimatedFloat {
props: Rc<RefCell<AnimatedFloatProps>>,
}
impl AnimatedFloat {
pub fn new(value: f32, listener: Option<Listener2<f32, f32>>) -> Self {
Self {
props: Rc::new(RefCell::new(AnimatedFloatProps {
value: Value::new(value, listener),
behavior: None,
})),
}
}
#[inline]
pub fn get(&self) -> f32 {
*self.props.borrow().value.get()
}
pub fn set(&self, value: f32) {
let mut props = self.props.borrow_mut();
props.behavior = None;
props.value.set(value);
}
pub fn update(&self, dt: f32) {
let mut props = self.props.borrow_mut();
let result = props.behavior.as_ref().map(|behavior| {
let value = behavior.update(dt);
let is_complete = behavior.is_complete();
(value, is_complete)
});
if let Some((value, is_complete)) = result {
props.value.set(value);
if is_complete {
props.behavior = None;
}
}
}
pub fn animate(&self, from: f32, to: f32, seconds: f32, easing: Option<EaseFunction>) {
self.set(from);
self.animate_to(to, seconds, easing);
}
pub fn animate_to(&self, to: f32, seconds: f32, easing: Option<EaseFunction>) {
let mut props = self.props.borrow_mut();
props.behavior = Some(Rc::new(Tween::new(*props.value.get(), to, seconds, easing)));
}
pub fn animate_by(&self, by: f32, seconds: f32, easing: Option<EaseFunction>) {
let mut props = self.props.borrow_mut();
props.behavior = Some(Rc::new(Tween::new(
*props.value.get(),
*props.value.get() + by,
seconds,
easing,
)));
}
#[inline]
pub fn bind_to(&self, to: Value<f32>, function: Option<BindingFunction>) {
let mut props = self.props.borrow_mut();
props.behavior = Some(Rc::new(Binding::new(to, function)));
}
pub fn set_behavior(&self, behavior: Option<Rc<dyn Behavior>>) {
let mut props = self.props.borrow_mut();
props.behavior = behavior;
self.update(0.0);
}
#[inline]
pub fn behavior(&self) -> Option<Rc<dyn Behavior>> {
let props = self.props.borrow();
props.behavior.clone()
}
}
impl Default for AnimatedFloat {
fn default() -> Self {
Self {
props: Rc::new(RefCell::new(AnimatedFloatProps {
value: Value::new(0.0, None),
behavior: None,
})),
}
}
}
impl fmt::Display for AnimatedFloat {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.props.borrow().value.value)
}
}
impl fmt::Debug for AnimatedFloat {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("AnimatedFloat")
.finish()
}
}