diff options
Diffstat (limited to 'MeshSketch.hs')
-rw-r--r-- | MeshSketch.hs | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/MeshSketch.hs b/MeshSketch.hs new file mode 100644 index 0000000..e23820c --- /dev/null +++ b/MeshSketch.hs | |||
@@ -0,0 +1,115 @@ | |||
1 | {-# LANGUAGE LambdaCase #-} | ||
2 | {-# LANGUAGE OverloadedLabels #-} | ||
3 | module MeshSketch where | ||
4 | |||
5 | import Control.Monad | ||
6 | import Data.Coerce | ||
7 | import Data.IORef | ||
8 | import Foreign.C.Types | ||
9 | import GI.Gdk | ||
10 | import GI.GObject.Functions | ||
11 | import GI.Gtk | ||
12 | import Numeric.LinearAlgebra | ||
13 | |||
14 | data MeshMaker = MeshMaker | ||
15 | { mmWidget :: GLArea | ||
16 | , mmRealized :: IORef (Maybe State) | ||
17 | } | ||
18 | |||
19 | data Camera = Camera | ||
20 | { camHeightAngle :: Float | ||
21 | , camTarget :: Vector Float | ||
22 | , camDirection :: Vector Float | ||
23 | , camDistance :: Float | ||
24 | , camWidth :: Float | ||
25 | , camHeight :: Float | ||
26 | , camWorldToScreen :: Maybe (Matrix Float) | ||
27 | , camScreenToWorld :: Maybe (Matrix Float) | ||
28 | } | ||
29 | |||
30 | data State = State | ||
31 | { stCamera :: IORef Camera | ||
32 | } | ||
33 | |||
34 | initCamera = Camera | ||
35 | { camHeightAngle = pi/6 | ||
36 | , camTarget = fromList [0,0,0] | ||
37 | , camDirection = fromList [0,0,-1] | ||
38 | , camDistance = 10 | ||
39 | , camWidth = 0 | ||
40 | , camHeight = 0 | ||
41 | , camWorldToScreen = Nothing | ||
42 | , camScreenToWorld = Nothing | ||
43 | } | ||
44 | |||
45 | new :: IO GLArea | ||
46 | new = do | ||
47 | w <- gLAreaNew | ||
48 | ref <- newIORef Nothing | ||
49 | let mm = MeshMaker w ref | ||
50 | -- _ <- on w #createContext $ onCreateContext mm | ||
51 | _ <- on w #realize $ onRealize mm | ||
52 | _ <- on w #unrealize $ onUnrealize mm | ||
53 | -- _ <- on w #destroy $ onDestroy mm | ||
54 | return w | ||
55 | |||
56 | onRealize :: MeshMaker -> IO () | ||
57 | onRealize mm@(MeshMaker w ref) = do | ||
58 | putStrLn "realize!" | ||
59 | readIORef ref >>= \case | ||
60 | Just st -> onUnrealize mm -- Shouldn't happen. | ||
61 | Nothing -> return () | ||
62 | widgetAddEvents w | ||
63 | [ EventMaskPointerMotionMask | ||
64 | , EventMaskButtonPressMask | ||
65 | , EventMaskButtonReleaseMask | ||
66 | , EventMaskTouchMask | ||
67 | , EventMaskScrollMask | ||
68 | ] | ||
69 | _ <- on w #event $ onEvent mm | ||
70 | cam <- newIORef initCamera | ||
71 | writeIORef ref $ Just State | ||
72 | { stCamera = cam | ||
73 | } | ||
74 | |||
75 | onUnrealize :: MeshMaker -> IO () | ||
76 | onUnrealize (MeshMaker w ref) = do | ||
77 | putStrLn "unrealize!" | ||
78 | readIORef ref >>= \case | ||
79 | Just st -> do | ||
80 | return () | ||
81 | Nothing -> return () -- Shouldn't happen. | ||
82 | writeIORef ref Nothing | ||
83 | |||
84 | |||
85 | onRender :: MeshMaker -> GLContext -> IO Bool | ||
86 | onRender (MeshMaker w ref) gl = do | ||
87 | return True | ||
88 | |||
89 | |||
90 | onEvent mm@(MeshMaker w ref) ev = do | ||
91 | msrc <- eventGetSourceDevice ev | ||
92 | inputSource <- forM msrc $ \src -> do | ||
93 | src <- get src #inputSource | ||
94 | return src | ||
95 | etype <- get ev #type | ||
96 | -- putStrLn $ "onEvent! " ++ show (etype,inputSource) | ||
97 | let put x = putStrLn (show inputSource ++ " " ++ show x) | ||
98 | case etype of | ||
99 | |||
100 | EventTypeMotionNotify -> do | ||
101 | mev <- get ev #motion | ||
102 | x <- get mev #x | ||
103 | y <- get mev #y | ||
104 | put (x,y) | ||
105 | return () | ||
106 | |||
107 | EventTypeScroll -> do | ||
108 | sev <- get ev #scroll | ||
109 | d <- get sev #direction | ||
110 | put d | ||
111 | return () | ||
112 | |||
113 | _ -> return () | ||
114 | |||
115 | return False | ||