packages feed

immutaball-core-0.1.0.4.1: Immutaball/Ball/State/LevelSets.hs

{-# OPTIONS_GHC -fno-warn-tabs #-}  -- Support tab indentation better, for a better default of no warning if tabs are used: https://dmitryfrank.com/articles/indent_with_tabs_align_with_spaces .
-- Enable warnings:
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}

-- LevelSets.hs.

{-# LANGUAGE Haskell2010 #-}
{-# LANGUAGE Arrows, TemplateHaskell, ScopedTypeVariables #-}

module Immutaball.Ball.State.LevelSets
	(
		mkLevelSetsState,
		LevelSetsWidget(..), AsLevelSetsWidget(..),
		levelSetsGui,
		levelSetsBaseGui,
		levelSetsButtons
	) where

import Prelude ()
import Immutaball.Prelude

import Control.Applicative
import Control.Arrow
import Data.Functor.Identity
import Data.Maybe

import Control.Lens
import qualified Data.Map as M
import qualified SDL.Raw.Enum as Raw

import Immutaball.Ball.LevelSets
import qualified Immutaball.Ball.State.LevelSelect as LevelSelect
import Immutaball.Share.GUI
import Immutaball.Share.Math
import Immutaball.Share.State
import Immutaball.Share.State.Context
import Immutaball.Share.Utils
import Immutaball.Share.Wire

mkLevelSetsState :: (Either IBContext IBStateContext -> Immutaball) -> Either IBContext IBStateContext -> Immutaball
mkLevelSetsState mkBack baseCxt0 = closeSecondI . switch . fromImmutaballSingleWith Nothing . openSecondI $ proc (Identity request) -> do
	rec
		cxtLast <- delay cxt0 -< cxt
		cxtn <- requireBasics -< (cxtLast, request)

		(levelSets :: LevelSets) <- initial -< liftIBIO $ getLevelSets (cxtn^.ibContext)

		--(guiResponse, cxtnp1) <- mkGUI $ levelSetsGui levelSets -< (GUIDrive request, cxtn)
		(guiResponse, cxtnp1) <- withM (\gui -> second (mkGUI gui) >>> arr snd) (return . fst) -< (levelSetsGui levelSets, (GUIDrive request, cxtn))
		let response = ContinueResponse

		let isEsc  = (const False ||| (== (fromIntegral Raw.SDLK_ESCAPE, True))) . matching _Keybd $ request
		let isBack = isEsc || guiResponse == WidgetAction BackButton

		() <- finishFrame -< (request, cxtnp1)
		cxt <- returnA -< cxtnp1

	-- Switch on Back button.
	let switchTo0 = if' (not isBack) Nothing . Just . openSecondI $ mkBack (Right cxt)
	let onSet levelSetPath = flip M.lookup (levelSets^.lsLevelSets) levelSetPath >>= \levelSet -> return . openSecondI $ LevelSelect.mkLevelSelectState levelSet (mkLevelSetsState mkBack) (Right cxt)
	let switchTo = switchTo0 <|> case guiResponse of (WidgetAction (LevelSetButton levelSetPath)) -> onSet levelSetPath; _ -> Nothing
	returnA -< (Identity response, switchTo)

	where cxt0 = either initialStateCxt id baseCxt0

data LevelSetsWidget =
	  LevelSetsRoot
	| BackButton
	| LevelSetsVstack
	| LevelSetButton String
	| Anonymous Integer
	deriving (Eq, Ord, Show)
--makeClassyPrisms ''LevelSetsWidget

-- TODO: make a better UI.  For now we just have a simple list of level set titles.

levelSetsGui :: LevelSets -> [Widget LevelSetsWidget]
levelSetsGui levelSets =
	levelSetsBaseGui ++
	levelSetsButtons levelSets

levelSetsBaseGui :: [Widget LevelSetsWidget]
levelSetsBaseGui =
	[
		RootWidget   $ Root   { _rootWid   = LevelSetsRoot                               },
		ButtonWidget $ Button { _buttonWid = BackButton, _buttonWparent = LevelSetsRoot,
			_buttonText = "Back", _buttonRect = Just $ Rect (Vec2 (-0.800) (0.720)) (Vec2 (-0.700) (0.800)) },
		VstackWidget $ Vstack { _vstackWid = LevelSetsVstack, _vstackWparent = LevelSetsRoot  }
	]

levelSetsButtons :: LevelSets -> [Widget LevelSetsWidget]
-- Preserve order.
--levelSetsButtons levelSets = flip map (zip [0..] . M.toList $ levelSets^.lsLevelSets) $ \((idx :: Integer), (path, levelSet)) ->
levelSetsButtons levelSets = catMaybes . flip map (zip [0..] (levelSets^.lsExplicitSets)) $ \((idx :: Integer), path) -> flip fmap (M.lookup path (levelSets^.lsLevelSets)) $ \levelSet ->
	let idx' = fromIntegral idx in
	ButtonWidget $ Button { _buttonWid = LevelSetButton path, _buttonWparent = LevelSetsVstack,
		_buttonText = (levelSet^.lsTitle), _buttonRect = Just $ Rect (Vec2 (-0.100) (0.620 - 0.100*idx')) (Vec2 (0.100) (0.700 - 0.100*idx')) }

makeClassyPrisms ''LevelSetsWidget