diff --git a/docs/quil.core.md b/docs/quil.core.md index 62aec95..e016f30 100644 --- a/docs/quil.core.md +++ b/docs/quil.core.md @@ -121,7 +121,7 @@ - [ ] [`load-shader`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L2240) - "Loads a shader into the PShader object" - [ ] [`load-shape`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L2254) - "Load a geometry from a file as a PShape" - [ ] [`log`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L2265) - "Calculates the natural logarithm (the base-e logarithm) of a number" -- [ ] [`looping?`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L1705) - "Returns whether the sketch is looping" +- [x] [`looping?`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L1705) - "Returns whether the sketch is looping" - [ ] [`mag`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L2278) - "Calculates the magnitude (or length) of a vector" - [ ] [`map-range`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L2297) - "Re-maps a number from one range to another" - [ ] [`mask-image`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L2313) - "Masks part of an image from displaying by loading another image and using it as an alpha channel" @@ -139,7 +139,7 @@ - [ ] [`no-cursor`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L2490) - "Hides the cursor from view" - [ ] [`no-fill`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L2502) - "Disables filling geometry" - [ ] [`no-lights`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L2595) - "Disable all lighting" -- [ ] [`no-loop`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L2609) - "Stops Processing from continuously executing the code within draw" +- [x] [`no-loop`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L2609) - "Stops Processing from continuously executing the code within draw" - [ ] [`no-smooth`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L2664) - "Draws all geometry with jagged (aliased) edges" - [ ] [`no-stroke`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L2675) - "Disables drawing the stroke (outline)" - [ ] [`no-tint`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L2688) - "Removes the current fill value for displaying images and reverts to displaying images with their original hues" @@ -221,7 +221,7 @@ - [ ] [`spot-light`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L3818) - "Adds a spot light" - [ ] [`sq`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L3838) - "Squares a number (multiplies a number by itself)" - [ ] [`sqrt`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L3852) - "Calculates the square root of a number" -- [ ] [`start-loop`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L3867) - "Causes Processing to continuously execute the code within draw" +- [x] [`start-loop`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L3867) - "Causes Processing to continuously execute the code within draw" - [ ] [`state`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L227) - "Retrieve sketch-specific state by key" - [ ] [`state-atom`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L202) - "Retrieve sketch-specific state-atom" - [x] [`stroke`](https://github.com/quil/quil/blob/2.8.0/src/cljc/quil/core.cljc#L3885) - "Sets the color used to draw lines and borders around shapes" diff --git a/src/doodler/core.clje b/src/doodler/core.clje index 9ffc2f9..f86bfca 100644 --- a/src/doodler/core.clje +++ b/src/doodler/core.clje @@ -37,7 +37,7 @@ (defn- save-current-stroke [color] - (set! *sketch* (assoc *sketch* :current-stroke color))) + (u/swap-var! *sketch* assoc :current-stroke color)) (defn current-stroke [] @@ -79,7 +79,7 @@ (defn- save-current-fill [color] - (set! *sketch* (assoc *sketch* :current-fill color))) + (u/swap-var! *sketch* assoc :current-fill color)) (defn current-fill [] @@ -170,6 +170,19 @@ [] (- (u/time-mark) (*sketch* :epoch))) +(defn no-loop + [] + (u/swap-var! *sketch* assoc :looping? false)) + +(defn looping? + [] + (*sketch* :looping?)) + +(defn start-loop + [] + (u/swap-var! *sketch* assoc :looping? true) + (u/send-message (:pid *sketch*) :refresh)) + (defmacro defsketch [name & opts] (let [opts (apply hash-map opts)] diff --git a/src/doodler/events.clje b/src/doodler/events.clje new file mode 100644 index 0000000..facd175 --- /dev/null +++ b/src/doodler/events.clje @@ -0,0 +1,91 @@ +(ns doodler.events) + +(def event-names + [:set_focus ;; focus-gained + :kill_focus ;; focus-lost + :enter_window ;; mouse-entered + :leave_window ;; mouse-exited + :left_down ;; mouse-pressed + :middle_down ;; mouse-pressed + :right_down ;; mouse-pressed + :left_up ;; mouse-released + :middle_up ;; mouse-released + :right_up ;; mouse-released + :motion ;; mouse-moved + :left_dclick ;; mouse-clicked (twice) + :middle_dclick ;; mouse-clicked (twice) + :right_dclick ;; mouse-clicked (twice) + :mousewheel ;; mouse-wheel + ;; Listen to all key events + :key_down ;; key-pressed + :key_up ;; key-released + :char ;; key-typed (?) + ]) + +(defn* event-type->mouse-event + ([:enter_window] :mouse-entered) + ([:leave_window] :mouse-exited) + ([:left_down] :mouse-pressed) + ([:middle_down] :mouse-pressed) + ([:right_down] :mouse-pressed) + ([:left_up] :mouse-released) + ([:middle_up] :mouse-released) + ([:right_up] :mouse-released) + ([:left_dclick] :mouse-clicked) + ([:middle_dclick] :mouse-clicked) + ([:right_dclick] :mouse-clicked) + ([:motion] :mouse-moved) + ([:mousewheel] :mouse-wheel)) + +(defn* event-type->mouse-clicks + ([:left_dclick] 2) + ([:middle_dclick] 2) + ([:right_dclick] 2) + ([:left_up] 1) + ([:middle_up] 1) + ([:right_up] 1) + ([_] 0)) + +(defn* event-type->key-event + ([:key_down] :key-pressed) + ([:key_up] :key-released) + ([:char] :key-typed)) + +(defn* event->map + ([#erl[:wxClose :close_window]] + #erl{:event :on-close}) + + ([#erl[:wxSize :size size rect]] + #erl{:event :on-resize + :size size}) + + ([#erl[:wxFocus :set_focus window]] + #erl{:event :focus-gained + :window window}) + ([#erl[:wxFocus :kill_focus window]] + #erl{:event :focus-lost + :window window}) + + ([#erl[:wxMouse type + x y + left middle right + control shift alt meta + wheel-rotation wheel-delta lines-per-action]] + #erl{:event (event-type->mouse-event type) + :clicks (event-type->mouse-clicks type) + :x x :y y + :left left :middle middle :right right + :control control :shift shift :alt alt :meta meta + :wheel-rotation wheel-rotation :wheel-delta wheel-delta + :lines-per-action lines-per-action}) + + ([#erl[:wxKey type + x y + key-code control shift alt meta + scan-code uni-char raw-code raw-flags]] + #erl{:event (event-type->key-event type) + :x x :y y + :key-code key-code + :control control :shift shift :alt alt :meta meta + :scan-code scan-code :uni-char uni-char + :raw-code raw-code :raw-flags raw-flags})) diff --git a/src/doodler/examples/mandelbrot.clje b/src/doodler/examples/mandelbrot.clje index a331ab1..e840711 100644 --- a/src/doodler/examples/mandelbrot.clje +++ b/src/doodler/examples/mandelbrot.clje @@ -15,12 +15,12 @@ minx -2.5 miny -2.0 wh 4.0] - [(+ minx (* wh (/ x w))) - (+ miny (* wh (/ y h)))])) + #erl[(+ minx (* wh (/ x w))) + (+ miny (* wh (/ y h)))])) (defn ->color [n max-iters] - (int (* 255 (/ n max-iters)))) + (erlang/div (* 255 n) max-iters)) (defn mandelbrot [x y max-iters] (loop [a 0.0 @@ -35,10 +35,19 @@ (inc n))))) (defn mandelbrot-point [x y w h max-iters] - (let [[i j] (->complex x y w h) - n (mandelbrot i j max-iters) - color (->color n max-iters)] - [x y color])) + (let* [#erl[i j] (->complex x y w h) + n (mandelbrot i j max-iters) + color (->color n max-iters)] + #erl[x y color])) + +(defn on-mouse-pressed [state handler] + (if-not (d/looping?) + (do + (d/start-loop) + (d/background 0) + {:points (points) + :m-points nil}) + state)) (defn setup [] @@ -48,14 +57,17 @@ (defn update-state [{points :points :as state}] - (when points - (let [max-iters 100 + (if-not points + (do + (d/no-loop) + state) + (let [max-iters 255 w (d/width) h (d/height)] (loop* [#erl(#erl[x y] & rest) points m-points #erl() n 0] - (if (and (< n 500) (seq rest)) + (if (and (< n 1000) (seq rest)) (recur rest (conj m-points (mandelbrot-point x y w h max-iters)) (inc n)) @@ -73,6 +85,7 @@ :size [300 300] :setup setup :update update-state + :mouse-pressed on-mouse-pressed :draw draw :bgcolor [0] :features [:keep-on-top] diff --git a/src/doodler/middlewares/state_mode.clje b/src/doodler/middlewares/state_mode.clje index 1c10cd8..8bde090 100644 --- a/src/doodler/middlewares/state_mode.clje +++ b/src/doodler/middlewares/state_mode.clje @@ -15,7 +15,7 @@ (if update (assoc opts :draw #(do - (set! core/*state* (update core/*state*)) + (u/swap-var! core/*state* update) (draw core/*state*))) (assoc opts :draw #(draw core/*state*))))) @@ -38,9 +38,9 @@ (if-let [handler (name acc)] (if (state-only name) (assoc acc - name #(set! core/*state* (handler core/*state*))) + name #(u/swap-var! core/*state* handler)) (assoc acc - name #(set! core/*state* (handler core/*state* %)))) + name #(u/swap-var! core/*state* handler %))) acc)) opts callbacks)) diff --git a/src/doodler/sketch.clje b/src/doodler/sketch.clje index ffd2984..81d4be9 100644 --- a/src/doodler/sketch.clje +++ b/src/doodler/sketch.clje @@ -1,5 +1,6 @@ (ns doodler.sketch (:require [doodler.core :as core] + [doodler.events :as e] [doodler.util :as u])) (def SYSTEM_MENU 2048) @@ -105,7 +106,7 @@ [sketch] (wxWindow/refresh (:canvas sketch) #erl(#erl[:eraseBackground false])) - (assoc sketch :refresh true)) + sketch) (defn calculate-frame-rate [current-frame-rate time-mark p-time-mark] @@ -129,22 +130,20 @@ :current-frame-rate (calculate-frame-rate current-frame-rate time-mark p-time-mark) - :refresh false :p-time-mark p-time-mark :time-mark time-mark :frame-delay delay :frame-count (inc (sketch :frame-count))))) (defn on-paint - [sketch] + [{bitmap :bitmap canvas :canvas pid :pid}] (doodler.wx/batch - #(let [bitmap (:bitmap sketch) - dc (wxPaintDC/new (:canvas sketch))] + #(let [dc (wxPaintDC/new canvas)] (try (wxDC/drawBitmap dc bitmap #erl[0 0]) (finally (wxPaintDC/destroy dc))))) - (u/send-message (:pid sketch) #erl[:draw (u/time-mark)])) + (u/send-message pid #erl[:draw (u/time-mark)])) (defn on-draw [sketch f] @@ -198,25 +197,8 @@ (listen frame :close_window) ;; on-close ;; Listen to all mouse events - (listen canvas :set_focus) ;; focus-gained - (listen canvas :kill_focus) ;; focus-lost - (listen canvas :enter_window) ;; mouse-entered - (listen canvas :leave_window) ;; mouse-exited - (listen canvas :left_down) ;; mouse-pressed - (listen canvas :middle_down) ;; mouse-pressed - (listen canvas :right_down) ;; mouse-pressed - (listen canvas :left_up) ;; mouse-released - (listen canvas :middle_up) ;; mouse-released - (listen canvas :right_up) ;; mouse-released - (listen canvas :motion) ;; mouse-moved - (listen canvas :left_dclick) ;; mouse-clicked (twice) - (listen canvas :middle_dclick) ;; mouse-clicked (twice) - (listen canvas :right_dclick) ;; mouse-clicked (twice) - (listen canvas :mousewheel) ;; mouse-wheel - ;; Listen to all key events - (listen canvas :key_down) ;; key-pressed - (listen canvas :key_up) ;; key-released - (listen canvas :char) ;; key-typed (?) + (doseq [event-name e/event-names] + (listen canvas event-name)) ;; Set background color before showing the frame (wxWindow/setBackgroundColour canvas bgcolor) @@ -244,6 +226,7 @@ :frame-delay frame-period :current-frame-rate default-frame-rate + :looping? true :frame-count 0 :epoch (u/time-mark) :p-time-mark (u/time-mark) @@ -253,76 +236,6 @@ ;; get the right dimensions (make-bitmap canvas)))) -;; Events - -(defn* event-type->mouse-event - ([:enter_window] :mouse-entered) - ([:leave_window] :mouse-exited) - ([:left_down] :mouse-pressed) - ([:middle_down] :mouse-pressed) - ([:right_down] :mouse-pressed) - ([:left_up] :mouse-released) - ([:middle_up] :mouse-released) - ([:right_up] :mouse-released) - ([:left_dclick] :mouse-clicked) - ([:middle_dclick] :mouse-clicked) - ([:right_dclick] :mouse-clicked) - ([:motion] :mouse-moved) - ([:mousewheel] :mouse-wheel)) - -(defn* event-type->mouse-clicks - ([:left_dclick] 2) - ([:middle_dclick] 2) - ([:right_dclick] 2) - ([:left_up] 1) - ([:middle_up] 1) - ([:right_up] 1) - ([_] 0)) - -(defn* event-type->key-event - ([:key_down] :key-pressed) - ([:key_up] :key-released) - ([:char] :key-typed)) - -(defn* event->map - ([#erl[:wxClose :close_window]] - #erl{:event :on-close}) - - ([#erl[:wxSize :size size rect]] - #erl{:event :on-resize - :size size}) - - ([#erl[:wxFocus :set_focus window]] - #erl{:event :focus-gained - :window window}) - ([#erl[:wxFocus :kill_focus window]] - #erl{:event :focus-lost - :window window}) - - ([#erl[:wxMouse type - x y - left middle right - control shift alt meta - wheel-rotation wheel-delta lines-per-action]] - #erl{:event (event-type->mouse-event type) - :clicks (event-type->mouse-clicks type) - :x x :y y - :left left :middle middle :right right - :control control :shift shift :alt alt :meta meta - :wheel-rotation wheel-rotation :wheel-delta wheel-delta - :lines-per-action lines-per-action}) - - ([#erl[:wxKey type - x y - key-code control shift alt meta - scan-code uni-char raw-code raw-flags]] - #erl{:event (event-type->key-event type) - :x x :y y - :key-code key-code - :control control :shift shift :alt alt :meta meta - :scan-code scan-code :uni-char uni-char - :raw-code raw-code :raw-flags raw-flags})) - ;; Callbacks (defn handle_sync_event @@ -333,7 +246,7 @@ (defn handle_event [wx sketch] (let* [#erl[:wx id obj data event] wx - event (event->map event) + event (e/event->map event) event-key (:event event) handler (event-key sketch)] (if-not handler @@ -368,12 +281,12 @@ refresh u/noreply)) ([#erl[:draw time-mark] sketch] - (if (:refresh sketch) - (-> sketch - (on-draw (:draw-fn sketch)) - (next-refresh time-mark) - u/noreply) - (u/noreply sketch))) + (u/noreply + (if (:looping? sketch) + (-> sketch + (on-draw (:draw-fn sketch)) + (next-refresh time-mark)) + sketch))) ([wx sketch] (u/noreply sketch))) diff --git a/src/doodler/util.clje b/src/doodler/util.clje index 2b8b9a3..d3a0096 100644 --- a/src/doodler/util.clje +++ b/src/doodler/util.clje @@ -38,3 +38,7 @@ (defn time-mark [] (erlang/monotonic_time :millisecond)) + +(defmacro swap-var! + [var f & args] + `(set! ~var (~f ~var ~@args)))