Mercurial > hg > indyvon
changeset 80:880ae8e03408
Measure time intervals between repaints. Experiments.
author | Mikhail Kryshen <mikhail@kryshen.net> |
---|---|
date | Wed, 01 Sep 2010 22:25:55 +0400 |
parents | 5fd50e400124 |
children | 5d2153e8a28d |
files | src/net/kryshen/indyvon/demo.clj src/net/kryshen/indyvon/layers.clj |
diffstat | 2 files changed, 170 insertions(+), 30 deletions(-) [+] |
line diff
1.1 --- a/src/net/kryshen/indyvon/demo.clj Wed Sep 01 22:24:17 2010 +0400 1.2 +++ b/src/net/kryshen/indyvon/demo.clj Wed Sep 01 22:25:55 2010 +0400 1.3 @@ -26,6 +26,110 @@ 1.4 (java.awt Color) 1.5 (javax.swing JFrame))) 1.6 1.7 +(defn draw-button! 1.8 + "Draws button immediately (but uses callback for button action 1.9 + unlike IMGUI)." 1.10 + [id content callback & args] 1.11 + (with-handlers id 1.12 + (let [shadow-offset 2 1.13 + padding 4 1.14 + border-width 1 1.15 + offset (if (picked? id) (/ shadow-offset 2) 0) 1.16 + ^Color color (:alt-back-color *theme*) 1.17 + color (if (hovered? id) (.brighter color) color) 1.18 + width (- *width* shadow-offset) 1.19 + height (- *height* shadow-offset)] 1.20 + (with-color Color/BLACK 1.21 + (.fillRect *graphics* shadow-offset shadow-offset width height)) 1.22 + (with-color color 1.23 + (.fillRect *graphics* offset offset width height)) 1.24 + (draw! (border content border-width padding) 1.25 + offset offset width height)) 1.26 + ;; Event handlers 1.27 + (:mouse-entered _ (repaint)) 1.28 + (:mouse-exited _ (repaint)) 1.29 + (:mouse-pressed _ (repaint)) 1.30 + (:mouse-released _ (repaint)) 1.31 + (:mouse-clicked _ (apply callback args)))) 1.32 + 1.33 +(defn combine-colors [^Color color1 ^Color color2 c] 1.34 + (case c 1.35 + 0.0 color1 1.36 + 1.0 color2 1.37 + (let [rgb1 (.getRGBComponents color1 nil) 1.38 + rgb2 (.getRGBComponents color2 nil) 1.39 + rgb (float-array (map #(+ (* (- 1 c) %1) (* c %2)) rgb1 rgb2))] 1.40 + (Color. (aget rgb 0) (aget rgb 1) (aget rgb 2) (aget rgb 3))))) 1.41 + 1.42 +(defn animate 1.43 + "Changes atom value according to specified range, speed, and current 1.44 + frame interval. Invokes repaint if change happens." 1.45 + [atom from to speed] 1.46 + (let [prev @atom 1.47 + state (cond 1.48 + (zero? speed) :stop 1.49 + (= prev from) (if (pos? speed) :start :stop) 1.50 + (= prev to) (if (neg? speed) :start :stop) 1.51 + :default :continue)] 1.52 + ;;(println prev from to speed state *interval*) 1.53 + (if (= state :stop) 1.54 + prev 1.55 + (let [interval (if (= state :start) 1 *interval*) 1.56 + step (* speed interval 1E-9) 1.57 + val (swap! atom #(-> % (+ step) (max from) (min to)))] 1.58 + (repaint) 1.59 + val)))) 1.60 + 1.61 +(defn button 1.62 + "Create animated button layer." 1.63 + [content callback & args] 1.64 + (let [padding 4 1.65 + border-width 1 1.66 + shadow-offset 2 1.67 + face (border content padding border-width) 1.68 + highlight (atom 0) 1.69 + animation-speed (atom 0)] 1.70 + (interval-layer 1.71 + (reify 1.72 + Layer 1.73 + (render! [button] 1.74 + (with-handlers button 1.75 + (let [hovered (hovered? button) 1.76 + offset (if (picked? button) (/ shadow-offset 2) 0) 1.77 + color (combine-colors 1.78 + (:alt-back-color *theme*) Color/WHITE 1.79 + (animate highlight 0.0 1.0 @animation-speed)) 1.80 + width (- *width* shadow-offset) 1.81 + height (- *height* shadow-offset)] 1.82 + (with-color Color/BLACK 1.83 + (.fillRect *graphics* 1.84 + shadow-offset shadow-offset 1.85 + width height)) 1.86 + (with-color color 1.87 + (.fillRect *graphics* offset offset width height)) 1.88 + (draw! (border content border-width padding) 1.89 + offset offset width height)) 1.90 + ;; Event handlers 1.91 + (:mouse-entered _ 1.92 + (reset! animation-speed 4) 1.93 + (repaint)) 1.94 + (:mouse-exited _ 1.95 + (reset! animation-speed -2) 1.96 + (repaint)) 1.97 + (:mouse-pressed _ (repaint)) 1.98 + (:mouse-released _ (repaint)) 1.99 + (:mouse-clicked _ (apply callback args)))) 1.100 + (layer-size [button] 1.101 + (let [face-size (layer-size face)] 1.102 + (Size. (+ (:width face-size) shadow-offset) 1.103 + (+ (:height face-size) shadow-offset)))))))) 1.104 + 1.105 +(def button1 (button (label "Animated button 1") 1.106 + println "Animated button 1 clicked")) 1.107 + 1.108 +(def button2 (button (label "Animated button 2") 1.109 + println "Animated button 2 clicked")) 1.110 + 1.111 (def layer1 1.112 (reify 1.113 Layer 1.114 @@ -68,6 +172,7 @@ 1.115 Layer 1.116 (render! [layer] 1.117 ;;(repaint) 1.118 + ;;(println (format "%.3f" (/ *interval* 1E9))) 1.119 (doto *graphics* 1.120 ;; Random color to see when repaint happens. 1.121 (.setColor (rand-nth [Color/BLACK Color/BLUE Color/RED])) 1.122 @@ -75,13 +180,30 @@ 1.123 (.drawLine *width* 0 0 *height*)) 1.124 (draw! layer2 15 20) 1.125 (draw! layer2m 120 50) 1.126 - (draw! layer3 100 100 80 50)) 1.127 + (draw! layer3 100 100 80 50) 1.128 + (draw! button1 50 160) 1.129 + (with-rotate (/ Math/PI 6) 250 200 1.130 + (draw! button1 200 160)) 1.131 + (draw! button2 50 250) 1.132 + (with-bounds 100 200 140 30 1.133 + (draw-button! :button 1.134 + (label "Immediate button" :center :center) 1.135 + #(println "Button clicked!")))) 1.136 (layer-size [layer] 1.137 (Size. 400 300)))) 1.138 1.139 +;; Main viewport 1.140 (def vp (viewport layer)) 1.141 1.142 -(def root (fps-layer vp)) 1.143 +;; Miniature (rendered asynchronously) 1.144 +(def vp-miniature (border (viewport-miniature vp 100 75))) 1.145 + 1.146 +;; Main scene 1.147 +(def scene 1.148 + (fps-layer 1.149 + (decorate-layer vp [_] 1.150 + (draw! vp) 1.151 + (draw! vp-miniature (- *width* 105) 5)))) 1.152 1.153 (defn show-frame [layer] 1.154 (doto (make-jframe "Test" layer) 1.155 @@ -90,5 +212,4 @@ 1.156 1.157 (defn -main [] 1.158 (println "Try to drag the viewport.") 1.159 - (show-frame root) 1.160 - (show-frame (fps-layer (viewport-miniature vp 80 60)))) 1.161 + (show-frame scene))
2.1 --- a/src/net/kryshen/indyvon/layers.clj Wed Sep 01 22:24:17 2010 +0400 2.2 +++ b/src/net/kryshen/indyvon/layers.clj Wed Sep 01 22:25:55 2010 +0400 2.3 @@ -284,32 +284,6 @@ 2.4 (.drawRect *graphics* x y w h)))) 2.5 width height)) 2.6 2.7 -(defn- fps-label [text] 2.8 - (padding (label text :right :bottom) 5)) 2.9 - 2.10 -(defn fps-layer 2.11 - "Creates layer that draws content and displays 2.12 - the frames per seconds rate." 2.13 - [content] 2.14 - (let [update-interval 2E8 ; 0.2 s in nanoseconds 2.15 - frames (ref 0) 2.16 - prev-time (ref nil) 2.17 - display (ref (fps-label "fps n/a"))] 2.18 - (decorate-layer content [_] 2.19 - (draw! content) 2.20 - (draw! 2.21 - (dosync 2.22 - (alter frames inc) 2.23 - (if @prev-time 2.24 - (let [elapsed (- *time* @prev-time)] 2.25 - (when (> elapsed update-interval) 2.26 - (let [fps (/ @frames (/ elapsed 1E9))] 2.27 - (ref-set display (fps-label (format "%.1f" fps))) 2.28 - (ref-set frames 0) 2.29 - (ref-set prev-time *time*)))) 2.30 - (ref-set prev-time *time*)) 2.31 - @display))))) 2.32 - 2.33 ;; 2.34 ;; Layer context decorators. 2.35 ;; 2.36 @@ -338,3 +312,48 @@ 2.37 (anchor [t xa ya] 2.38 (with-theme theme 2.39 (anchor layer xa ya)))))) 2.40 + 2.41 +;; 2.42 +;; Measuring time 2.43 +;; 2.44 + 2.45 +(def *interval*) 2.46 + 2.47 +(defn interval-layer 2.48 + "Creates layer that measures time between repaints ant draws it's 2.49 + content with the *interval* var bound to the measured time." 2.50 + [content] 2.51 + (let [last-time (atom nil)] 2.52 + (decorate-layer content [_] 2.53 + (compare-and-set! last-time nil *time*) 2.54 + (let [lt @last-time] 2.55 + (binding [*interval* (if (compare-and-set! last-time lt *time*) 2.56 + (- *time* lt) 2.57 + 0)] ; already measured on parallel thread 2.58 + (render! content)))))) 2.59 + 2.60 +(defn- fps-label [text] 2.61 + (padding (label text :right :bottom) 5)) 2.62 + 2.63 +(defn fps-layer 2.64 + "Creates layer that draws content and displays 2.65 + the frames per seconds rate." 2.66 + [content] 2.67 + (let [update-interval 2E8 ; 0.2 s in nanoseconds 2.68 + frames (ref 0) 2.69 + prev-time (ref nil) 2.70 + display (ref (fps-label "fps n/a"))] 2.71 + (decorate-layer content [_] 2.72 + (draw! content) 2.73 + (draw! 2.74 + (dosync 2.75 + (alter frames inc) 2.76 + (if @prev-time 2.77 + (let [elapsed (- *time* @prev-time)] 2.78 + (when (> elapsed update-interval) 2.79 + (let [fps (/ @frames (/ elapsed 1E9))] 2.80 + (ref-set display (fps-label (format "%.1f" fps))) 2.81 + (ref-set frames 0) 2.82 + (ref-set prev-time *time*)))) 2.83 + (ref-set prev-time *time*)) 2.84 + @display)))))