Reorganise update-input-gamestate structure

This commit is contained in:
2023-02-23 11:47:05 +00:00
parent fc0fd5fa37
commit d513914886
3 changed files with 397 additions and 0 deletions
+250
View File
@@ -0,0 +1,250 @@
module Dodge.Update.Input.InGame
( updateUseInputInGame
) where
import qualified Data.IntMap.Strict as IM
import Data.List (sort)
import qualified Data.Map.Strict as M
import Data.Maybe
import Dodge.Base.You
import Dodge.Button.Event
import Dodge.Creature.Action
import Dodge.Data.Combine
import Dodge.Data.Universe
import Dodge.Default.World
import Dodge.DisplayInventory
import Dodge.Event.Test
import Dodge.InputFocus
import Dodge.Inventory
import Dodge.Inventory.Add
import Dodge.Menu
import Dodge.Reloading
import Dodge.Save
import Dodge.SelectionSections
import Dodge.Terminal.LeftButton
import Dodge.Update.Input.Text
import Dodge.WorldPos
import Geometry
import LensHelp
import SDL
updateUseInputInGame :: HUDElement -> Universe -> Universe
updateUseInputInGame h u = case h of
DisplayCarte -> over uvWorld updatePressedButtonsCarte u
DisplayInventory{_subInventory = si} -> case si of
DisplayTerminal tmid
| lbinitialpress && inTermFocus w ->
over uvWorld (doTerminalEffectLB (w ^?! cWorld . lWorld . terminals . ix tmid)) u
| inTermFocus (_uvWorld u) -> updateKeysInTerminal tmid u
| lbinitialpress ->
u & uvWorld . cWorld . lWorld . terminals . ix tmid . tmInput . tiFocus %~ const True
CombineInventory{_ciSections = sss}
| inSubInvRegex (u ^. uvWorld) -> u & uvWorld . hud . hudElement . subInventory . ciSections %~ doRegexInput u (-1)
& uvWorld . worldEventFlags . at CombineInventoryChange ?~ ()
| lbinitialpress -> (uvWorld . worldEventFlags . at InventoryChange ?~ ()) . maybeExitCombine $ over uvWorld (tryCombine sss) u
& uvWorld . worldEventFlags . at CombineInventoryChange ?~ ()
-- _ -> case regexFocus w of
-- Nothing -> M.foldlWithKey' updateKeyInGame u pkeys
-- Just (filtpoint,selpoint,i) -> u & uvWorld . p %~ doRegexInput
_
| inInvRegex (u ^. uvWorld) ->
u & uvWorld . hud . hudElement . diSections %~ doRegexInput u (-1)
& uvWorld . worldEventFlags . at InventoryChange ?~ ()
& uvWorld %~ setInvPosFromSS
_
| inCloseRegex (u ^. uvWorld) ->
u & uvWorld . hud . hudElement . diSections %~ doRegexInput u 2
& uvWorld . worldEventFlags . at InventoryChange ?~ ()
& uvWorld %~ setInvPosFromSS
_ -> M.foldlWithKey' updateKeyInGame u pkeys
where
w = u ^. uvWorld
pkeys = u ^. uvWorld . input . pressedKeys
lbinitialpress = u ^? uvWorld . input . mouseButtons . ix ButtonLeft == Just False
updatePressedButtonsCarte :: World -> World
updatePressedButtonsCarte w = updatePressedButtonsCarte' (_mouseButtons (_input w)) w
updatePressedButtonsCarte' :: M.Map MouseButton Bool -> World -> World
updatePressedButtonsCarte' pkeys w
| isDown ButtonRight =
w
& input . clickMousePos .~ _mousePos (_input w)
& hud . carteCenter %~ (-.- trans)
| isDown ButtonLeft =
w
& input . clickMousePos .~ _mousePos (_input w)
& hud . carteRot -~ rot
& hud . carteZoom *~ czoom
| otherwise = w
where
isDown but = but `M.member` pkeys
rot = angleBetween (_mousePos (_input w)) (_clickMousePos (_input w))
czoom = magV (_mousePos (_input w)) / magV (_clickMousePos (_input w))
trans =
rotateV (w ^. hud . carteRot) $
1 / (w ^. hud . carteZoom) *.* (_mousePos (_input w) -.- _clickMousePos (_input w))
updateKeysInTerminal :: Int -> Universe -> Universe
updateKeysInTerminal tmid u =
u & doTextInputOver tmpoint
& checkEndStatus
where
tmpoint = uvWorld . cWorld . lWorld . terminals . ix tmid . tmInput . tiText
pkeys = u ^. uvWorld . input . pressedKeys
checkEndStatus
| pkeys ^. at ScancodeReturn == Just InitialPress =
over uvWorld (\w -> terminalReturnEffect (w ^?! cWorld . lWorld . terminals . ix tmid) w)
| otherwise = id
updateKeyInGame :: Universe -> Scancode -> PressType -> Universe
updateKeyInGame uv sc pt = case pt of
InitialPress -> updateInitialPressInGame uv sc
LongPress -> updateLongPressInGame uv sc
_ -> uv
updateInitialPressInGame :: Universe -> Scancode -> Universe
updateInitialPressInGame uv sc = case sc of
ScancodeF5 -> doQuicksave uv
ScancodeF9 -> loadSaveSlot QuicksaveSlot uv
ScancodeEscape -> pauseGame uv
ScancodeSpace -> over uvWorld spaceAction uv
ScancodeP -> pauseGame uv
ScancodeF -> over uvWorld youDropItem uv
ScancodeM -> toggleMap uv
ScancodeR -> over (uvWorld . cWorld . lWorld . creatures . ix 0) crToggleReloading uv
ScancodeT -> over uvWorld testEvent uv
ScancodeX -> uv & uvWorld %~ toggleTweakInv
ScancodeC -> toggleCombineInv uv
-- the following should be put in a more sensible place
ScancodeSlash -> uv & uvWorld %~ updateEnterRegex
ScancodeBackspace -> uv & uvWorld %~ updateBackspaceRegex
_ -> uv
updateLongPressInGame :: Universe -> Scancode -> Universe
updateLongPressInGame uv sc = case sc of
ScancodeF -> over uvWorld youDropItem uv
ScancodeSpace -> over uvWorld spaceAction uv
_ -> uv
doRegexInput :: Universe -> Int -> SelectionSections a -> SelectionSections a
doRegexInput u i sss
| backspacetonothing || escapekey = endregex i 0
| endkeys || endmouse = endregex (i + 1) (j -1)
| otherwise = sss & doTextInputOver' u (sssExtra . sssFilters . ix i . _Just)
where
endregex a b =
sss
& sssExtra . sssFilters . ix i .~ Nothing
& sssSections . ix i . ssItems .~ mempty
& ssSetCursor (ssLookupDown a b)
j = fromMaybe 0 $ do
itms <- sss ^? sssSections . ix (i + 1) . ssItems
fst <$> IM.lookupMin itms
escapekey = ScancodeEscape `M.lookup` pkeys == Just InitialPress
endkeys =
any
((== Just InitialPress) . (`M.lookup` pkeys))
[ScancodeReturn, ScancodeSlash]
endmouse = fromMaybe False $ u ^? uvWorld . input . mouseButtons . ix ButtonLeft
backspacetonothing =
sss ^? sssExtra . sssFilters . ix i . _Just == Just ""
&& ScancodeBackspace `M.lookup` pkeys == Just InitialPress
pkeys = u ^. uvWorld . input . pressedKeys
updateBackspaceRegex :: World -> World
updateBackspaceRegex w = case di ^? subInventory of
Just NoSubInventory | secfocus (-1) 0 -> w & hud . hudElement . diSections %~ trybackspace (-1)
& worldEventFlags . at InventoryChange ?~ ()
Just NoSubInventory | secfocus 2 3 -> w & hud . hudElement . diSections %~ trybackspace 2
& worldEventFlags . at InventoryChange ?~ ()
Just CombineInventory{} -> w & hud . hudElement . subInventory . ciSections %~ trybackspace (-1)
& worldEventFlags . at InventoryChange ?~ ()
_ -> w
where
secfocus a b = fromMaybe False $ do
i <- di ^? diSections . sssExtra . sssSelPos . _Just . _1
return $ i == a || i == b
trybackspace x sss = fromMaybe sss $ do
-- i <- fss ^? fssSections . sssSelPos . _Just . _1
-- guard (i == x || i == x+1)
str <- sss ^? sssExtra . sssFilters . ix x . _Just
return $ case str of
(_ : _) ->
sss & sssExtra . sssFilters . ix x . _Just %~ init
& sssExtra . sssSelPos ?~ (x, 0)
[] -> sss & sssExtra . sssFilters . ix x .~ Nothing
di = w ^. hud . hudElement
updateEnterRegex :: World -> World
updateEnterRegex w = case w ^? hud . hudElement . subInventory of
Just NoSubInventory
| secfocus (-1) 0 ->
w & hud . hudElement . diSections . sssExtra . sssSelPos ?~ (-1, 0)
& hud . hudElement . diSections %~ enterregex (-1)
Just NoSubInventory
| secfocus 2 3 ->
w & hud . hudElement . diSections . sssExtra . sssSelPos ?~ (2, 0)
& hud . hudElement . diSections %~ enterregex 2
Just CombineInventory{} ->
w & hud . hudElement . subInventory . ciSections %~ enterregex (-1)
& hud . hudElement . subInventory . ciSections . sssExtra . sssSelPos ?~ (-1, 0)
_ -> w
where
di = w ^. hud . hudElement
secfocus a b = fromMaybe False $ do
i <- di ^? diSections . sssExtra . sssSelPos . _Just . _1
return $ i == a || i == b
enterregex x sss =
sss & sssExtra . sssFilters . ix x %~ f
& sssExtra . sssSelPos ?~ (x, 0)
f Nothing = Just ""
f x = x
pauseGame :: Universe -> Universe
pauseGame u = u & uvScreenLayers .~ [pauseMenu u]
spaceAction :: World -> World
spaceAction w = case w ^. hud . hudElement of
DisplayCarte -> w & hud . carteCenter .~ theLoc
DisplayInventory{_subInventory = NoSubInventory} -> case selectedCloseObject w of
Just (Left flit) -> pickUpItem 0 flit w
& worldEventFlags . at InventoryChange ?~ ()
Just (Right but) -> doButtonEvent (_btEvent but) but w
& worldEventFlags . at InventoryChange ?~ ()
_ -> w
DisplayInventory{_subInventory = DisplayTerminal{}} ->
w & hud . hudElement . subInventory .~ NoSubInventory
& worldEventFlags . at InventoryChange ?~ ()
_ -> w & hud . hudElement . subInventory .~ NoSubInventory
where
theLoc =
doWorldPos
(w ^?! cWorld . lWorld . seenLocations . ix (w ^. cWorld . lWorld . selLocation) . _1)
w
toggleMap :: Universe -> Universe
toggleMap u = case u ^. uvWorld . hud . hudElement of
DisplayCarte ->
u & uvWorld . hud . hudElement
.~ DisplayInventory{_subInventory = NoSubInventory, _diSections = defaultInvSections}
_ -> u & uvWorld . hud . hudElement .~ DisplayCarte
toggleTweakInv :: World -> World
toggleTweakInv w = case w ^? hud . hudElement . subInventory of
Just ExamineInventory{} -> w & thepointer .~ NoSubInventory
_ -> w & thepointer .~ ExamineInventory mi
where
thepointer = hud . hudElement . subInventory
mi = 0 <$ (yourItem w >>= (^? itTweaks . tweakParams . ix 0))
tryCombine :: SelectionSections CombinableItem -> World -> World
tryCombine sss w = fromMaybe w $ do
(i, j) <- sss ^? sssExtra . sssSelPos . _Just
CombinableItem is it _ <- sss ^? sssSections . ix i . ssItems . ix j . siPayload
return $ createAndSelectItem it $ foldr (rmInvItem 0) w (sort is)
maybeExitCombine :: Universe -> Universe
maybeExitCombine u
| ButtonRight `M.member` (u ^. uvWorld . input . mouseButtons) = u
| otherwise = u & uvWorld . hud . hudElement . subInventory .~ NoSubInventory
+115
View File
@@ -0,0 +1,115 @@
module Dodge.Update.Input.ScreenLayer (
updateUseInputOnScreen,
) where
import qualified Data.Map.Strict as M
import Data.Maybe
import Dodge.Base.Window
import Dodge.Data.Universe
import Dodge.Debug.Terminal
import Dodge.Menu.Option
import Dodge.SelectionList
import Dodge.Update.Input.Text
import Geometry
import LensHelp
import SDL
updateUseInputOnScreen :: ScreenLayer -> Universe -> Universe
updateUseInputOnScreen sl = case sl of
InputScreen thetext _ -> doInputScreenInput thetext
screen@OptionScreen{_scPositionedMenuOption = mop, _scSelectionList = sellist, _scListDisplayParams = ldps} ->
optionScreenUpdate screen mop ldps sellist
doInputScreenInput :: String -> Universe -> Universe
doInputScreenInput s u =
u & doTextInputOver (uvScreenLayers . _head . scInput)
& checkEndStatus
where
pkeys = u ^. uvWorld . input . pressedKeys
checkEndStatus
| ScancodeReturn `M.member` pkeys =
(uvScreenLayers %~ tail)
. applyTerminalString (words s)
. (uvWorld . worldEventFlags . at InventoryChange ?~ ())
| ScancodeEscape `M.member` pkeys = uvScreenLayers %~ tail
| otherwise = id
optionScreenUpdate ::
ScreenLayer ->
PositionedMenuOption ->
ListDisplayParams ->
SelectionList (Universe -> Universe) ->
Universe ->
Universe
optionScreenUpdate screen mop ldps sl u =
refreshOptionsSelectionList
. optionScreenDefaultEffect mop
. mouseClickOptionsList screen
. mouseOverSelectionList ldps sl
. menuWheelEvents
. over (uvScreenLayers . _head) (setSelectionListRestriction (u ^. uvConfig))
$ u
optionScreenDefaultEffect :: PositionedMenuOption -> Universe -> Universe
optionScreenDefaultEffect f u = case u ^. uvWorld . input . pressedKeys . at ScancodeEscape of
Just InitialPress -> fromMaybe id (f ^? pmoMenuOption . moEff) u
_ -> u
mouseClickOptionsList :: ScreenLayer -> Universe -> Universe
mouseClickOptionsList screen u = fromMaybe u $ do
sl <- screen ^? scSelectionList
Just $ case u ^. uvWorld . input . mouseButtons . at ButtonLeft of
Just False -> fromMaybe u $ do
i <- sl ^. slSelPos
f <- sl ^? slItems . ix i . siPayload
return $ f u
_ -> u
mouseOverSelectionList :: ListDisplayParams -> SelectionList (Universe -> Universe) -> Universe -> Universe
mouseOverSelectionList ldps sl u
| x > xl && x < xr
&& ylower == yupper
&& mmoving
&& ylower >= 0
&& ylower < ymax
&& isselectable =
u & uvScreenLayers . _head . scSelectionList . slSelPos ?~ yupper
| otherwise = u
where
isselectable =
fromMaybe False $
u ^? uvScreenLayers . _head . scSelectionList . slItems . ix yupper . siIsSelectable
ymax = maybe 0 length $ sl ^? slItems
mmoving = u ^. uvWorld . input . mouseMoving
ylower = ceiling $ (hh - (75 + y + _ldpPosY ldps)) / 50
yupper = floor $ (hh - (15 + y + _ldpPosY ldps)) / 50
xl = _ldpPosX ldps - hw
--xr = xl + _ldpScale ldps * 15 * 9
xr = xl + _ldpScale ldps * 26 * 9
V2 x y = u ^. uvWorld . input . mousePos
cfig = u ^. uvConfig
hh = halfHeight cfig
hw = halfWidth cfig
menuWheelEvents :: Universe -> Universe
menuWheelEvents u = foldr ($) u (replicate (abs y) (menuWheelStep (signum y)))
where
y = u ^. uvWorld . input . scrollAmount
-- you probably want i to be 1 or -1
menuWheelStep :: Int -> Universe -> Universe
menuWheelStep i u = fromMaybe u $ do
sl <- u ^? uvScreenLayers . _head . scSelectionList
selpos <- sl ^? slSelPos . _Just
ymax <- fmap length (sl ^? slItems)
let newpos = (selpos - i) `mod` ymax
itm <- sl ^? slItems . ix newpos
let newu = u & uvScreenLayers . _head . scSelectionList . slSelPos . _Just %~ const newpos
if _siIsSelectable itm
then Just newu
else Just $ menuWheelStep i newu
setSelectionListRestriction :: Configuration -> ScreenLayer -> ScreenLayer
setSelectionListRestriction cfig screen = fromMaybe screen $ do
ldps <- screen ^? scListDisplayParams
return $ screen & scAvailableLines %~ const (getAvailableListLines ldps cfig)
+32
View File
@@ -0,0 +1,32 @@
module Dodge.Update.Input.Text (
doTextInputOver,
doTextInputOver',
) where
import Data.Char
import Dodge.Data.Universe
import LensHelp
import SDL
doTextInputOver :: ASetter' Universe String -> Universe -> Universe
doTextInputOver p u = doTextInputOver' u p u
doTextInputOver' :: Universe -> ASetter' a String -> a -> a
doTextInputOver' u p x =
x & p %~ (++ map toUpper str)
& checkBackspace
where
str = u ^. uvWorld . input . textInput
checkBackspace
| backspaceInputted u = p %~ doBackspace
| otherwise = id
backspaceInputted :: Universe -> Bool
backspaceInputted u = case u ^. uvWorld . input . pressedKeys . at ScancodeBackspace of
Just InitialPress -> True
Just LongPress -> True
_ -> False
doBackspace :: String -> String
doBackspace [] = []
doBackspace s = init s