mischief-input (empty) → 0.1.0.0
raw patch · 8 files changed
+817/−0 lines, 8 filesdep +basedep +bytestringdep +containers
Dependencies added: base, bytestring, containers, data-default, mischief-ecs, mischief-input, mischief-sdl, primitive, sdl3-bindgen-sys, transformers
Files
- CHANGELOG.md +5/−0
- LICENSE +29/−0
- README.md +8/−0
- mischief-input.cabal +144/−0
- src/Mischief/Input.hs +94/−0
- src/Mischief/Input/Keys.hs +403/−0
- src/Mischief/Input/Mouse.hs +101/−0
- test/Main.hs +33/−0
+ CHANGELOG.md view
@@ -0,0 +1,5 @@+# Revision history for mischief++## 0.1.0.0 -- YYYY-mm-dd++* First version. Released on an unsuspecting world.
+ LICENSE view
@@ -0,0 +1,29 @@+Copyright (c) 2026, Damon+++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of the copyright holder nor the names of its+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,8 @@+# mischief-input ++Library that adds input functionality to Mischief. Go to the root module above, `Mischief.Input`, for more information and examples. ++This library lives in the official [repo](https://codeberg.org/mischief/mischief) and is considered a "core library" of the ecosystem. ++To contribute, you can file issues, such as bug reports and feature requests, in the official [repository](https://codeberg.org/mischief/mischief).+You can also join the official server on discord to be kept up to date with updates and chat with the rest of the community. Link in the aforementioned repo.
+ mischief-input.cabal view
@@ -0,0 +1,144 @@+cabal-version: 3.0+-- The cabal-version field refers to the version of the .cabal specification,+-- and can be different from the cabal-install (the tool) version and the+-- Cabal (the library) version you are using. As such, the Cabal (the library)+-- version used must be equal or greater than the version stated in this field.+-- Starting from the specification version 2.2, the cabal-version field must be+-- the first thing in the cabal file.+-- Initial package description 'mischief' generated by+-- 'cabal init'. For further documentation, see:+-- http://haskell.org/cabal/users-guide/+--+-- The name of the package.+name: mischief-input+-- The package version.+-- See the Haskell package versioning policy (PVP) for standards+-- guiding when and how versions should be incremented.+-- https://pvp.haskell.org+-- PVP summary: +-+------- breaking API changes+-- | | +----- non-breaking API additions+-- | | | +--- code changes with no API change+version: 0.1.0.0+-- A short (one-line) description of the package.+-- synopsis:+-- A longer description of the package.+-- description:+-- The license under which the package is released.+license: BSD-3-Clause+-- The file containing the license text.+license-file: LICENSE+-- The package author(s).+author: Damon+-- An email address to which users can send suggestions, bug reports, and patches.+maintainer: pvdoriginal2019@gmail.com+homepage: https://codeberg.org/mischief/mischief+synopsis: Input for the Mischief game engine+-- A copyright notice.+-- copyright:+build-type: Simple+-- Extra doc files to be distributed with the package, such as a CHANGELOG or a README.+extra-doc-files:+ CHANGELOG.md+ README.md++-- Extra source files to be distributed with the package, such as examples, or a tutorial module.+-- extra-source-files:+common warnings+ ghc-options:+ "-Wall,"+ -Wno-name-shadowing++library+ -- Import common warning flags.+ import: warnings+ -- Modules exported by the library.+ exposed-modules:+ Mischief.Input+ Mischief.Input.Keys+ Mischief.Input.Mouse++ -- Modules included in this library but not exported.+ -- other-modules:+ other-modules:+ -- LANGUAGE extensions used by modules in this package.z+ default-extensions:+ DefaultSignatures+ DeriveAnyClass+ DuplicateRecordFields+ FunctionalDependencies+ ImportQualifiedPost+ MagicHash+ MultiWayIf+ NoFieldSelectors+ NoGeneralizedNewtypeDeriving+ OverloadedRecordDot+ OverloadedStrings+ PatternSynonyms+ RequiredTypeArguments+ TemplateHaskell+ TypeFamilyDependencies+ UndecidableInstances++ -- other-extensions:+ -- Other library packages from which modules are imported.+ build-depends:+ base >=4.21.0 && <4.22,+ bytestring >=0.12.2 && <0.13,+ containers >=0.7 && <0.8,+ data-default >=0.8.0 && <0.9,+ mischief-ecs >=0.2.1 && <0.3,+ mischief-sdl >=0.1.0 && <0.2,+ primitive >=0.9.1 && <0.10,+ sdl3-bindgen-sys >=0.0.1 && <0.1,++ -- Directories containing source files.+ hs-source-dirs:+ src++ -- Base language which the package is written in.+ default-language:+ GHC2024++ ghc-options: -fno-omit-yields++test-suite mischief-test+ -- Import common warning flags.+ import: warnings+ ghc-options:+ -fno-omit-yields+ -Wno-unused-do-bind++ -- Base language which the package is written in.+ default-language: GHC2024+ -- Modules included in this executable, other than Main.+ -- other-modules:+ -- LANGUAGE extensions used by modules in this package.+ default-extensions:+ DeriveAnyClass+ DuplicateRecordFields+ MagicHash+ NoFieldSelectors+ NoGeneralizedNewtypeDeriving+ OverloadedRecordDot+ OverloadedStrings+ QuasiQuotes+ RequiredTypeArguments+ TypeFamilyDependencies++ -- other-extensions:+ -- The interface type and version of the test suite.+ type: exitcode-stdio-1.0+ -- Directories containing source files.+ hs-source-dirs: test+ -- The entrypoint to the test suite.+ main-is: Main.hs+ -- Test dependencies.+ build-depends:+ base >=4.21.0.0 && <4.22,+ containers,+ data-default,+ mischief-ecs,+ mischief-input,+ primitive,+ sdl3-bindgen-sys,+ transformers,
+ src/Mischief/Input.hs view
@@ -0,0 +1,94 @@+{-# OPTIONS_GHC -Wno-unused-imports #-}++module Mischief.Input+ ( -- * Mischief Input+ -- $intro++ -- * Dependencies+ -- $deps++ -- * How to Use+ -- $use++ -- * Keyboard+ -- $key++ -- * Mouse+ -- $mouse+ InputPlugin,+ Keys,+ Mouse,+ module Mischief.SDL.Window,+ )+where++import Mischief.ECS+import Mischief.Input.Keys (Keys, KeysPlugin)+import Mischief.Input.Keys qualified as Keys+import Mischief.Input.Mouse (Mouse, MousePlugin)+import Mischief.Input.Mouse qualified as Mouse+import Mischief.SDL.Window++data InputPlugin = InputPlugin deriving (Eq)++instance Plugin InputPlugin where+ deps = [dep @KeysPlugin, dep @MousePlugin]++-- $intro+-- This is the official input library for the Mischief game engine. It allows you to read input, such as from a mouse or keyboard.++-- $deps+-- * [mischief-ecs]("Mischief.ECS")+-- * [mischief-sdl]("Mischief.SDL")+--+-- You will need to manually install the following library (click for install guide):+--+-- * [SDL]("Mischief.SDL")++-- $use+-- To use this library, add the @'InputPlugin'@ to your App. This will add the individual plugins for all input types, such as @'KeysPlugin'@ and @'MousePlugin'@.++-- $key+-- To read keyboard input, import the following module:+--+-- @+-- import "Mischief.Input.Keys" qualified as Keys+-- @+--+-- Then, inside a system, query for the Keys resource:+--+-- @+-- Just keys <- 'res' \@'Keys'+-- @+--+-- You can use the 'Keys.justPressed', 'Keys.pressed', 'Keys.released', 'Keys.justReleased' functions to find out the state of a certain key. For instance:+--+-- @+-- Keys.'Keys.justPressed' keys Keys.'Keys.Space'+-- @++-- $mouse+-- To read mouse input, import the following module:+--+-- @+-- import "Mischief.Input.Mouse" qualified as Mouse+-- @+--+-- Then, query the Mouse resource:+--+-- @+-- mouse <- 'res' \@'Mouse'+-- @+--+-- You can use 'Keys.justPressed' and so on (same as the keys functions) to get the state of a mouse button. For instance:+--+-- @+-- Mouse.'Mouse.justPressed' mouse Mouse.'Mouse.Left'+-- @+--+-- You can also use the @pos@ function to get the current position of the cursor. This will be a screenspace position that is (0, 0) in the top-left corner+-- of the window:+--+-- @+-- pos <- Mouse.'Mouse.pos'+-- @
+ src/Mischief/Input/Keys.hs view
@@ -0,0 +1,403 @@+{-# OPTIONS_GHC -Wno-missing-pattern-synonym-signatures #-}++module Mischief.Input.Keys+ ( -- * Resource+ Keys,++ -- * Functions+ pressed,+ released,+ justPressed,+ justReleased,++ -- * Plugin+ KeysPlugin,++ -- * Keys+ -- $keys+ pattern Mischief.Input.Keys.A,+ pattern Mischief.Input.Keys.B,+ pattern Mischief.Input.Keys.C,+ pattern Mischief.Input.Keys.D,+ pattern Mischief.Input.Keys.E,+ pattern Mischief.Input.Keys.F,+ pattern Mischief.Input.Keys.G,+ pattern Mischief.Input.Keys.H,+ pattern Mischief.Input.Keys.I,+ pattern Mischief.Input.Keys.J,+ pattern Mischief.Input.Keys.K,+ pattern Mischief.Input.Keys.L,+ pattern Mischief.Input.Keys.M,+ pattern Mischief.Input.Keys.N,+ pattern Mischief.Input.Keys.O,+ pattern Mischief.Input.Keys.P,+ pattern Mischief.Input.Keys.Q,+ pattern Mischief.Input.Keys.R,+ pattern Mischief.Input.Keys.S,+ pattern Mischief.Input.Keys.T,+ pattern Mischief.Input.Keys.U,+ pattern Mischief.Input.Keys.V,+ pattern Mischief.Input.Keys.W,+ pattern Mischief.Input.Keys.X,+ pattern Mischief.Input.Keys.Y,+ pattern Mischief.Input.Keys.Z,+ pattern Mischief.Input.Keys.Key0,+ pattern Mischief.Input.Keys.Key1,+ pattern Mischief.Input.Keys.Key2,+ pattern Mischief.Input.Keys.Key3,+ pattern Mischief.Input.Keys.Key4,+ pattern Mischief.Input.Keys.Key5,+ pattern Mischief.Input.Keys.Key6,+ pattern Mischief.Input.Keys.Key7,+ pattern Mischief.Input.Keys.Key8,+ pattern Mischief.Input.Keys.Key9,+ pattern Mischief.Input.Keys.Enter,+ pattern Mischief.Input.Keys.Escape,+ pattern Mischief.Input.Keys.Backspace,+ pattern Mischief.Input.Keys.Tab,+ pattern Mischief.Input.Keys.Space,+ pattern Mischief.Input.Keys.Minus,+ pattern Mischief.Input.Keys.Equals,+ pattern Mischief.Input.Keys.LeftBracket,+ pattern Mischief.Input.Keys.RightBracket,+ pattern Mischief.Input.Keys.BackSlash,+ pattern Mischief.Input.Keys.Semicolon,+ pattern Mischief.Input.Keys.Apostrophe,+ pattern Mischief.Input.Keys.Grave,+ pattern Mischief.Input.Keys.Comma,+ pattern Mischief.Input.Keys.Period,+ pattern Mischief.Input.Keys.Slash,+ pattern Mischief.Input.Keys.Capslock,+ pattern Mischief.Input.Keys.F1,+ pattern Mischief.Input.Keys.F2,+ pattern Mischief.Input.Keys.F3,+ pattern Mischief.Input.Keys.F4,+ pattern Mischief.Input.Keys.F5,+ pattern Mischief.Input.Keys.F6,+ pattern Mischief.Input.Keys.F7,+ pattern Mischief.Input.Keys.F8,+ pattern Mischief.Input.Keys.F9,+ pattern Mischief.Input.Keys.F10,+ pattern Mischief.Input.Keys.F11,+ pattern Mischief.Input.Keys.F12,+ pattern Mischief.Input.Keys.Printscreen,+ pattern Mischief.Input.Keys.Scrolllock,+ pattern Mischief.Input.Keys.Pause,+ pattern Mischief.Input.Keys.Insert,+ pattern Mischief.Input.Keys.Home,+ pattern Mischief.Input.Keys.PageUp,+ pattern Mischief.Input.Keys.PageDown,+ pattern Mischief.Input.Keys.Delete,+ pattern Mischief.Input.Keys.End,+ pattern Mischief.Input.Keys.Right,+ pattern Mischief.Input.Keys.Left,+ pattern Mischief.Input.Keys.Down,+ pattern Mischief.Input.Keys.Up,+ pattern Mischief.Input.Keys.Numlockclear,+ pattern Mischief.Input.Keys.KeypadDivide,+ pattern Mischief.Input.Keys.KeypadMultiply,+ pattern Mischief.Input.Keys.Keypad0,+ pattern Mischief.Input.Keys.Keypad1,+ pattern Mischief.Input.Keys.Keypad2,+ pattern Mischief.Input.Keys.Keypad3,+ pattern Mischief.Input.Keys.Keypad4,+ pattern Mischief.Input.Keys.Keypad5,+ pattern Mischief.Input.Keys.Keypad6,+ pattern Mischief.Input.Keys.Keypad7,+ pattern Mischief.Input.Keys.Keypad8,+ pattern Mischief.Input.Keys.Keypad9,+ pattern Mischief.Input.Keys.KeypadPeriod,+ pattern Mischief.Input.Keys.KeypadComma,+ pattern Mischief.Input.Keys.KeypadEnter,+ pattern Mischief.Input.Keys.KeypadEquals,+ pattern Mischief.Input.Keys.KeypadMinus,+ pattern Mischief.Input.Keys.KeypadPlus,+ pattern Mischief.Input.Keys.LCtrl,+ pattern Mischief.Input.Keys.LShift,+ pattern Mischief.Input.Keys.LAlt,+ pattern Mischief.Input.Keys.RCtrl,+ pattern Mischief.Input.Keys.RShift,+ pattern Mischief.Input.Keys.RAlt,+ pattern Mischief.Input.Keys.Application,+ )+where++import Control.Monad.IO.Class+import Data.List ((!?))+import Foreign (nullPtr, peekArray, toBool)+import Foreign.C (CBool)+import Foreign.C.ConstPtr+import GHC.Generics+import Mischief.ECS+import Mischief.ECS.App.Schedules (First)+import Mischief.SDL (SDLPlugin)+import SDL3.Sys qualified as SDL3++data Keys = Keys+ { currentKeys :: [CBool],+ previousKeys :: [CBool]+ }+ deriving (Generic, Default, Component)++-- newtype HotKeys = HotKeys [((SDL3.SDL_Scancode, SDL3.SDL_Keycode), KeyState)] deriving (Generic, Default, Component)++-- setStatePhysical :: KeyState -> SDL3.SDL_Scancode -> IORef Keys -> IO ()+-- setStatePhysical state scancode keys =+-- modifyIORef' keys (\Keys {physical, virtual} -> Keys {physical = Map.insert scancode state physical, virtual})++-- setStateVirtual :: KeyState -> SDL3.SDL_Keycode -> IORef Keys -> IO ()+-- setStateVirtual state keycode keys =+-- modifyIORef' keys (\Keys {physical, virtual} -> Keys {physical, virtual = Map.insert keycode state virtual})++pressed :: Keys -> SDL3.SDL_Scancode -> Bool+pressed Keys {currentKeys} code = maybe False toBool $ currentKeys !? unwrapScancode code++justPressed :: Keys -> SDL3.SDL_Scancode -> Bool+justPressed Keys {currentKeys, previousKeys} code = do+ let c = unwrapScancode code+ maybe False toBool (currentKeys !? c) && not (maybe False toBool $ previousKeys !? c)++released :: Keys -> SDL3.SDL_Scancode -> Bool+released Keys {currentKeys} code = not $ maybe False toBool $ currentKeys !? unwrapScancode code++justReleased :: Keys -> SDL3.SDL_Scancode -> Bool+justReleased Keys {currentKeys, previousKeys} code = do+ let c = unwrapScancode code+ not (maybe False toBool (currentKeys !? c)) && maybe False toBool (previousKeys !? c)++-- | Plugin which keeps track of key inputs and updates the 'Keys' resource.+data KeysPlugin++instance Plugin KeysPlugin where+ init = do+ systems updateKeys+ & schedule @First++ insertRes $ Keys [] []++ deps = [dep @SDLPlugin]++unwrapScancode :: SDL3.SDL_Scancode -> Int+unwrapScancode (SDL3.SDL_Scancode i) = fromIntegral i++updateKeys :: System ()+updateKeys = do+ Just keys <- res @Keys+ ConstPtr a <- liftIO $ SDL3.getKeyboardState nullPtr+ b <- liftIO $ peekArray (unwrapScancode SDL3.SDL_SCANCODE_COUNT) a+ insertRes Keys {currentKeys = b, previousKeys = keys.currentKeys}++pattern A = SDL3.SDL_SCANCODE_A++pattern B = SDL3.SDL_SCANCODE_B++pattern C = SDL3.SDL_SCANCODE_C++pattern D = SDL3.SDL_SCANCODE_D++pattern E = SDL3.SDL_SCANCODE_E++pattern F = SDL3.SDL_SCANCODE_F++pattern G = SDL3.SDL_SCANCODE_G++pattern H = SDL3.SDL_SCANCODE_H++pattern I = SDL3.SDL_SCANCODE_I++pattern J = SDL3.SDL_SCANCODE_J++pattern K = SDL3.SDL_SCANCODE_K++pattern L = SDL3.SDL_SCANCODE_L++pattern M = SDL3.SDL_SCANCODE_M++pattern N = SDL3.SDL_SCANCODE_N++pattern O = SDL3.SDL_SCANCODE_O++pattern P = SDL3.SDL_SCANCODE_P++pattern Q = SDL3.SDL_SCANCODE_Q++pattern R = SDL3.SDL_SCANCODE_R++pattern S = SDL3.SDL_SCANCODE_S++pattern T = SDL3.SDL_SCANCODE_T++pattern U = SDL3.SDL_SCANCODE_U++pattern V = SDL3.SDL_SCANCODE_V++pattern W = SDL3.SDL_SCANCODE_W++pattern X = SDL3.SDL_SCANCODE_X++pattern Y = SDL3.SDL_SCANCODE_Y++pattern Z = SDL3.SDL_SCANCODE_Z++pattern Key1 = SDL3.SDL_SCANCODE_1++pattern Key2 = SDL3.SDL_SCANCODE_2++pattern Key3 = SDL3.SDL_SCANCODE_3++pattern Key4 = SDL3.SDL_SCANCODE_4++pattern Key5 = SDL3.SDL_SCANCODE_5++pattern Key6 = SDL3.SDL_SCANCODE_6++pattern Key7 = SDL3.SDL_SCANCODE_7++pattern Key8 = SDL3.SDL_SCANCODE_8++pattern Key9 = SDL3.SDL_SCANCODE_9++pattern Key0 = SDL3.SDL_SCANCODE_0++pattern Enter = SDL3.SDL_SCANCODE_RETURN++pattern Escape = SDL3.SDL_SCANCODE_ESCAPE++pattern Backspace = SDL3.SDL_SCANCODE_BACKSPACE++pattern Tab = SDL3.SDL_SCANCODE_TAB++pattern Space = SDL3.SDL_SCANCODE_SPACE++pattern Minus = SDL3.SDL_SCANCODE_MINUS++pattern Equals = SDL3.SDL_SCANCODE_EQUALS++pattern LeftBracket = SDL3.SDL_SCANCODE_LEFTBRACKET++pattern RightBracket = SDL3.SDL_SCANCODE_RIGHTBRACKET++pattern BackSlash = SDL3.SDL_SCANCODE_BACKSLASH++pattern Semicolon = SDL3.SDL_SCANCODE_SEMICOLON++pattern Apostrophe = SDL3.SDL_SCANCODE_APOSTROPHE++pattern Grave = SDL3.SDL_SCANCODE_GRAVE++pattern Comma = SDL3.SDL_SCANCODE_COMMA++pattern Period = SDL3.SDL_SCANCODE_PERIOD++pattern Slash = SDL3.SDL_SCANCODE_SLASH++pattern Capslock = SDL3.SDL_SCANCODE_CAPSLOCK++pattern F1 = SDL3.SDL_SCANCODE_F1++pattern F2 = SDL3.SDL_SCANCODE_F2++pattern F3 = SDL3.SDL_SCANCODE_F3++pattern F4 = SDL3.SDL_SCANCODE_F4++pattern F5 = SDL3.SDL_SCANCODE_F5++pattern F6 = SDL3.SDL_SCANCODE_F6++pattern F7 = SDL3.SDL_SCANCODE_F7++pattern F8 = SDL3.SDL_SCANCODE_F8++pattern F9 = SDL3.SDL_SCANCODE_F9++pattern F10 = SDL3.SDL_SCANCODE_F10++pattern F11 = SDL3.SDL_SCANCODE_F11++pattern F12 = SDL3.SDL_SCANCODE_F12++pattern Printscreen = SDL3.SDL_SCANCODE_PRINTSCREEN++pattern Scrolllock = SDL3.SDL_SCANCODE_SCROLLLOCK++pattern Pause = SDL3.SDL_SCANCODE_PAUSE++pattern Insert = SDL3.SDL_SCANCODE_INSERT++pattern Home = SDL3.SDL_SCANCODE_HOME++pattern PageUp = SDL3.SDL_SCANCODE_PAGEUP++pattern Delete = SDL3.SDL_SCANCODE_DELETE++pattern End = SDL3.SDL_SCANCODE_END++pattern PageDown = SDL3.SDL_SCANCODE_PAGEDOWN++pattern Right = SDL3.SDL_SCANCODE_RIGHT++pattern Left = SDL3.SDL_SCANCODE_LEFT++pattern Down = SDL3.SDL_SCANCODE_DOWN++pattern Up = SDL3.SDL_SCANCODE_UP++pattern Numlockclear = SDL3.SDL_SCANCODE_NUMLOCKCLEAR++pattern KeypadDivide = SDL3.SDL_SCANCODE_KP_DIVIDE++pattern KeypadMultiply = SDL3.SDL_SCANCODE_KP_MULTIPLY++pattern KeypadMinus = SDL3.SDL_SCANCODE_KP_MINUS++pattern KeypadPlus = SDL3.SDL_SCANCODE_KP_PLUS++pattern KeypadEnter = SDL3.SDL_SCANCODE_KP_ENTER++pattern Keypad1 = SDL3.SDL_SCANCODE_KP_1++pattern Keypad2 = SDL3.SDL_SCANCODE_KP_2++pattern Keypad3 = SDL3.SDL_SCANCODE_KP_3++pattern Keypad4 = SDL3.SDL_SCANCODE_KP_4++pattern Keypad5 = SDL3.SDL_SCANCODE_KP_5++pattern Keypad6 = SDL3.SDL_SCANCODE_KP_6++pattern Keypad7 = SDL3.SDL_SCANCODE_KP_7++pattern Keypad8 = SDL3.SDL_SCANCODE_KP_8++pattern Keypad9 = SDL3.SDL_SCANCODE_KP_9++pattern Keypad0 = SDL3.SDL_SCANCODE_KP_0++pattern KeypadPeriod = SDL3.SDL_SCANCODE_KP_PERIOD++pattern KeypadEquals = SDL3.SDL_SCANCODE_KP_EQUALS++pattern KeypadComma = SDL3.SDL_SCANCODE_KP_COMMA++pattern LCtrl = SDL3.SDL_SCANCODE_LCTRL++pattern LShift = SDL3.SDL_SCANCODE_LSHIFT++pattern LAlt = SDL3.SDL_SCANCODE_LALT++pattern RCtrl = SDL3.SDL_SCANCODE_RCTRL++pattern RShift = SDL3.SDL_SCANCODE_RSHIFT++pattern RAlt = SDL3.SDL_SCANCODE_RALT++pattern Application = SDL3.SDL_SCANCODE_APPLICATION++-- $keys+-- Below is an opinionated collection of keys selected from SDL3's scancodes. These can be used with 'pressed', 'justPressed', and so on.+--+-- Most key names are the same as SDL's, the only significant exception is @Return@ which has been renamed to @Enter@.+--+-- If you wish to access a key that's not defined here, you can grab it directly from "SDL3.Sys.Bindgen.Scancode".
+ src/Mischief/Input/Mouse.hs view
@@ -0,0 +1,101 @@+{-# OPTIONS_GHC -Wno-missing-pattern-synonym-signatures #-}++module Mischief.Input.Mouse+ ( Mouse,+ MousePlugin,+ pressed,+ released,+ justPressed,+ justReleased,+ pos,+ delta,+ getPos,+ getDelta,+ pattern Mischief.Input.Mouse.Left,+ pattern Mischief.Input.Mouse.Right,+ pattern Mischief.Input.Mouse.Middle,+ pattern Mischief.Input.Mouse.X1,+ pattern Mischief.Input.Mouse.X2,+ )+where++import Control.Monad.IO.Class (MonadIO (..))+import Foreign (Bits ((.&.)), Storable (peek), alloca)+import Foreign.C (CFloat)+import Mischief.ECS+import Mischief.ECS.App.Schedules+import Mischief.SDL+import SDL3.Sys qualified as SDL3++data MouseData = MouseData+ { flags :: SDL3.SDL_MouseButtonFlags,+ x :: CFloat,+ y :: CFloat+ }++data Mouse = Mouse+ { current :: MouseData,+ old :: MouseData+ }+ deriving (Component)++-- | Plugin which keeps track of key inputs and updates the 'Keys' resource.+data MousePlugin++instance Plugin MousePlugin where+ init = do+ systems updateMouse+ & schedule @First++ insertRes $ Mouse (MouseData 0 0 0) (MouseData 0 0 0)++ deps = [dep @SDLPlugin]++updateMouse :: System ()+updateMouse = do+ Just mouse <- res @Mouse++ (flags, x, y) <- liftIO $ alloca @CFloat $ \x -> alloca @CFloat $ \y -> do+ a <- liftIO $ SDL3.getMouseState x y+ x <- peek x+ y <- peek y+ pure (a, x, y)++ insertRes $ Mouse {old = mouse.current, current = MouseData flags x y}++pressed :: Mouse -> SDL3.SDL_MouseButtonFlags -> Bool+pressed Mouse {current = MouseData {flags}} = getVal flags++released :: Mouse -> SDL3.SDL_MouseButtonFlags -> Bool+released Mouse {current = MouseData {flags}} = getVal flags++justPressed :: Mouse -> SDL3.SDL_MouseButtonFlags -> Bool+justPressed Mouse {current = MouseData {flags}, old = MouseData {flags = flags'}} flag = getVal flags flag && not (getVal flags' flag)++justReleased :: Mouse -> SDL3.SDL_MouseButtonFlags -> Bool+justReleased Mouse {current = MouseData {flags}, old = MouseData {flags = flags'}} flag = not (getVal flags flag) && getVal flags' flag++getVal :: SDL3.SDL_MouseButtonFlags -> SDL3.SDL_MouseButtonFlags -> Bool+getVal x i = (x .&. i) /= 0++pos :: (MonadSystem w m) => m (Float, Float)+pos = getPos . unwrap <$> res @Mouse++getPos :: Mouse -> (Float, Float)+getPos Mouse {current = MouseData {x, y}} = (realToFrac x, realToFrac y)++delta :: (MonadSystem w m) => m (Float, Float)+delta = getDelta . unwrap <$> res @Mouse++getDelta :: Mouse -> (Float, Float)+getDelta Mouse {current = MouseData {x, y}, old = MouseData {x = x', y = y'}} = (realToFrac $ x - x', realToFrac $ y - y')++pattern Left = SDL3.SDL_BUTTON_LMASK++pattern Middle = SDL3.SDL_BUTTON_MMASK++pattern Right = SDL3.SDL_BUTTON_RMASK++pattern X1 = SDL3.SDL_BUTTON_X1MASK++pattern X2 = SDL3.SDL_BUTTON_X2MASK
+ test/Main.hs view
@@ -0,0 +1,33 @@+module Main where++import Control.Monad+import Mischief.ECS+import Mischief.Input+import Mischief.Input.Keys qualified as Keys+import Mischief.Input.Mouse qualified as Mouse+import Prelude hiding (and)++main :: IO ()+main = do+ app <- newApp+ addPlugin @MainPlugin app+ runApp app++data MainPlugin++instance Plugin MainPlugin where+ init = do+ spawn_ Window+ schedule @Update $ systems test+ deps = [dep @InputPlugin]++test :: System ()+test = do+ Just keys <- res @Keys+ when (Keys.pressed keys Keys.A) $ do+ info "A"++ Just mouse <- res @Mouse+ when (Mouse.justPressed mouse Mouse.Left) $ do+ pos <- Mouse.pos+ info [i|Click at #{pos}|]