Skip to content

Commit 455c1a0

Browse files
authored
Fix createCursor inputs, add createCursorFrom (#273)
Fixes #232
1 parent 941327b commit 455c1a0

File tree

1 file changed

+73
-7
lines changed

1 file changed

+73
-7
lines changed

src/SDL/Input/Mouse.hs

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
{-# LANGUAGE DeriveGeneric #-}
44
{-# LANGUAGE MultiParamTypeClasses #-}
55
{-# LANGUAGE OverloadedStrings #-}
6-
{-# LANGUAGE PatternSynonyms #-}
76

87
module SDL.Input.Mouse
98
( -- * Relative Mouse Mode
@@ -35,6 +34,7 @@ module SDL.Input.Mouse
3534
, SystemCursor(..)
3635
, activeCursor
3736
, createCursor
37+
, createCursorFrom
3838
, freeCursor
3939
, createColorCursor
4040
, createSystemCursor
@@ -45,6 +45,7 @@ import Control.Monad.IO.Class (MonadIO, liftIO)
4545
import Data.Bits
4646
import Data.Bool
4747
import Data.Data (Data)
48+
import Data.List (nub)
4849
import Data.StateVar
4950
import Data.Typeable
5051
import Data.Word
@@ -257,21 +258,86 @@ activeCursor = makeStateVar getCursor setCursor
257258
setCursor = Raw.setCursor . unwrapCursor
258259

259260
-- | Create a cursor using the specified bitmap data and mask (in MSB format).
260-
--
261-
--
262261
createCursor :: MonadIO m
263-
=> V.Vector Bool -- ^ Whether this part of the cursor is black. Use 'False' for white and 'True' for black.
264-
-> V.Vector Bool -- ^ Whether or not pixels are visible. Use 'True' for visible and 'False' for transparent.
262+
=> V.Vector Word8 -- ^ Whether this part of the cursor is black. Use 'False' for white and 'True' for black.
263+
-> V.Vector Word8 -- ^ Whether or not pixels are visible. Use 'True' for visible and 'False' for transparent.
265264
-> V2 CInt -- ^ The width and height of the cursor.
266265
-> Point V2 CInt -- ^ The X- and Y-axis location of the upper left corner of the cursor relative to the actual mouse position
267266
-> m Cursor
268267
createCursor dta msk (V2 w h) (P (V2 hx hy)) =
269268
liftIO . fmap Cursor $
270269
throwIfNull "SDL.Input.Mouse.createCursor" "SDL_createCursor" $
271-
V.unsafeWith (V.map (bool 0 1) dta) $ \unsafeDta ->
272-
V.unsafeWith (V.map (bool 0 1) msk) $ \unsafeMsk ->
270+
V.unsafeWith dta $ \unsafeDta ->
271+
V.unsafeWith msk $ \unsafeMsk ->
273272
Raw.createCursor unsafeDta unsafeMsk w h hx hy
274273

274+
{- | Create a cursor from a bit art painting of it.
275+
276+
The number of columns must be a multiple of 8.
277+
278+
Symbols used: @ @ (space) - transparent, @.@ - visible black, @#@ (or anything else) - visible white.
279+
280+
A minimal cursor template:
281+
@
282+
source8x8 :: [[Char]]
283+
source8x8 =
284+
[ " "
285+
, " "
286+
, " "
287+
, " "
288+
, " "
289+
, " "
290+
, " "
291+
, " "
292+
]
293+
@
294+
-}
295+
createCursorFrom :: MonadIO m
296+
=> Point V2 CInt -- ^ The X- and Y-axis location of the upper left corner of the cursor relative to the actual mouse position
297+
-> [[Char]]
298+
-> m Cursor
299+
createCursorFrom point source = do
300+
createCursor color mask (V2 w h) point
301+
where
302+
h = fromIntegral (length source)
303+
w = case nub $ map length source of
304+
[okay] ->
305+
fromIntegral okay
306+
mismatch ->
307+
error $ "Inconsistent row widths: " <> show mismatch
308+
309+
color = packBools colorBits
310+
mask = packBools maskBits
311+
(colorBits, maskBits) = unzip $ map charToBool $ concat source
312+
313+
packBools = V.fromList . boolListToWord8List
314+
315+
charToBool ' ' = (False, False) -- transparent
316+
charToBool '.' = (True, True) -- visible black
317+
charToBool _ = (True, False) -- visible white
318+
319+
boolListToWord8List xs =
320+
case xs of
321+
b1 : b2 : b3 : b4 : b5 : b6 : b7 : b8 : rest ->
322+
let
323+
packed =
324+
i b1 128 +
325+
i b2 64 +
326+
i b3 32 +
327+
i b4 16 +
328+
i b5 8 +
329+
i b6 4 +
330+
i b7 2 +
331+
i b8 1
332+
in
333+
packed : boolListToWord8List rest
334+
[] ->
335+
[]
336+
_leftovers ->
337+
error "The number of columns must be a multiple of 8."
338+
where
339+
i True multiple = multiple
340+
i False _ = 0
275341

276342
-- | Free a cursor created with 'createCursor', 'createColorCusor' and 'createSystemCursor'.
277343
--

0 commit comments

Comments
 (0)