{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ViewPatterns #-}
module Swarm.TUI.Model.UI (
UIState (..),
UIGameplay (..),
UITiming (..),
UIInventory (..),
GoalDisplay (..),
uiGameplay,
uiPopups,
uiTiming,
uiInventory,
uiMenu,
uiPlaying,
uiCheatMode,
uiFocusRing,
uiLaunchConfig,
uiWorldCursor,
uiWorldEditor,
uiREPL,
uiInventoryList,
uiInventorySort,
uiInventorySearch,
uiScrollToEnd,
uiModal,
uiGoal,
uiStructure,
uiHideGoals,
uiAchievements,
lgTicksPerSecond,
lastFrameTime,
accumulatedTime,
tickCount,
frameCount,
frameTickCount,
lastInfoTime,
uiShowFPS,
uiShowREPL,
uiShowZero,
uiShowDebug,
uiShowRobots,
uiHideRobotsUntil,
uiInventoryShouldUpdate,
uiTPF,
uiFPS,
uiAttrMap,
scenarioRef,
initFocusRing,
defaultInitLgTicksPerSecond,
initUIState,
) where
import Brick (AttrMap)
import Brick.Focus
import Brick.Widgets.List qualified as BL
import Control.Arrow ((&&&))
import Control.Effect.Accum
import Control.Effect.Lift
import Control.Lens hiding (from, (<.>))
import Data.Bits (FiniteBits (finiteBitSize))
import Data.List.Extra (enumerate)
import Data.Map (Map)
import Data.Map qualified as M
import Data.Sequence (Seq)
import Data.Text (Text)
import Data.Text qualified as T
import Swarm.Game.Achievement.Attainment
import Swarm.Game.Achievement.Definitions
import Swarm.Game.Achievement.Persistence
import Swarm.Game.Failure (SystemFailure)
import Swarm.Game.ResourceLoading (getSwarmHistoryPath)
import Swarm.Game.ScenarioInfo (
ScenarioInfoPair,
)
import Swarm.Game.Universe
import Swarm.Game.World.Coords
import Swarm.TUI.Editor.Model
import Swarm.TUI.Inventory.Sorting
import Swarm.TUI.Launch.Model
import Swarm.TUI.Launch.Prep
import Swarm.TUI.Model.Goal
import Swarm.TUI.Model.Menu
import Swarm.TUI.Model.Name
import Swarm.TUI.Model.Popup
import Swarm.TUI.Model.Repl
import Swarm.TUI.Model.Structure
import Swarm.TUI.View.Attribute.Attr (swarmAttrMap)
import Swarm.Util
import Swarm.Util.Lens (makeLensesExcluding, makeLensesNoSigs)
import System.Clock
data UITiming = UITiming
{ UITiming -> Bool
_uiShowFPS :: Bool
, UITiming -> Double
_uiTPF :: Double
, UITiming -> Double
_uiFPS :: Double
, UITiming -> Int
_lgTicksPerSecond :: Int
, UITiming -> Int
_tickCount :: Int
, UITiming -> Int
_frameCount :: Int
, UITiming -> Int
_frameTickCount :: Int
, UITiming -> TimeSpec
_lastFrameTime :: TimeSpec
, UITiming -> TimeSpec
_accumulatedTime :: TimeSpec
, UITiming -> TimeSpec
_lastInfoTime :: TimeSpec
}
makeLensesExcluding ['_lgTicksPerSecond] ''UITiming
uiShowFPS :: Lens' UITiming Bool
uiTPF :: Lens' UITiming Double
uiFPS :: Lens' UITiming Double
lgTicksPerSecond :: Lens' UITiming Int
lgTicksPerSecond :: Lens' UITiming Int
lgTicksPerSecond = (UITiming -> Int)
-> (UITiming -> Int -> UITiming) -> Lens' UITiming Int
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens UITiming -> Int
_lgTicksPerSecond UITiming -> Int -> UITiming
safeSetLgTicks
where
maxLog :: Int
maxLog = Int -> Int
forall b. FiniteBits b => b -> Int
finiteBitSize (Int
forall a. Bounded a => a
maxBound :: Int)
maxTicks :: Int
maxTicks = Int
maxLog Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2
minTicks :: Int
minTicks = Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
maxLog
safeSetLgTicks :: UITiming -> Int -> UITiming
safeSetLgTicks UITiming
ui Int
lTicks
| Int
lTicks Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
minTicks = UITiming -> Int -> UITiming
setLgTicks UITiming
ui Int
minTicks
| Int
lTicks Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
maxTicks = UITiming -> Int -> UITiming
setLgTicks UITiming
ui Int
maxTicks
| Bool
otherwise = UITiming -> Int -> UITiming
setLgTicks UITiming
ui Int
lTicks
setLgTicks :: UITiming -> Int -> UITiming
setLgTicks UITiming
ui Int
lTicks = UITiming
ui {_lgTicksPerSecond = lTicks}
tickCount :: Lens' UITiming Int
frameCount :: Lens' UITiming Int
frameTickCount :: Lens' UITiming Int
lastInfoTime :: Lens' UITiming TimeSpec
lastFrameTime :: Lens' UITiming TimeSpec
accumulatedTime :: Lens' UITiming TimeSpec
data UIInventory = UIInventory
{ UIInventory -> Maybe (Int, List Name InventoryListEntry)
_uiInventoryList :: Maybe (Int, BL.List Name InventoryListEntry)
, UIInventory -> InventorySortOptions
_uiInventorySort :: InventorySortOptions
, UIInventory -> Maybe Text
_uiInventorySearch :: Maybe Text
, UIInventory -> Bool
_uiShowZero :: Bool
, UIInventory -> Bool
_uiInventoryShouldUpdate :: Bool
}
makeLensesNoSigs ''UIInventory
uiInventorySort :: Lens' UIInventory InventorySortOptions
uiInventorySearch :: Lens' UIInventory (Maybe Text)
uiInventoryList :: Lens' UIInventory (Maybe (Int, BL.List Name InventoryListEntry))
uiShowZero :: Lens' UIInventory Bool
uiInventoryShouldUpdate :: Lens' UIInventory Bool
data UIGameplay = UIGameplay
{ UIGameplay -> FocusRing Name
_uiFocusRing :: FocusRing Name
, UIGameplay -> Maybe (Cosmic Coords)
_uiWorldCursor :: Maybe (Cosmic Coords)
, UIGameplay -> WorldEditor Name
_uiWorldEditor :: WorldEditor Name
, UIGameplay -> REPLState
_uiREPL :: REPLState
, UIGameplay -> UIInventory
_uiInventory :: UIInventory
, UIGameplay -> Bool
_uiScrollToEnd :: Bool
, UIGameplay -> Maybe Modal
_uiModal :: Maybe Modal
, UIGameplay -> GoalDisplay
_uiGoal :: GoalDisplay
, UIGameplay -> StructureDisplay
_uiStructure :: StructureDisplay
, UIGameplay -> Bool
_uiHideGoals :: Bool
, UIGameplay -> Bool
_uiShowREPL :: Bool
, UIGameplay -> Bool
_uiShowDebug :: Bool
, UIGameplay -> TimeSpec
_uiHideRobotsUntil :: TimeSpec
, UIGameplay -> UITiming
_uiTiming :: UITiming
, UIGameplay -> Maybe ScenarioInfoPair
_scenarioRef :: Maybe ScenarioInfoPair
}
makeLensesNoSigs ''UIGameplay
uiTiming :: Lens' UIGameplay UITiming
uiInventory :: Lens' UIGameplay UIInventory
uiFocusRing :: Lens' UIGameplay (FocusRing Name)
uiWorldCursor :: Lens' UIGameplay (Maybe (Cosmic Coords))
uiWorldEditor :: Lens' UIGameplay (WorldEditor Name)
uiREPL :: Lens' UIGameplay REPLState
uiScrollToEnd :: Lens' UIGameplay Bool
uiModal :: Lens' UIGameplay (Maybe Modal)
uiGoal :: Lens' UIGameplay GoalDisplay
uiStructure :: Lens' UIGameplay StructureDisplay
uiHideGoals :: Lens' UIGameplay Bool
uiShowREPL :: Lens' UIGameplay Bool
uiShowDebug :: Lens' UIGameplay Bool
uiHideRobotsUntil :: Lens' UIGameplay TimeSpec
uiShowRobots :: Getter UIGameplay Bool
uiShowRobots :: Getter UIGameplay Bool
uiShowRobots = (UIGameplay -> Bool)
-> (Bool -> f Bool) -> UIGameplay -> f UIGameplay
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to (\UIGameplay
ui -> UIGameplay
ui UIGameplay -> Getting TimeSpec UIGameplay TimeSpec -> TimeSpec
forall s a. s -> Getting a s a -> a
^. (UITiming -> Const TimeSpec UITiming)
-> UIGameplay -> Const TimeSpec UIGameplay
Lens' UIGameplay UITiming
uiTiming ((UITiming -> Const TimeSpec UITiming)
-> UIGameplay -> Const TimeSpec UIGameplay)
-> ((TimeSpec -> Const TimeSpec TimeSpec)
-> UITiming -> Const TimeSpec UITiming)
-> Getting TimeSpec UIGameplay TimeSpec
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TimeSpec -> Const TimeSpec TimeSpec)
-> UITiming -> Const TimeSpec UITiming
Lens' UITiming TimeSpec
lastFrameTime TimeSpec -> TimeSpec -> Bool
forall a. Ord a => a -> a -> Bool
> UIGameplay
ui UIGameplay -> Getting TimeSpec UIGameplay TimeSpec -> TimeSpec
forall s a. s -> Getting a s a -> a
^. Getting TimeSpec UIGameplay TimeSpec
Lens' UIGameplay TimeSpec
uiHideRobotsUntil)
scenarioRef :: Lens' UIGameplay (Maybe ScenarioInfoPair)
data UIState = UIState
{ :: Menu
, UIState -> Bool
_uiPlaying :: Bool
, UIState -> Bool
_uiCheatMode :: Bool
, UIState -> LaunchOptions
_uiLaunchConfig :: LaunchOptions
, UIState -> Map CategorizedAchievement Attainment
_uiAchievements :: Map CategorizedAchievement Attainment
, UIState -> AttrMap
_uiAttrMap :: AttrMap
, UIState -> UIGameplay
_uiGameplay :: UIGameplay
, :: PopupState
}
uiMenu :: Lens' UIState Menu
uiPlaying :: Lens' UIState Bool
uiCheatMode :: Lens' UIState Bool
uiLaunchConfig :: Lens' UIState LaunchOptions
uiAchievements :: Lens' UIState (Map CategorizedAchievement Attainment)
uiAttrMap :: Lens' UIState AttrMap
uiGameplay :: Lens' UIState UIGameplay
uiPopups :: Lens' UIState PopupState
initFocusRing :: FocusRing Name
initFocusRing :: FocusRing Name
initFocusRing = [Name] -> FocusRing Name
forall n. [n] -> FocusRing n
focusRing ([Name] -> FocusRing Name) -> [Name] -> FocusRing Name
forall a b. (a -> b) -> a -> b
$ (FocusablePanel -> Name) -> [FocusablePanel] -> [Name]
forall a b. (a -> b) -> [a] -> [b]
map FocusablePanel -> Name
FocusablePanel [FocusablePanel]
forall a. (Enum a, Bounded a) => [a]
enumerate
defaultInitLgTicksPerSecond :: Int
defaultInitLgTicksPerSecond :: Int
defaultInitLgTicksPerSecond = Int
4
initUIState ::
( Has (Accum (Seq SystemFailure)) sig m
, Has (Lift IO) sig m
) =>
Int ->
Bool ->
Bool ->
m UIState
initUIState :: forall (sig :: (* -> *) -> * -> *) (m :: * -> *).
(Has (Accum (Seq SystemFailure)) sig m, Has (Lift IO) sig m) =>
Int -> Bool -> Bool -> m UIState
initUIState Int
speedFactor Bool
showMainMenu Bool
cheatMode = do
Maybe Text
historyT <- IO (Maybe Text) -> m (Maybe Text)
forall (sig :: (* -> *) -> * -> *) (m :: * -> *) a.
Has (Lift IO) sig m =>
IO a -> m a
sendIO (IO (Maybe Text) -> m (Maybe Text))
-> IO (Maybe Text) -> m (Maybe Text)
forall a b. (a -> b) -> a -> b
$ FilePath -> IO (Maybe Text)
readFileMayT (FilePath -> IO (Maybe Text)) -> IO FilePath -> IO (Maybe Text)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Bool -> IO FilePath
getSwarmHistoryPath Bool
False
let history :: [REPLHistItem]
history = [REPLHistItem]
-> (Text -> [REPLHistItem]) -> Maybe Text -> [REPLHistItem]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] ((Text -> REPLHistItem) -> [Text] -> [REPLHistItem]
forall a b. (a -> b) -> [a] -> [b]
map Text -> REPLHistItem
mkREPLSubmission ([Text] -> [REPLHistItem])
-> (Text -> [Text]) -> Text -> [REPLHistItem]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Text]
T.lines) Maybe Text
historyT
TimeSpec
startTime <- IO TimeSpec -> m TimeSpec
forall (sig :: (* -> *) -> * -> *) (m :: * -> *) a.
Has (Lift IO) sig m =>
IO a -> m a
sendIO (IO TimeSpec -> m TimeSpec) -> IO TimeSpec -> m TimeSpec
forall a b. (a -> b) -> a -> b
$ Clock -> IO TimeSpec
getTime Clock
Monotonic
[Attainment]
achievements <- m [Attainment]
forall (sig :: (* -> *) -> * -> *) (m :: * -> *).
(Has (Accum (Seq SystemFailure)) sig m, Has (Lift IO) sig m) =>
m [Attainment]
loadAchievementsInfo
LaunchOptions
launchConfigPanel <- IO LaunchOptions -> m LaunchOptions
forall (sig :: (* -> *) -> * -> *) (m :: * -> *) a.
Has (Lift IO) sig m =>
IO a -> m a
sendIO IO LaunchOptions
initConfigPanel
let out :: UIState
out =
UIState
{ _uiMenu :: Menu
_uiMenu = if Bool
showMainMenu then List Name MainMenuEntry -> Menu
MainMenu (MainMenuEntry -> List Name MainMenuEntry
mainMenu MainMenuEntry
NewGame) else Menu
NoMenu
, _uiPlaying :: Bool
_uiPlaying = Bool -> Bool
not Bool
showMainMenu
, _uiCheatMode :: Bool
_uiCheatMode = Bool
cheatMode
, _uiLaunchConfig :: LaunchOptions
_uiLaunchConfig = LaunchOptions
launchConfigPanel
, _uiAchievements :: Map CategorizedAchievement Attainment
_uiAchievements = [(CategorizedAchievement, Attainment)]
-> Map CategorizedAchievement Attainment
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(CategorizedAchievement, Attainment)]
-> Map CategorizedAchievement Attainment)
-> [(CategorizedAchievement, Attainment)]
-> Map CategorizedAchievement Attainment
forall a b. (a -> b) -> a -> b
$ (Attainment -> (CategorizedAchievement, Attainment))
-> [Attainment] -> [(CategorizedAchievement, Attainment)]
forall a b. (a -> b) -> [a] -> [b]
map (Getting CategorizedAchievement Attainment CategorizedAchievement
-> Attainment -> CategorizedAchievement
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting CategorizedAchievement Attainment CategorizedAchievement
Lens' Attainment CategorizedAchievement
achievement (Attainment -> CategorizedAchievement)
-> (Attainment -> Attainment)
-> Attainment
-> (CategorizedAchievement, Attainment)
forall b c c'. (b -> c) -> (b -> c') -> b -> (c, c')
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& Attainment -> Attainment
forall a. a -> a
id) [Attainment]
achievements
, _uiAttrMap :: AttrMap
_uiAttrMap = AttrMap
swarmAttrMap
, _uiPopups :: PopupState
_uiPopups = PopupState
initPopupState
, _uiGameplay :: UIGameplay
_uiGameplay =
UIGameplay
{ _uiFocusRing :: FocusRing Name
_uiFocusRing = FocusRing Name
initFocusRing
, _uiWorldCursor :: Maybe (Cosmic Coords)
_uiWorldCursor = Maybe (Cosmic Coords)
forall a. Maybe a
Nothing
, _uiWorldEditor :: WorldEditor Name
_uiWorldEditor = TimeSpec -> WorldEditor Name
initialWorldEditor TimeSpec
startTime
, _uiREPL :: REPLState
_uiREPL = REPLHistory -> REPLState
initREPLState (REPLHistory -> REPLState) -> REPLHistory -> REPLState
forall a b. (a -> b) -> a -> b
$ [REPLHistItem] -> REPLHistory
newREPLHistory [REPLHistItem]
history
, _uiInventory :: UIInventory
_uiInventory =
UIInventory
{ _uiInventoryList :: Maybe (Int, List Name InventoryListEntry)
_uiInventoryList = Maybe (Int, List Name InventoryListEntry)
forall a. Maybe a
Nothing
, _uiInventorySort :: InventorySortOptions
_uiInventorySort = InventorySortOptions
defaultSortOptions
, _uiInventorySearch :: Maybe Text
_uiInventorySearch = Maybe Text
forall a. Maybe a
Nothing
, _uiShowZero :: Bool
_uiShowZero = Bool
True
, _uiInventoryShouldUpdate :: Bool
_uiInventoryShouldUpdate = Bool
False
}
, _uiScrollToEnd :: Bool
_uiScrollToEnd = Bool
False
, _uiModal :: Maybe Modal
_uiModal = Maybe Modal
forall a. Maybe a
Nothing
, _uiGoal :: GoalDisplay
_uiGoal = GoalDisplay
emptyGoalDisplay
, _uiStructure :: StructureDisplay
_uiStructure = StructureDisplay
emptyStructureDisplay
, _uiHideGoals :: Bool
_uiHideGoals = Bool
False
, _uiTiming :: UITiming
_uiTiming =
UITiming
{ _uiShowFPS :: Bool
_uiShowFPS = Bool
False
, _uiTPF :: Double
_uiTPF = Double
0
, _uiFPS :: Double
_uiFPS = Double
0
, _lgTicksPerSecond :: Int
_lgTicksPerSecond = Int
speedFactor
, _lastFrameTime :: TimeSpec
_lastFrameTime = TimeSpec
startTime
, _accumulatedTime :: TimeSpec
_accumulatedTime = TimeSpec
0
, _lastInfoTime :: TimeSpec
_lastInfoTime = TimeSpec
0
, _tickCount :: Int
_tickCount = Int
0
, _frameCount :: Int
_frameCount = Int
0
, _frameTickCount :: Int
_frameTickCount = Int
0
}
, _uiShowREPL :: Bool
_uiShowREPL = Bool
True
, _uiShowDebug :: Bool
_uiShowDebug = Bool
False
, _uiHideRobotsUntil :: TimeSpec
_uiHideRobotsUntil = TimeSpec
startTime TimeSpec -> TimeSpec -> TimeSpec
forall a. Num a => a -> a -> a
- TimeSpec
1
, _scenarioRef :: Maybe ScenarioInfoPair
_scenarioRef = Maybe ScenarioInfoPair
forall a. Maybe a
Nothing
}
}
UIState -> m UIState
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return UIState
out