packages feed

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 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}|]