diff --git a/src/Dodge/Update/Input/InGame.hs b/src/Dodge/Update/Input/InGame.hs new file mode 100644 index 000000000..77b01d61b --- /dev/null +++ b/src/Dodge/Update/Input/InGame.hs @@ -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 diff --git a/src/Dodge/Update/Input/ScreenLayer.hs b/src/Dodge/Update/Input/ScreenLayer.hs new file mode 100644 index 000000000..95bc8ef69 --- /dev/null +++ b/src/Dodge/Update/Input/ScreenLayer.hs @@ -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) diff --git a/src/Dodge/Update/Input/Text.hs b/src/Dodge/Update/Input/Text.hs new file mode 100644 index 000000000..caad91620 --- /dev/null +++ b/src/Dodge/Update/Input/Text.hs @@ -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