-- | UI screen coordinates.
module Game.LambdaHack.Client.UI.PointUI
  ( PointUI(..), PointSquare(..), squareToUI, uiToSquare
  , squareToMap, mapToSquare
#ifdef EXPOSE_INTERNAL
    -- * Internal operations
  , mapStartY
#endif
  ) where

import Prelude ()

import Game.LambdaHack.Core.Prelude

import Game.LambdaHack.Common.Point

-- | UI screen coordinates, independent of whether square or monospace fonts
-- are being placed on the screen (though square fonts are never placed
-- on odd coordinates). These are not game map coordinates,
-- becuse UI is larger and more fine-grained than just the game map.
data PointUI = PointUI Int Int
  deriving (Y -> PointUI -> ShowS
[PointUI] -> ShowS
PointUI -> String
(Y -> PointUI -> ShowS)
-> (PointUI -> String) -> ([PointUI] -> ShowS) -> Show PointUI
forall a.
(Y -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Y -> PointUI -> ShowS
showsPrec :: Y -> PointUI -> ShowS
$cshow :: PointUI -> String
show :: PointUI -> String
$cshowList :: [PointUI] -> ShowS
showList :: [PointUI] -> ShowS
Show, PointUI -> PointUI -> Bool
(PointUI -> PointUI -> Bool)
-> (PointUI -> PointUI -> Bool) -> Eq PointUI
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PointUI -> PointUI -> Bool
== :: PointUI -> PointUI -> Bool
$c/= :: PointUI -> PointUI -> Bool
/= :: PointUI -> PointUI -> Bool
Eq)

-- | Coordinates of the big square fonts. These are not game map coordinates,
-- because the latter are offset by @mapStartY@ and represented by @Point@.
--
-- However, confusingly, @Point@ is also used for square font glyph coordinates,
-- though exclusively in context of rendered frames to be sent to a frontend,
-- namely @PointArray.Array@, which is indexed by @Point@ and is a vector,
-- and so traditionally indexed starting from zero and not from minus one,
-- as would be needed for consistency.
data PointSquare = PointSquare Int Int
  deriving (Y -> PointSquare -> ShowS
[PointSquare] -> ShowS
PointSquare -> String
(Y -> PointSquare -> ShowS)
-> (PointSquare -> String)
-> ([PointSquare] -> ShowS)
-> Show PointSquare
forall a.
(Y -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Y -> PointSquare -> ShowS
showsPrec :: Y -> PointSquare -> ShowS
$cshow :: PointSquare -> String
show :: PointSquare -> String
$cshowList :: [PointSquare] -> ShowS
showList :: [PointSquare] -> ShowS
Show, PointSquare -> PointSquare -> Bool
(PointSquare -> PointSquare -> Bool)
-> (PointSquare -> PointSquare -> Bool) -> Eq PointSquare
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PointSquare -> PointSquare -> Bool
== :: PointSquare -> PointSquare -> Bool
$c/= :: PointSquare -> PointSquare -> Bool
/= :: PointSquare -> PointSquare -> Bool
Eq)

squareToUI :: PointSquare -> PointUI
{-# INLINE squareToUI #-}
squareToUI :: PointSquare -> PointUI
squareToUI (PointSquare Y
x Y
y) = Y -> Y -> PointUI
PointUI (Y
x Y -> Y -> Y
forall a. Num a => a -> a -> a
* Y
2) Y
y

uiToSquare :: PointUI -> PointSquare
{-# INLINE uiToSquare #-}
uiToSquare :: PointUI -> PointSquare
uiToSquare (PointUI Y
x Y
y) = Y -> Y -> PointSquare
PointSquare (Y
x Y -> Y -> Y
forall a. Integral a => a -> a -> a
`div` Y
2) Y
y

-- | The row where the dungeon map starts, both in @PointUI@
-- and @PointSquare@ coordinates.
mapStartY :: Int
mapStartY :: Y
mapStartY = Y
1

squareToMap :: PointSquare -> Point
{-# INLINE squareToMap #-}
squareToMap :: PointSquare -> Point
squareToMap (PointSquare Y
x Y
y) = Y -> Y -> Point
Point Y
x (Y
y Y -> Y -> Y
forall a. Num a => a -> a -> a
- Y
mapStartY)

mapToSquare :: Point -> PointSquare
{-# INLINE mapToSquare #-}
mapToSquare :: Point -> PointSquare
mapToSquare (Point Y
x Y
y) = Y -> Y -> PointSquare
PointSquare Y
x (Y
y Y -> Y -> Y
forall a. Num a => a -> a -> a
+ Y
mapStartY)