test.agda 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. {-- test.agda - playing with agda/haskell interop
  2. -- Copyright (C) 2018-2019 caryoscelus
  3. --
  4. -- This program is free software: you can redistribute it and/or modify
  5. -- it under the terms of the GNU General Public License as published by
  6. -- the Free Software Foundation, either version 3 of the License, or
  7. -- (at your option) any later version.
  8. --
  9. -- This program is distributed in the hope that it will be useful,
  10. -- but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. -- GNU General Public License for more details.
  13. --
  14. -- You should have received a copy of the GNU General Public License
  15. -- along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. --}
  17. -- {-# OPTIONS --without-K #-}
  18. module test where
  19. open import Data.Empty
  20. open import Data.Unit hiding (_≟_)
  21. open import Data.Bool hiding (_≟_)
  22. open import Data.Nat
  23. open import Data.Nat.Properties
  24. open import Data.Nat.DivMod
  25. import Data.Integer as ℤ
  26. open import Data.Sum hiding (map)
  27. open import Data.Product hiding (map ; zip)
  28. import Data.Product as P
  29. open import Data.List
  30. import Data.List as L
  31. open import Relation.Binary.PropositionalEquality
  32. open import Relation.Nullary
  33. open import Relation.Nullary.Decidable hiding (map)
  34. import IO
  35. open import Function
  36. open import Util
  37. open import Hask
  38. import GLFW
  39. open GLFW.Types
  40. open import NanoLens
  41. open import GLApp
  42. record Stroke : Set where
  43. constructor mkStroke
  44. field
  45. sZoom : Int
  46. sPoints : List Point
  47. open Stroke
  48. Picture = List Stroke
  49. record AllApp : Set where
  50. field
  51. frames : List Picture
  52. zoomLevel : Int
  53. cursor : V2 Coord
  54. isDrawing : Bool
  55. nowFrame : ℕ
  56. frameCount : ℕ
  57. needToClearTexture : Bool
  58. open AllApp
  59. emptyApp : ℕ → AllApp
  60. emptyApp nFrames = record
  61. { frameCount = nFrames
  62. ; nowFrame = 0
  63. ; frames = replicate nFrames []
  64. ; cursor = v2 (ℤ.+ 0) (ℤ.+ 0)
  65. ; isDrawing = false
  66. ; zoomLevel = I0
  67. ; needToClearTexture = true
  68. }
  69. modifyAt : ∀ {ℓ} {A : Set ℓ} (n : ℕ) (f : A → A) → List A → List A
  70. modifyAt n f [] = []
  71. modifyAt zero f (x ∷ l) = f x ∷ l
  72. modifyAt (suc n) f (x ∷ l) = x ∷ modifyAt n f l
  73. newShape : AllApp → AllApp
  74. newShape app =
  75. let
  76. zl = zoomLevel app
  77. fi = nowFrame app
  78. in
  79. modify ፦[ frames ] (modifyAt fi (mkStroke zl [] ∷_)) app
  80. appendShape : AllApp → AllApp
  81. appendShape app =
  82. let
  83. xy = cursor app
  84. fi = nowFrame app
  85. in
  86. modify ፦[ frames ]
  87. (modifyAt fi (λ
  88. { (mkStroke z ss ∷ shapes) → mkStroke z (xy ∷ ss) ∷ shapes
  89. ; [] → [] -- TODO should never happen, eliminate
  90. }))
  91. app
  92. mouseCallback : GLFW.MouseCallback AllApp
  93. mouseCallback button MouseButtonState'Pressed mods =
  94. set ፦[ isDrawing ] true ⟫ newShape
  95. mouseCallback button _ mods = set ፦[ isDrawing ] false
  96. cursorCallback : GLFW.CursorCallback AllApp
  97. cursorCallback x y app =
  98. (set ፦[ cursor ] (screenToGl wh wh x y) ⟫ λ app →
  99. let
  100. draw = isDrawing app
  101. in
  102. when′ draw appendShape app) app
  103. loopFrameLeft : ℕ → ℕ → ℕ
  104. loopFrameLeft m zero = pred m
  105. loopFrameLeft m (suc n) = n
  106. loopFrameRight : ℕ → ℕ → ℕ
  107. loopFrameRight m n
  108. with suc n <? m
  109. ... | yes _ = suc n
  110. ... | no _ = 0
  111. keyCallback : GLFW.KeyCallback AllApp
  112. keyCallback _ _ KeyState'Released _ = id
  113. keyCallback Key'Equal _ _ _ =
  114. set ፦[ needToClearTexture ] true ⟫
  115. modify ፦[ zoomLevel ] Isuc
  116. keyCallback Key'Minus _ _ _ =
  117. set ፦[ needToClearTexture ] true ⟫
  118. modify ፦[ zoomLevel ] Ipred
  119. keyCallback Key'Left _ _ _ app =
  120. ( set ፦[ needToClearTexture ] true
  121. ⟫ modify ፦[ nowFrame ] (loopFrameLeft (frameCount app))
  122. ) app
  123. keyCallback Key'Right _ _ _ app =
  124. ( set ፦[ needToClearTexture ] true
  125. ⟫ modify ፦[ nowFrame ] (loopFrameRight (frameCount app))
  126. ) app
  127. keyCallback _ _ _ _ = id
  128. pic⇒triangles : Int → Picture → List (V2 Float)
  129. pic⇒triangles zoom = foldr addStroke []
  130. where
  131. addStroke :
  132. (stroke : Stroke) (vertices : List (V2 Float)) → List (V2 Float)
  133. addStroke stroke =
  134. let
  135. sp = sPoints stroke
  136. q = toZoom zoom (sZoom stroke)
  137. ss = zip sp (drop 1 sp)
  138. in
  139. concat (map (uncurry (drawLine q)) ss) ++_
  140. getLast : ∀ {ℓ} {A : Set ℓ} (z : A) (xs : List A) → A
  141. getLast z [] = z
  142. getLast z (x ∷ xs) = getLast x xs
  143. index : ∀ {ℓ} {A : Set ℓ} (z : A) (n : ℕ) (xs : List A) → A
  144. index z _ [] = z
  145. index z zero (x ∷ xs) = x
  146. index z (suc n) (x ∷ xs) = index x n xs
  147. module _ where
  148. import Data.Vec as V
  149. import Data.Fin as Fin
  150. vec-length : ∀ {ℓ n} {A : Set ℓ} → V.Vec A n → ℕ
  151. vec-length {_} {n} _ = n
  152. getAround : ∀ {ℓ} {A : Set ℓ} (z : A) (n : ℕ) (xs : List A) → A × A
  153. getAround z n xs
  154. with length xs | V.fromList xs
  155. ... | .zero | V.[] = z , z
  156. ... | .(suc _) | xs′@(_ V.∷ _) =
  157. let
  158. kk x = V.lookup xs′ (x mod (vec-length xs′))
  159. in
  160. P.map kk kk (pred n , suc n)
  161. v2avg : V2 Coord → V2 Coord → V2 Coord
  162. v2avg a b = v2
  163. (avgC (V2.x a) (V2.x b))
  164. (avgC (V2.y a) (V2.y b))
  165. sample-at :
  166. ∀ {m} (n : ℕ)
  167. {m≠0 : m ≡ 0 → ⊥}
  168. {n≠0 : False (n ≟ 0)}
  169. (xs : V.Vec (V2 Coord) m)
  170. (i : ℕ)
  171. → V2 Coord
  172. sample-at {m} n {m≠0} {n≠0} xs i =
  173. let
  174. p′ = _div_ (i * m) n {n≠0}
  175. p = p′ ⊓ pred m
  176. p-ok : p < m
  177. p-ok = ≤-trans
  178. (s≤s (m⊓n≤n p′ (pred m)))
  179. (≤-reflexive (m≢0⇒suc[pred[m]]≡m m≠0))
  180. in
  181. V.lookup xs (Fin.fromℕ≤ p-ok)
  182. doIt : List (V2 Coord) → List (V2 Coord) → List (V2 Coord)
  183. doIt a b
  184. with length a | V.fromList a | length b | V.fromList b
  185. ... | .zero | V.[] | .zero | V.[] = []
  186. ... | .(suc _) | _ V.∷ _ | .zero | V.[] = []
  187. ... | .zero | V.[] | .(suc _) | _ V.∷ _ = []
  188. ... | .(suc _) | xs@(_ V.∷ _) | .(suc _) | ys@(_ V.∷ _) =
  189. let
  190. l = vec-length xs ⊔ vec-length ys
  191. in
  192. V.toList $
  193. V.map (λ n →
  194. v2avg
  195. (sample-at l {λ ()} xs n)
  196. (sample-at l {λ ()} ys n))
  197. (V.fromList $ upTo l)
  198. -- UGH ; ignoring zoom ; ...
  199. iStrokes : Stroke → Stroke → Stroke
  200. iStrokes a b = modify ፦[ sPoints ] (doIt (sPoints b)) a
  201. interpolate : Int → Picture → Picture → List (V2 Float)
  202. interpolate zoom before after =
  203. pic⇒triangles zoom (map (uncurry iStrokes) (zip before after))
  204. half : Float
  205. half = ℕratioToFloat 1 2
  206. penColor : V3 Float
  207. penColor = v3 half half half
  208. toTriangles′ : Int → ℕ → List Picture → List (V2 Float)
  209. toTriangles′ zoom n frames
  210. with drop n frames
  211. ... | [] = []
  212. ... | frame ∷ tail
  213. with frame
  214. ... | [] = uncurry (interpolate zoom) (getAround frame n frames)
  215. ... | _ ∷ _ = pic⇒triangles zoom frame
  216. toTriangles : AllApp → RenderResult AllApp
  217. RenderResult.newState (toTriangles x) = x -- TODO: dirty
  218. RenderResult.result (toTriangles x) = L.map (λ p → rgbPoint p penColor) $ toTriangles′
  219. (zoomLevel x) -- -256
  220. (nowFrame x)
  221. (frames x)
  222. defaultFrameCount = 24
  223. drawApp : DrawApp AllApp
  224. drawApp = record
  225. { empty = emptyApp defaultFrameCount
  226. ; render = toTriangles
  227. ; frameCount = frameCount
  228. ; nowFrame = nowFrame
  229. ; dontClearTexture = set ፦[ needToClearTexture ] false
  230. ; getNeedToClearTexture = needToClearTexture
  231. ; mouseCallback = GLFW.mouseCallbackWrap mouseCallback
  232. ; cursorCallback = GLFW.cursorCallbackWrap cursorCallback
  233. ; keyCallback = GLFW.keyCallbackWrap keyCallback
  234. ; isDirty = λ _ _ → true
  235. }
  236. main = run ∘ lift ∘ everything $ drawApp
  237. where open IO