anchor.diff:  (defparameter *last-hover-target* nil)
   (defparameter *last-mouse-down-target* nil)
   (defparameter *dragging* nil)
  +(defparameter *drag-start-position* nil)
   
   (defmethod initialize-instance :after ((this button) &key width height events)
     (describe this))
  
positive.code: 
    (let ((ret))
      (maphash (lambda (k v)
  	       (push (funcall f k v) ret))
  	     (gethash e *event-hash*))
      ret))
  
  (clinch:defevent clinch:*on-mouse-down* (win mouse x y button state clicks ts)
  
negative.code:   ;;(format t "win: ~A mouse: ~A x: ~A y: ~A button: ~A state: ~A clicks: ~A ts: ~A~%" win mouse x y button state clicks ts)
  
    (let ((event `((:window . ,win)
                   (:mouse . ,mouse)
                   (:mouse-screen-position ,x . ,y)
                   (:button . ,button)
                   (:state . ,state)
                   (:clicks . ,clicks)
                   (:timestamp . ,ts)))
          (collision-hash (make-hash-table :test 'equal)))
  
      (map-event (lambda (k v)
                   (multiple-value-bind (collisions start ray)
                       (memoized-check-intersect (car (children k)) k x y *viewport* *projection* collision-hash)
  
                     (when collisions
                       (funcall v k (acons :event :mouse-down
                                           (acons :ray-start start
                                                  (acons :ray ray
                                                         (acons :collisions collisions event)))))
  
                       (when (= button *click-button*)
                         (setf *last-mouse-down-target* k)))))
  
                 :mouse-down)
  
      (when (= button *drag-button*)
        (map-event (lambda (k v)
                     (multiple-value-bind (collisions start ray)
                         (memoized-check-intersect (car (children k)) k x y *viewport* *projection* collision-hash)
  
                       (when collisions
                         (setf *dragging* k
                               *drag-start-position* (list (get-translation-from-matrix (clinch::current-transform k))
                                                           start ray))
                         (funcall v k (acons :event :mouse-drag-start
                                             (acons :ray-start start
                                                    (acons :ray ray
                                                           (acons :collisions collisions event))))))))
                   :mouse-drag-start))))
  
  
  (clinch:defevent clinch:*on-mouse-up* (win mouse x y button state clicks ts)
  
    ;;(format t "win: ~A mouse: ~A x: ~A y: ~A button: ~A state: ~A clicks: ~A ts: ~A~%" win mouse x y button state clicks ts)
    (let ((event `((:window . ,win)
                   (:mouse . ,mouse)
                   (:mouse-screen-position ,x . ,y)
                   (:button . ,button)
                   (:state . ,state)
                   (:clicks . ,clicks)
                   (:timestamp . ,ts)))
          (collision-hash (make-hash-table :test 'equal)))
  
      (map-event (lambda (k v)
                   (multiple-value-bind (collisions start ray)
                       (memoized-check-intersect (car (children k)) k x y *viewport* *projection* collision-hash)
                     (when collisions
                       (let ((e (acons :ray-start start
                                       (acons :ray ray event))))
                         (when (and
                                (= *click-button* button)
                                (eq *last-mouse-down-target* k))
                           (let ((h (gethash :mouse-click *event-hash*)))
                             (when h
                               (let ((f (gethash k h)))
                                 (when f (funcall f k (acons :event :mouse-click
                                                             (acons :collisions collisions e))))))))
  
                         (funcall v k (acons :event :mouse-up
                                             (acons :collisions collisions e))))
                       (setf *last-mouse-down-target* nil))))
  
                 :mouse-up)
      (when (and *dragging*
                 (= button *drag-button*))
  
        (setf *dragging* nil
              *drag-start-position* nil)
  
  
        (map-event (lambda (k v)
                     (multiple-value-bind (origin ray) (unproject x y (width *viewport*) (height *viewport*) (m4:inverse *projection*))
  
                       (funcall v k (acons :event :mouse-drag-drop
                                           (acons :ray-start origin
                                                  (acons :ray ray event))))))
  
                   :mouse-drag-drop))))
  
  
  ;; (loop for n in *buttons*
  ;;     collect (check-intersect (car (children n)) n x y *viewport* *projection*)))
  
  ;; Rotate and translate with mouse
  (clinch:defevent clinch:*on-mouse-move* (win mouse state x y xrel yrel ts)
    ;;(format t "win: ~A mouse: ~A x: ~A y: ~A button: ~A state: ~A clicks: ~A ts: ~A~%" win mouse state x y xrel yrel ts)
  
    (let ((event `((:window . ,win)
                   (:mouse . ,mouse)
                   (:mouse-screen-position ,x . ,y)
                   (:state . ,state)
                   (:x-relative ,xrel)
                   (:y-relative . ,yrel)
                   (:timestamp . ,ts)))
          (cached-collisions (make-hash-table :test 'equal)))
  
      (map-event (lambda (k v)
                   (multiple-value-bind (collisions start ray)
                       (memoized-check-intersect (car (children k)) k x y *viewport* *projection* cached-collisions)
                     (if collisions
                         (progn
                           (unless (eq k *last-hover-target*)
                             (setf *last-hover-target* k)
                             (funcall v k (acons :event :mouse-hover event)))
                           (funcall v k (acons :event :mouse-move
                                               (acons :ray-start start
                                                      (acons :ray ray
                                                             (acons :collisions collisions event))))))
                         (when (eq k *last-hover-target*)
                           (let ((f (gethash k (gethash :mouse-exit *event-hash*))))
                             (when f (funcall f k (acons :event :mouse-exit event)))
                             (setf *last-hover-target* nil))))))
  
                 :mouse-move)
      (when *dragging*
        ;; move it!
        (let ((proj-1 (M4:inverse *projection*)))
  
          (multiple-value-bind (d-pos d) (clinch:get-screen-direction proj-1)
            (multiple-value-bind (button-start-position button-end-position)
                (unproject x y (width *viewport*) (height *viewport*) proj-1)
              (let ((trans (calculate-movement d-pos
                                               d
                                               (second *drag-start-position*)
                                               (third *drag-start-position*)
                                               button-start-position
                                               button-end-position)))
                (format t "Drag start ~A~%" *drag-start-position*)
  	      (format t "calculate-movement ~A ~A ~A ~A ~A ~A~%" d-pos
  		      d
  		      (second *drag-start-position*)
  		      (third *drag-start-position*)
  		      button-start-position
  		      button-end-position)
  	      (format t "~A~%" trans))))))))
  
  
  
    ;; (loop for n in *buttons*
    ;;    for q = (car (children n))
    ;;    if (some (lambda (x)
    ;;            (not (null x)))
    ;;          (alexandria:flatten (check-intersect q n x y *viewport* *projection*)))
    ;;    do (draw-button q
    ;;                 "Hello World!"
    ;;                 :line-width 12
    ;;                 :foreground '(.1 .1 .1 1)
    ;;                 :fill '(0 0 0 .4)
    ;;                 :line '(0 0 .9 1))
    ;;    else
    ;;    do (draw-button q
    ;;                 "Hello World!"
    ;;                 :line-width 10
    ;;                 :foreground '(.1 .1 .1 1)
    ;;                 :fill '(0 0 0 .2)
    ;;                 :line '(0 0 .8 1))))
  
  
  
  