(ns advent.tween) (set! *unchecked-math* :warn-on-boxed) (defn ease-in-expo-maker [^double power ] (fn ^double [^double t ^double start ^double delta ^double duration] (let [pct-done (/ t duration) pct-done (Math/pow pct-done power)] (+ start (* delta pct-done))))) (def ease-linear (ease-in-expo-maker 1.0)) (def ease-in-quadratic (ease-in-expo-maker 2.0)) (def ease-in-cubic (ease-in-expo-maker 3.0)) (def ease-in-quartic (ease-in-expo-maker 4.0)) (def ease-in-quintic (ease-in-expo-maker 5.0)) (def ease-in-dectic (ease-in-expo-maker 10.0)) (defn ease-in-out-quadratic [^double t ^double start ^double delta ^double duration] (let [t (/ t (/ duration 2))] (if (< t 1) (+ (* (/ delta 2) t t) start) (let [t (dec t)] (+ (* (/ (- delta) 2) (dec (* t (- t 2)))) start))))) (defn ease-in-out-quintic ^double [^double t ^double start ^double delta ^double duration] (let [t (/ t (/ duration (double 2.0)))] (if (< t (double 1)) (let [result (+ (* (/ delta (double 2.0)) t t t t t) start)] result) (let [t (- t (double 2.0)) result (+ (* (/ (- delta) (double 2.0)) (- (* t t t t) (double 2.0))) start)] result)))) (defn ease-out-quadratic ^double [^double t ^double start ^double delta ^double duration] (let [t (/ t duration)] (unchecked-add (-> (unchecked-subtract 1 delta) (unchecked-multiply t) (unchecked-multiply (unchecked-subtract t 2))) start))) (defn ease-out-cubic ^double [^double t ^double start ^double delta ^double duration] (let [t (unchecked-subtract (/ t duration) 1)] (unchecked-add (unchecked-multiply delta (unchecked-add 1 (Math/pow t 3))) start))) (defn tween [id screen path start end duration & {:keys [finish ease entities]}] (let [ease (or ease ease-linear) finish (or finish identity) start-time (or (:total-time screen) 0.0) start (if (and entities (= start :current)) (get-in entities path) start) delta (unchecked-subtract ^double end ^double start) ] (fn [e ^double total-time] (let [delta-time (- total-time ^double start-time) pct-done (min (/ delta-time ^double duration) 1.0) new-val (ease delta-time start delta duration) e (assoc-in e path (if (= 1.0 pct-done) end new-val))] (if (= 1.0 pct-done) (finish (update-in e [:tweens] dissoc id)) e)) )))