summaryrefslogtreecommitdiff
path: root/tweening.lisp
blob: cc6adb18589bc803614c44b673ce443e6e9e575c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
(in-package :animise)

(defmacro when-bound (symbol)
  `(when (boundp (quote ,symbol)) ,symbol))

(defvar *duration*)
(defvar *target*)
(defvar *start-time*)

(defmacro sequencing ((&key loop-mode start starting with-target targeting target) &body forms)
  "START and STARTING are synonym keywords, and are used to specify as tart time.

   WITH-TARGET, TARGETING, and TARGET are synonym keywords, used to specify a
   default tween target for all tweens made within the body of this form.

   LOOP-MODE is supplied to the LOOP-MODE slot on the TWEEN-SEQ class that this
   form returns."
  (let ((this-seq (gensym))
        (dyn-vars (append (when (or with-target target targeting)
                             `((*target* ,(or with-target target targeting))))
                           (when (or start starting)
                             `((*start-time* ,(or start starting)))))))
    `(let ,dyn-vars
       (let ((,this-seq (in-sequence ,@forms)))
         (setf (loop-mode ,this-seq) ',loop-mode)
         ,this-seq))))


(defun pausing (&key for duration start)
  "A light wrapper around PAUSE. Is aware of default parameters that may have
   been set in an enclosing form."
  (pause (or for duration (when-bound *duration*) 0)
         (or start (when-bound *start-time*) 0)))

(defmacro grouping ((&key duration for with-duration) &body forms)
  "Returns a TWEEN-GROUP instance.

   DURATION, FOR, and WITH-DURATION are all synonym keywords, used to specify a default
   duration for any tweens define din this body, where applicable."
  (let ((dyn-vars (append (when (or duration for with-duration)
                            `((*duration* ,(or duration for with-duration)))))))
    `(let ,dyn-vars
       (as-group ,@forms))))


(defun keyword->ease-fn (name)
  (case name
    ((:bounce-out :bouncing-out) #'bounce-out)
    ((:cubing-in :cubically-in :cubic-in) #'cubic-in)
    ((:cubing-in-out :cubically-in-out :cubic-in-out) #'cubic-in-out)
    ((:cubing-out :cubically-out :cubic-out) #'cubic-out)
    ((:elastic-out :elastically-out) #'elastic-out)
    ((:linear :linearly) #'linear)
    ((:quading-in :quad-in :quadratically-in) #'quad-in)
    ((:quading-in-out :quad-in-out :quadratically-in-out) #'quad-in-out)
    ((:quading-out :quad-out :quadratically-out) #'quad-out)
    ((:sine-in :sinusoidal-in :sinusoidally-in) #'sinusoidal-in)
    ((:sine-in-out :sinusoidally-in-out :sinusoidal-in-out) #'sinusoidal-in-out)
    ((:sine-out :sinusoidal-out :sinusoidally-out) #'sinusoidal-out)))

(defun animating (ease &key the modifying of to for start starting)
  "A wrapper around ANIMATE that is aware of any default values defined in the
   the most recently enclosing form.

   EASE is either an easing function, or a keyword that indicates an easing
   function. The valid keywords are :BOUNCE-OUT :BOUNCING-OUT :CUBING-IN
   :CUBICALLY-IN :CUBIC-IN :CUBING-IN-OUT :CUBICALLY-IN-OUT :CUBIC-IN-OUT
   :CUBING-OUT :CUBICALLY-OUT :CUBIC-OUT :ELASTIC-OUT :ELASTICALLY-OUT
   :LINEAR :LINEARLY :QUADING-IN :QUAD-IN :QUADRATICALLY-IN :QUADING-IN-OUT
   :QUAD-IN-OUT :QUADRATICALLY-IN-OUT :QUADING-OUT :QUAD-OUT :QUADRATICALLY-OUT
   :SINE-IN :SINUSOIDAL-IN :SINUSOIDALLY-IN :SINE-IN-OUT :SINUSOIDALLY-IN-OUT
   :SINUSOIDAL-IN-OUT :SINE-OUT :SINUSOIDAL-OUT :SINUSOIDALLY-OUT

   THE and MODIFYING are synonym keywords. Either one specifies the ACCESSOR to
   use for the tween.

   OF becomes the value of the TARGET slot of this TWEEN. If OF is NIL,
   then any default target value already set in an enclosing form is used.

   TO becomes the value of the END-VAL slot this TWEEN.

   FOR becomes the value of the DURATION slot of this TWEEN, superseding any
   default value set in the enclosing form.

   START and STARTING are synonym keywords, specifiying a START-TIME.
   "
  (animate (or of (when-bound *target*))
           (or the modifying)
           to
           :start (or start starting (when-bound *start-time*) 0)
           :ease (if (functionp ease) ease (keyword->ease-fn ease))
           :duration (or for (when-bound *duration*) 0)))