module Resource.Image.Atlas
( Atlas(..)
, fromTileSize
, fromImageSize
) where
import RIO
import Geomancy (UVec2, Vec2, uvec2, withUVec2, vec2)
data Atlas = Atlas
{ Atlas -> UVec2
sizeTiles :: UVec2
, Atlas -> UVec2
sizePx :: UVec2
, Atlas -> UVec2
tileSizePx :: UVec2
, Atlas -> UVec2
marginPx :: UVec2
, Atlas -> Vec2
uvScale :: Vec2
}
deriving (Atlas -> Atlas -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Atlas -> Atlas -> Bool
$c/= :: Atlas -> Atlas -> Bool
== :: Atlas -> Atlas -> Bool
$c== :: Atlas -> Atlas -> Bool
Eq, Int -> Atlas -> ShowS
[Atlas] -> ShowS
Atlas -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Atlas] -> ShowS
$cshowList :: [Atlas] -> ShowS
show :: Atlas -> String
$cshow :: Atlas -> String
showsPrec :: Int -> Atlas -> ShowS
$cshowsPrec :: Int -> Atlas -> ShowS
Show, forall x. Rep Atlas x -> Atlas
forall x. Atlas -> Rep Atlas x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Atlas x -> Atlas
$cfrom :: forall x. Atlas -> Rep Atlas x
Generic)
fromTileSize :: UVec2 -> UVec2 -> UVec2 -> Atlas
fromTileSize :: UVec2 -> UVec2 -> UVec2 -> Atlas
fromTileSize UVec2
sizeTiles UVec2
tileSizePx UVec2
marginPx = Atlas{UVec2
Vec2
uvScale :: Vec2
sizePx :: UVec2
marginPx :: UVec2
tileSizePx :: UVec2
sizeTiles :: UVec2
$sel:uvScale:Atlas :: Vec2
$sel:marginPx:Atlas :: UVec2
$sel:tileSizePx:Atlas :: UVec2
$sel:sizePx:Atlas :: UVec2
$sel:sizeTiles:Atlas :: UVec2
..}
where
sizePx :: UVec2
sizePx = UVec2
sizeTiles forall a. Num a => a -> a -> a
* UVec2
tileSizePx forall a. Num a => a -> a -> a
+ (UVec2
sizeTiles forall a. Num a => a -> a -> a
- UVec2
1) forall a. Num a => a -> a -> a
* UVec2
marginPx
uvScale :: Vec2
uvScale = UVec2 -> Vec2
fromU UVec2
tileSizePx forall a. Fractional a => a -> a -> a
/ UVec2 -> Vec2
fromU UVec2
sizePx
fromImageSize :: UVec2 -> UVec2 -> UVec2 -> Either UVec2 Atlas
fromImageSize :: UVec2 -> UVec2 -> UVec2 -> Either UVec2 Atlas
fromImageSize UVec2
sizePx UVec2
tileSizePx UVec2
marginPx =
if UVec2
leftovers forall a. Eq a => a -> a -> Bool
== UVec2
totalMargins then
forall a b. b -> Either a b
Right Atlas{UVec2
Vec2
uvScale :: Vec2
sizeTiles :: UVec2
marginPx :: UVec2
tileSizePx :: UVec2
sizePx :: UVec2
$sel:uvScale:Atlas :: Vec2
$sel:marginPx:Atlas :: UVec2
$sel:tileSizePx:Atlas :: UVec2
$sel:sizePx:Atlas :: UVec2
$sel:sizeTiles:Atlas :: UVec2
..}
else
forall a b. a -> Either a b
Left UVec2
leftovers
where
totalMargins :: UVec2
totalMargins = (UVec2
sizeTiles forall a. Num a => a -> a -> a
- UVec2
1) forall a. Num a => a -> a -> a
* UVec2
marginPx
(UVec2
sizeTiles, UVec2
leftovers) =
forall r. UVec2 -> (Word32 -> Word32 -> r) -> r
withUVec2 UVec2
sizePx \Word32
aw Word32
ah ->
forall r. UVec2 -> (Word32 -> Word32 -> r) -> r
withUVec2 UVec2
tileSizePx \Word32
tw Word32
th ->
let
(Word32
w, Word32
wRem) = Word32
aw forall a. Integral a => a -> a -> (a, a)
`divMod` Word32
tw
(Word32
h, Word32
hRem) = Word32
ah forall a. Integral a => a -> a -> (a, a)
`divMod` Word32
th
in
( Word32 -> Word32 -> UVec2
uvec2 Word32
w Word32
h
, Word32 -> Word32 -> UVec2
uvec2 Word32
wRem Word32
hRem
)
uvScale :: Vec2
uvScale = UVec2 -> Vec2
fromU UVec2
tileSizePx forall a. Fractional a => a -> a -> a
/ UVec2 -> Vec2
fromU UVec2
sizePx
fromU :: UVec2 -> Vec2
fromU :: UVec2 -> Vec2
fromU UVec2
u =
forall r. UVec2 -> (Word32 -> Word32 -> r) -> r
withUVec2 UVec2
u \Word32
x Word32
y ->
Float -> Float -> Vec2
vec2 (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
x) (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
y)