packages feed

swarm-0.5.0.0: src/Swarm/TUI/Editor/Model.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}

-- |
-- SPDX-License-Identifier: BSD-3-Clause
module Swarm.TUI.Editor.Model where

import Brick.Focus
import Brick.Widgets.List qualified as BL
import Control.Lens hiding (from, (.=), (<.>))
import Data.Map qualified as M
import Data.Vector qualified as V
import Swarm.Game.Display (Display)
import Swarm.Game.Entity qualified as E
import Swarm.Game.Scenario.Topography.EntityFacade
import Swarm.Game.Scenario.Topography.WorldPalette
import Swarm.Game.Terrain (TerrainType)
import Swarm.Game.Universe
import Swarm.Game.World qualified as W
import Swarm.TUI.Model.Name
import Swarm.Util
import System.Clock

data BoundsSelectionStep
  = UpperLeftPending
  | -- | Stores the *world coords* of the upper-left click
    LowerRightPending (Cosmic W.Coords)
  | SelectionComplete

data EntityPaint
  = Facade EntityFacade
  | Ref E.Entity
  deriving (Eq)

getDisplay :: EntityPaint -> Display
getDisplay (Facade (EntityFacade _ d)) = d
getDisplay (Ref e) = e ^. E.entityDisplay

toFacade :: EntityPaint -> EntityFacade
toFacade = \case
  Facade f -> f
  Ref e -> mkFacade e

getEntityName :: EntityFacade -> E.EntityName
getEntityName (EntityFacade name _) = name

data MapEditingBounds = MapEditingBounds
  { _boundsRect :: Maybe (Cosmic W.BoundsRectangle)
  -- ^ Upper-left and lower-right coordinates
  -- of the map to be saved.
  , _boundsPersistDisplayUntil :: TimeSpec
  , _boundsSelectionStep :: BoundsSelectionStep
  }

makeLenses ''MapEditingBounds

data WorldOverdraw = WorldOverdraw
  { _isWorldEditorEnabled :: Bool
  -- ^ This field has deferred initialization; it gets populated when a game
  -- is initialized.
  , _paintedTerrain :: M.Map W.Coords (TerrainWith EntityFacade)
  }

makeLenses ''WorldOverdraw

data WorldEditor n = WorldEditor
  { _worldOverdraw :: WorldOverdraw
  , _terrainList :: BL.List n TerrainType
  , _entityPaintList :: BL.List n EntityFacade
  , _editingBounds :: MapEditingBounds
  , _editorFocusRing :: FocusRing n
  , _outputFilePath :: FilePath
  , _lastWorldEditorMessage :: Maybe String
  }

makeLenses ''WorldEditor

initialWorldEditor :: TimeSpec -> WorldEditor Name
initialWorldEditor ts =
  WorldEditor
    (WorldOverdraw False mempty)
    (BL.list TerrainList (V.fromList listEnums) 1)
    (BL.list EntityPaintList (V.fromList []) 1)
    bounds
    (focusRing $ map WorldEditorPanelControl listEnums)
    "mymap.yaml"
    Nothing
 where
  bounds =
    MapEditingBounds
      -- Note that these are in "world coordinates",
      -- not in player-facing "Location" coordinates
      (Just $ Cosmic DefaultRootSubworld (W.Coords (-10, -20), W.Coords (10, 20)))
      (ts - 1)
      SelectionComplete