WIP, does not compile.
This commit is contained in:
commit
e37832371c
@ -16,7 +16,6 @@ executable Pioneers
|
|||||||
Map.Types,
|
Map.Types,
|
||||||
Map.Graphics,
|
Map.Graphics,
|
||||||
Map.Creation,
|
Map.Creation,
|
||||||
Map.StaticMaps,
|
|
||||||
Importer.IQM.Types,
|
Importer.IQM.Types,
|
||||||
Importer.IQM.Parser,
|
Importer.IQM.Parser,
|
||||||
Render.Misc,
|
Render.Misc,
|
||||||
|
14
src/Main.hs
14
src/Main.hs
@ -43,7 +43,9 @@ import Render.Render (initRendering,
|
|||||||
import Render.Types
|
import Render.Types
|
||||||
import UI.Callbacks
|
import UI.Callbacks
|
||||||
import Map.Graphics
|
import Map.Graphics
|
||||||
|
import Map.Creation (exportedMap)
|
||||||
import Types
|
import Types
|
||||||
|
import qualified UI.UIBase as UI
|
||||||
import Importer.IQM.Parser
|
import Importer.IQM.Parser
|
||||||
--import Data.Attoparsec.Char8 (parseTest)
|
--import Data.Attoparsec.Char8 (parseTest)
|
||||||
--import qualified Data.ByteString as B
|
--import qualified Data.ByteString as B
|
||||||
@ -53,7 +55,7 @@ import Importer.IQM.Parser
|
|||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
testParser :: String -> IO ()
|
testParser :: String -> IO ()
|
||||||
testParser a = putStrLn . show =<< parseIQM a
|
testParser a = print =<< parseIQM a
|
||||||
{-do
|
{-do
|
||||||
f <- B.readFile a
|
f <- B.readFile a
|
||||||
putStrLn "reading in:"
|
putStrLn "reading in:"
|
||||||
@ -85,7 +87,8 @@ main =
|
|||||||
(SDL.Size fbWidth fbHeight) <- SDL.glGetDrawableSize window'
|
(SDL.Size fbWidth fbHeight) <- SDL.glGetDrawableSize window'
|
||||||
initRendering
|
initRendering
|
||||||
--generate map vertices
|
--generate map vertices
|
||||||
glMap' <- initMapShader 4 =<< getMapBufferObject
|
curMap <- exportedMap
|
||||||
|
glMap' <- initMapShader 4 =<< getMapBufferObject curMap
|
||||||
eventQueue <- newTQueueIO :: IO (TQueue SDL.Event)
|
eventQueue <- newTQueueIO :: IO (TQueue SDL.Event)
|
||||||
now <- getCurrentTime
|
now <- getCurrentTime
|
||||||
--font <- TTF.openFont "fonts/ttf-04B_03B_/04B_03B_.TTF" 10
|
--font <- TTF.openFont "fonts/ttf-04B_03B_/04B_03B_.TTF" 10
|
||||||
@ -125,7 +128,7 @@ main =
|
|||||||
, _yAngle = pi/2
|
, _yAngle = pi/2
|
||||||
, _zDist = 10
|
, _zDist = 10
|
||||||
, _frustum = frust
|
, _frustum = frust
|
||||||
, _camObject = createFlatCam 25 25
|
, _camObject = createFlatCam 25 25 curMap
|
||||||
}
|
}
|
||||||
, _io = IOState
|
, _io = IOState
|
||||||
{ _clock = now
|
{ _clock = now
|
||||||
@ -153,12 +156,13 @@ main =
|
|||||||
, _glFramebuffer = frameBuffer
|
, _glFramebuffer = frameBuffer
|
||||||
}
|
}
|
||||||
, _game = GameState
|
, _game = GameState
|
||||||
{
|
{ _currentMap = curMap
|
||||||
}
|
}
|
||||||
, _ui = UIState
|
, _ui = UIState
|
||||||
{ _uiHasChanged = True
|
{ _uiHasChanged = True
|
||||||
, _uiMap = guiMap
|
, _uiMap = guiMap
|
||||||
, _uiRoots = guiRoots
|
, _uiRoots = guiRoots
|
||||||
|
, _uiButtonState = UI.UIButtonState 0 Nothing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,7 +220,7 @@ run = do
|
|||||||
- 0.2 * kyrot * mults
|
- 0.2 * kyrot * mults
|
||||||
mody y' = y' + 0.2 * kxrot * mults
|
mody y' = y' + 0.2 * kxrot * mults
|
||||||
- 0.2 * kyrot * multc
|
- 0.2 * kyrot * multc
|
||||||
modify $ camera.camObject %~ (\c -> moveBy c (\(x,y) -> (modx x,mody y)))
|
modify $ camera.camObject %~ (\c -> moveBy c (\(x,y) -> (modx x,mody y)) (state ^. game.currentMap))
|
||||||
|
|
||||||
{-
|
{-
|
||||||
--modify the state with all that happened in mt time.
|
--modify the state with all that happened in mt time.
|
||||||
|
@ -2,7 +2,6 @@ module Map.Creation
|
|||||||
where
|
where
|
||||||
|
|
||||||
import Map.Types
|
import Map.Types
|
||||||
import Map.StaticMaps
|
|
||||||
-- import Map.Map unused (for now)
|
-- import Map.Map unused (for now)
|
||||||
|
|
||||||
import Data.Array
|
import Data.Array
|
||||||
@ -18,6 +17,10 @@ infix 5 -<-
|
|||||||
(-<-) :: (PlayMap -> PlayMap) -> (PlayMap -> PlayMap) -> PlayMap -> PlayMap
|
(-<-) :: (PlayMap -> PlayMap) -> (PlayMap -> PlayMap) -> PlayMap -> PlayMap
|
||||||
f -<- g = f . g
|
f -<- g = f . g
|
||||||
|
|
||||||
|
-- entirely empty map, only uses the minimal constructor
|
||||||
|
mapEmpty :: PlayMap
|
||||||
|
mapEmpty = array ((0,0), (199,199)) [((a,b), Node (a,b) (fromIntegral a, (if even b then (fromIntegral b) else(fromIntegral b) - 0.5), 1) Grass BNothing NoPlayer NoPath Plain []) | a <- [0..199], b <- [0..199]]
|
||||||
|
|
||||||
exportedMap :: IO PlayMap
|
exportedMap :: IO PlayMap
|
||||||
exportedMap = do mounts <- mnt
|
exportedMap = do mounts <- mnt
|
||||||
return $ aplAll mounts mapEmpty
|
return $ aplAll mounts mapEmpty
|
||||||
@ -52,7 +55,7 @@ gauss3Dgeneral :: Floating q =>
|
|||||||
-> q -- ^ Coordinate in question on X
|
-> q -- ^ Coordinate in question on X
|
||||||
-> q -- ^ Coordinate in question on Z
|
-> q -- ^ Coordinate in question on Z
|
||||||
-> q -- ^ elevation on coordinate in question
|
-> q -- ^ elevation on coordinate in question
|
||||||
gauss3Dgeneral amp x0 z0 sX sZ x z = amp * exp(-(((x-x0)^(2 :: Integer)/(2 * sX^(2 :: Integer)))+((z-z0)^(2 :: Integer)/(2 * sZ^(2 :: Integer)))))
|
gauss3Dgeneral amp x0 z0 sX sZ x z = amp * exp(-(((x-x0)^(2 :: Int)/(2 * sX^(2 :: Int)))+((z-z0)^(2 :: Int)/(2 * sZ^(2 :: Int)))))
|
||||||
|
|
||||||
-- specialised 3D gaussian with an origin on 100/100, an amplitude of 15 and two sigmas of 15
|
-- specialised 3D gaussian with an origin on 100/100, an amplitude of 15 and two sigmas of 15
|
||||||
gauss3D :: Floating q =>
|
gauss3D :: Floating q =>
|
||||||
@ -93,20 +96,17 @@ mnt = do g <- newStdGen
|
|||||||
gaussMountain :: Int -> PlayMap -> PlayMap
|
gaussMountain :: Int -> PlayMap -> PlayMap
|
||||||
gaussMountain seed mp = aplByPlace (liftUp c) (\(_,_) -> True) mp
|
gaussMountain seed mp = aplByPlace (liftUp c) (\(_,_) -> True) mp
|
||||||
where
|
where
|
||||||
g = mkStdGen seed
|
gs = map mkStdGen (map (*seed) [1..])
|
||||||
c = let ((a,b), (x,y)) = bounds mp in (head (randomRs (a,x) g), (head (randomRs (b,y) g)))
|
c = let ((a,b), (x,y)) = bounds mp in (head (randomRs (a,x) (gs !! 0)), (head (randomRs (b,y) (gs !! 1))))
|
||||||
amp = head $ randomRs (2.0, 5.0) g
|
amp = head $ randomRs ((2.0, 5.0) :: (Float, Float)) (gs !! 2)
|
||||||
sig = head $ randomRs (1.0, 5.0) g
|
sig = head $ randomRs ((1.0, 15.0) :: (Float, Float)) (gs !! 3)
|
||||||
fi = fromIntegral
|
|
||||||
htt = heightToTerrain
|
htt = heightToTerrain
|
||||||
|
|
||||||
-- TODO: Fix Lambda to True with sensible function, maybe rework giveNeighbourhood in Map.Map
|
-- TODO: Fix Lambda to True with sensible function, maybe rework giveNeighbourhood in Map.Map
|
||||||
liftUp :: (Int, Int) -> Node -> Node
|
liftUp :: (Int, Int) -> Node -> Node
|
||||||
liftUp (gx,gz) (Full (x,z) y _ b pl pa r s) = let y_neu = max y e
|
liftUp (gx,gz) (Node (x,z) (rx,rz,y) _ b pl pa r s) = let y_neu = max y e
|
||||||
in Full (x,z) y_neu (htt GrassIslandMap y_neu) b pl pa r s
|
in Node (x,z) (rx, rz, y_neu) (htt GrassIslandMap y_neu) b pl pa r s
|
||||||
where e = gauss3Dgeneral amp (fi gx) (fi gz) sig sig (fi x) (fi z)
|
where e = gauss3Dgeneral amp (fromIntegral gx) (fromIntegral gz) sig sig rx rz
|
||||||
liftUp (gx, gz) (Minimal (x,z)) = Full (x,z) e (htt GrassIslandMap e) BFlag NoPlayer NoPath Plain []
|
|
||||||
where e = gauss3Dgeneral amp (fi gx) (fi gz) sig sig (fi x) (fi z)
|
|
||||||
|
|
||||||
-- | Makes sure the edges of the Map are mountain-free
|
-- | Makes sure the edges of the Map are mountain-free
|
||||||
makeIsland :: PlayMap -> PlayMap
|
makeIsland :: PlayMap -> PlayMap
|
||||||
|
@ -50,16 +50,14 @@ stripify :: (Int,Int) -> (Int,Int)
|
|||||||
stripify (x,z) = (if even z then 2*x else 2*x+1, z `div` 2)
|
stripify (x,z) = (if even z then 2*x else 2*x+1, z `div` 2)
|
||||||
|
|
||||||
strp :: Node -> Node
|
strp :: Node -> Node
|
||||||
strp (Full xz y tt bi pli p ri si) = Full (stripify xz) y tt bi pli p ri si
|
strp (Node i (x,z,y) tt bi pli p ri si) = Node (stripify i) (x,z,y) tt bi pli p ri si
|
||||||
strp (Minimal xz ) = Minimal (stripify xz)
|
|
||||||
|
|
||||||
-- extract graphics information from Playmap
|
-- extract graphics information from Playmap
|
||||||
convertToGraphicsMap :: PlayMap -> GraphicsMap
|
convertToGraphicsMap :: PlayMap -> GraphicsMap
|
||||||
convertToGraphicsMap mp = array (bounds mp) [(i, graphicsyfy (mp ! i))| i <- indices mp]
|
convertToGraphicsMap mp = array (bounds mp) [(i, graphicsyfy (mp ! i))| i <- indices mp]
|
||||||
where
|
where
|
||||||
graphicsyfy :: Node -> MapEntry
|
graphicsyfy :: Node -> MapEntry
|
||||||
graphicsyfy (Minimal _ ) = (1.0, Grass)
|
graphicsyfy (Node _ (_,_,y) t _ _ _ _ _ ) = (y, t)
|
||||||
graphicsyfy (Full _ y t _ _ _ _ _ ) = (y, t)
|
|
||||||
|
|
||||||
lineHeight :: GLfloat
|
lineHeight :: GLfloat
|
||||||
lineHeight = 0.8660254
|
lineHeight = 0.8660254
|
||||||
@ -87,9 +85,8 @@ fgNormalIndex = (ToFloat, mapVertexArrayDescriptor 3 4) --normal after color
|
|||||||
fgVertexIndex :: (IntegerHandling, VertexArrayDescriptor GLfloat)
|
fgVertexIndex :: (IntegerHandling, VertexArrayDescriptor GLfloat)
|
||||||
fgVertexIndex = (ToFloat, mapVertexArrayDescriptor 3 7) --vertex after normal
|
fgVertexIndex = (ToFloat, mapVertexArrayDescriptor 3 7) --vertex after normal
|
||||||
|
|
||||||
getMapBufferObject :: IO (BufferObject, NumArrayIndices)
|
getMapBufferObject :: PlayMap -> IO (BufferObject, NumArrayIndices)
|
||||||
getMapBufferObject = do
|
getMapBufferObject eMap = do
|
||||||
eMap <- exportedMap
|
|
||||||
myMap' <- return $ convertToGraphicsMap $ convertToStripeMap eMap
|
myMap' <- return $ convertToGraphicsMap $ convertToStripeMap eMap
|
||||||
! myMap <- return $ generateTriangles myMap'
|
! myMap <- return $ generateTriangles myMap'
|
||||||
len <- return $ fromIntegral $ P.length myMap `div` numComponents
|
len <- return $ fromIntegral $ P.length myMap `div` numComponents
|
||||||
@ -203,8 +200,8 @@ colorLookup hs t = if inRange (bounds hs) t then c else (0.0, 0.0, 0.0)
|
|||||||
Beach -> (0.90, 0.85, 0.70)
|
Beach -> (0.90, 0.85, 0.70)
|
||||||
Desert -> (1.00, 0.87, 0.39)
|
Desert -> (1.00, 0.87, 0.39)
|
||||||
Grass -> (0.30, 0.90, 0.10)
|
Grass -> (0.30, 0.90, 0.10)
|
||||||
Hill -> (0.80, 0.80, 0.80)
|
Mountain -> (0.80, 0.80, 0.80)
|
||||||
Mountain -> (0.50, 0.50, 0.50)
|
Hill -> (0.50, 0.50, 0.50)
|
||||||
|
|
||||||
coordLookup :: (Int,Int) -> GLfloat -> V3 GLfloat
|
coordLookup :: (Int,Int) -> GLfloat -> V3 GLfloat
|
||||||
coordLookup (x,z) y =
|
coordLookup (x,z) y =
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
module Map.Map where
|
module Map.Map where
|
||||||
|
|
||||||
import Map.Types
|
import Map.Types
|
||||||
|
import Map.Creation
|
||||||
|
|
||||||
import Data.Array (bounds)
|
import Data.Function (on)
|
||||||
import Data.List (sort, group)
|
import Data.Array (bounds, (!))
|
||||||
|
import Data.List (sort, sortBy, group)
|
||||||
|
|
||||||
-- WARNING: Does NOT Check for neighbours exceeding maximum map coordinates yet.
|
-- WARNING: Does NOT Check for neighbours exceeding maximum map coordinates yet.
|
||||||
unsafeGiveNeighbours :: (Int, Int) -- ^ original coordinates
|
unsafeGiveNeighbours :: (Int, Int) -- ^ original coordinates
|
||||||
@ -36,6 +38,57 @@ giveNeighbourhood _ 0 (a,b) = [(a,b)]
|
|||||||
giveNeighbourhood mp n (a,b) = let ns = giveNeighbours mp (a,b) in
|
giveNeighbourhood mp n (a,b) = let ns = giveNeighbours mp (a,b) in
|
||||||
remdups . concat $ ns : map (giveNeighbourhood mp (n-1)) ns
|
remdups . concat $ ns : map (giveNeighbourhood mp (n-1)) ns
|
||||||
|
|
||||||
|
-- | Calculates the height of any given point on the map.
|
||||||
|
-- Does not add camera distance to ground to that.
|
||||||
|
--
|
||||||
|
-- This ueses barycentric coordinate stuff. Wanna read more?
|
||||||
|
-- http://en.wikipedia.org/wiki/Barycentric_coordinate_system_%28mathematics%29
|
||||||
|
-- http://www.alecjacobson.com/weblog/?p=1596
|
||||||
|
--
|
||||||
|
giveMapHeight :: PlayMap
|
||||||
|
-> (Float, Float) -- ^ Coordinates on X/Z-axes
|
||||||
|
-> Float -- ^ Terrain Height at that position
|
||||||
|
giveMapHeight mp (x,z) = let [a,b,c] = getTrianglePoints [tff,tfc,tcf,tcc]
|
||||||
|
ar = area (fi a) (fi b) (fi c)
|
||||||
|
λa = area (fi b) (fi c) (x, z) / ar
|
||||||
|
λb = area (fi a) (fi c) (x, z) / ar
|
||||||
|
λc = area (fi a) (fi b) (x, z) / ar
|
||||||
|
in (λa * hlu a) + (λb * hlu b) + (λc * hlu c)
|
||||||
|
where
|
||||||
|
|
||||||
|
fi :: (Int, Int) -> (Float, Float)
|
||||||
|
fi (m, n) = (fromIntegral m, fromIntegral n)
|
||||||
|
|
||||||
|
-- Height LookUp
|
||||||
|
hlu :: (Int, Int) -> Float
|
||||||
|
hlu (k,j) = let (Node _ (_,_,y) _ _ _ _ _ _) = mp ! (k,j) in y
|
||||||
|
|
||||||
|
ff = (floor x, floor z) :: (Int, Int)
|
||||||
|
fc = (floor x, ceiling z) :: (Int, Int)
|
||||||
|
cf = (ceiling x, floor z) :: (Int, Int)
|
||||||
|
cc = (ceiling x, ceiling z) :: (Int, Int)
|
||||||
|
|
||||||
|
tff = (ff, dist (x,z) ff)
|
||||||
|
tfc = (fc, dist (x,z) fc)
|
||||||
|
tcf = (cf, dist (x,z) cf)
|
||||||
|
tcc = (cc, dist (x,z) cc)
|
||||||
|
|
||||||
|
getTrianglePoints :: [((Int,Int), Float)] -> [(Int,Int)]
|
||||||
|
getTrianglePoints = ((take 3) . (map fst) . (sortBy (compare `on` snd)))
|
||||||
|
|
||||||
|
dist :: (Float, Float) -> (Int, Int) -> Float
|
||||||
|
dist (x1,z1) (x2,z2) = let x' = x1 - fromIntegral x2
|
||||||
|
z' = z1 - fromIntegral z2
|
||||||
|
in sqrt $ x'*x' + z'*z'
|
||||||
|
|
||||||
|
-- Heron's Formula: http://en.wikipedia.org/wiki/Heron%27s_formula
|
||||||
|
area :: (Float, Float) -> (Float, Float) -> (Float, Float) -> Float
|
||||||
|
area (x1,z1) (x2,z2) (x3,z3) = let a = sqrt $ (x1-x2)*(x1-x2) + (z1-z2)*(z1-z2)
|
||||||
|
b = sqrt $ (x2-x3)*(x2-x3) + (z2-z3)*(z2-z3)
|
||||||
|
c = sqrt $ (x1-x3)*(x1-x3) + (z1-z3)*(z1-z3)
|
||||||
|
s = (a+b+c)/2
|
||||||
|
in sqrt $ s * (s-a) * (s-b) * (s-c)
|
||||||
|
|
||||||
-- removing duplicates in O(n log n), losing order and adding Ord requirement
|
-- removing duplicates in O(n log n), losing order and adding Ord requirement
|
||||||
remdups :: Ord a => [a] -> [a]
|
remdups :: Ord a => [a] -> [a]
|
||||||
remdups = map head . group . sort
|
remdups = map head . group . sort
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
module Map.StaticMaps
|
|
||||||
where
|
|
||||||
|
|
||||||
import Map.Types
|
|
||||||
import Data.Array
|
|
||||||
|
|
||||||
-- entirely empty map, only uses the minimal constructor
|
|
||||||
mapEmpty :: PlayMap
|
|
||||||
mapEmpty = array ((0,0), (199,199)) [((a,b), Minimal (a,b)) | a <- [0..199], b <- [0..199]]
|
|
||||||
|
|
||||||
--mapCenterMountain :: PlayMap
|
|
||||||
--mapCenterMountain = array ((0,0),(199,199)) nodes
|
|
||||||
-- where
|
|
||||||
-- nodes = water ++ beach ++ grass ++ hill ++ mountain
|
|
||||||
-- water = [((a,b), Full (a,b) 0.0 Ocean BNothing NoPlayer NoPath Plain []) | a <- [0..199], b <- [0..199], m2d (a,b) > 95]
|
|
||||||
-- beach = [((a,b), Full (a,b) (g2d a b) Beach BNothing NoPlayer NoPath Plain []) | a <- [0..199], b <- [0..199], m2d (a,b) <= 95, m2d (a,b) > 75]
|
|
||||||
-- grass = [((a,b), Full (a,b) (g2d a b) Grass BNothing NoPlayer NoPath Plain []) | a <- [0..199], b <- [0..199], m2d (a,b) <= 75, m2d (a,b) > 25]
|
|
||||||
-- hill = [((a,b), Full (a,b) (g2d a b) Hill BNothing NoPlayer NoPath Plain []) | a <- [0..199], b <- [0..199], m2d (a,b) <= 25, m2d (a,b) > 10]
|
|
||||||
-- mountain = [((a,b), Full (a,b) (g2d a b) Mountain BNothing NoPlayer NoPath Plain []) | a <- [0..199], b <- [0..199], m2d (a,b) <= 10]
|
|
||||||
|
|
||||||
-- g2d :: Int -> Int -> Float
|
|
||||||
-- g2d x y = gauss3D (fromIntegral x) (fromIntegral y)
|
|
||||||
|
|
||||||
-- m2d :: (Int,Int) -> Int
|
|
||||||
-- m2d (x,y) = mnh2D (x,y) (100,100)
|
|
||||||
|
|
||||||
-- small helper for some hills. Should be replaced by multi-layer perlin-noise
|
|
||||||
-- TODO: Replace as given in comment.
|
|
||||||
--_noisyMap :: (Floating q) => q -> q -> q
|
|
||||||
--_noisyMap x y = gauss3Dgeneral 15 100.0 100.0 15.0 15.0 x y
|
|
||||||
-- + gauss3Dgeneral 5 10.0 10.0 10.0 10.0 x y
|
|
||||||
-- + gauss3Dgeneral 5 150.0 120.0 10.0 10.0 x y
|
|
||||||
-- + gauss3Dgeneral 5 50.0 75.0 10.0 10.0 x y
|
|
||||||
|
|
||||||
-- generates a noisy map
|
|
||||||
-- TODO: add real noise to a simple pattern
|
|
||||||
--mapNoise :: PlayMap
|
|
||||||
--mapNoise = array ((0,0),(199,199)) nodes
|
|
||||||
-- where
|
|
||||||
-- nodes = [((a,b), Full (a,b)
|
|
||||||
-- (height a b)
|
|
||||||
-- (heightToTerrain GrassIslandMap $ height a b)
|
|
||||||
-- BNothing
|
|
||||||
-- NoPlayer
|
|
||||||
-- NoPath
|
|
||||||
-- Plain
|
|
||||||
-- []) | a <- [0..199], b <- [0..199]]
|
|
||||||
-- where
|
|
||||||
-- height a b = _noisyMap (fromIntegral a) (fromIntegral b)
|
|
@ -1,14 +1,14 @@
|
|||||||
module Map.Types
|
module Map.Types
|
||||||
where
|
where
|
||||||
|
|
||||||
import Types
|
|
||||||
|
|
||||||
import Data.Array
|
import Data.Array
|
||||||
|
|
||||||
type PlayMap = Array (XCoord, ZCoord) Node
|
type PlayMap = Array (Xindex, Zindex) Node
|
||||||
|
|
||||||
type XCoord = Int
|
type Xindex = Int
|
||||||
type ZCoord = Int
|
type Zindex = Int
|
||||||
|
type XCoord = Float
|
||||||
|
type ZCoord = Float
|
||||||
type YCoord = Float
|
type YCoord = Float
|
||||||
|
|
||||||
data MapType = GrassIslandMap
|
data MapType = GrassIslandMap
|
||||||
@ -66,7 +66,67 @@ data TileType = Ocean
|
|||||||
| Mountain -- ^ Not accessible
|
| Mountain -- ^ Not accessible
|
||||||
deriving (Show, Eq)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
-- TODO: Record Syntax
|
-- TODO: Record Syntax?
|
||||||
data Node = Full (XCoord, ZCoord) YCoord TileType BuildInfo PlayerInfo PathInfo ResInfo StorInfo
|
data Node = Node (Xindex, Zindex) (XCoord, ZCoord, YCoord) TileType BuildInfo PlayerInfo PathInfo ResInfo StorInfo
|
||||||
| Minimal (XCoord, ZCoord) -- defaults to empty green grass node on height 1
|
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
|
|
||||||
|
data Structure = Flag -- Flag
|
||||||
|
| Woodcutter -- Huts
|
||||||
|
| Forester
|
||||||
|
| Stonemason
|
||||||
|
| Fisher
|
||||||
|
| Hunter
|
||||||
|
| Barracks
|
||||||
|
| Guardhouse
|
||||||
|
| LookoutTower
|
||||||
|
| Well
|
||||||
|
| Sawmill -- Houses
|
||||||
|
| Slaughterhouse
|
||||||
|
| Mill
|
||||||
|
| Bakery
|
||||||
|
| IronSmelter
|
||||||
|
| Metalworks
|
||||||
|
| Armory
|
||||||
|
| Mint
|
||||||
|
| Shipyard
|
||||||
|
| Brewery
|
||||||
|
| Storehouse
|
||||||
|
| Watchtower
|
||||||
|
| Catapult
|
||||||
|
| GoldMine -- Mines
|
||||||
|
| IronMine
|
||||||
|
| GraniteMine
|
||||||
|
| CoalMine
|
||||||
|
| Farm -- Castles
|
||||||
|
| PigFarm
|
||||||
|
| DonkeyBreeder
|
||||||
|
| Harbor
|
||||||
|
| Fortress
|
||||||
|
deriving (Show, Eq)
|
||||||
|
|
||||||
|
data Amount = Infinite -- Neverending supply
|
||||||
|
| Finite Int -- Finite supply
|
||||||
|
|
||||||
|
-- Extremely preliminary, expand when needed
|
||||||
|
data Commodity = WoodPlank
|
||||||
|
| Sword
|
||||||
|
| Fish
|
||||||
|
deriving Eq
|
||||||
|
|
||||||
|
data Resource = Coal
|
||||||
|
| Iron
|
||||||
|
| Gold
|
||||||
|
| Granite
|
||||||
|
| Water
|
||||||
|
| Fishes
|
||||||
|
deriving (Show, Eq)
|
||||||
|
|
||||||
|
instance Show Amount where
|
||||||
|
show (Infinite) = "inexhaustable supply"
|
||||||
|
show (Finite n) = show n ++ " left"
|
||||||
|
|
||||||
|
instance Show Commodity where
|
||||||
|
show WoodPlank = "wooden plank"
|
||||||
|
show Sword = "sword"
|
||||||
|
show Fish = "fish"
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ import Render.Types
|
|||||||
import Graphics.GLUtil.BufferObjects (makeBuffer)
|
import Graphics.GLUtil.BufferObjects (makeBuffer)
|
||||||
import Importer.IQM.Parser
|
import Importer.IQM.Parser
|
||||||
import Importer.IQM.Types
|
import Importer.IQM.Types
|
||||||
|
import Map.Map (giveMapHeight)
|
||||||
|
|
||||||
mapVertexShaderFile :: String
|
mapVertexShaderFile :: String
|
||||||
mapVertexShaderFile = "shaders/map/vertex.shader"
|
mapVertexShaderFile = "shaders/map/vertex.shader"
|
||||||
|
@ -4,6 +4,10 @@ module Render.Types (createFlatCam, createSphereCam, Camera, GLCamera(..)) where
|
|||||||
import Linear
|
import Linear
|
||||||
import Foreign.C (CFloat)
|
import Foreign.C (CFloat)
|
||||||
import Render.Misc (lookAt)
|
import Render.Misc (lookAt)
|
||||||
|
import Map.Map (giveMapHeight)
|
||||||
|
import Map.Types (PlayMap)
|
||||||
|
import GHC.Float
|
||||||
|
import qualified Debug.Trace as D
|
||||||
|
|
||||||
type Distance = Double
|
type Distance = Double
|
||||||
type Pitch = Double
|
type Pitch = Double
|
||||||
@ -11,27 +15,29 @@ type Yaw = Double
|
|||||||
|
|
||||||
class GLCamera a where
|
class GLCamera a where
|
||||||
getCam :: a -> Distance -> Pitch -> Yaw -> M44 CFloat
|
getCam :: a -> Distance -> Pitch -> Yaw -> M44 CFloat
|
||||||
moveBy :: a -> (Position -> Position) -> a
|
moveBy :: a -> (Position -> Position) -> PlayMap -> a
|
||||||
move :: a -> Position -> a
|
move :: a -> Position -> PlayMap -> a
|
||||||
|
|
||||||
type Position = (Double, Double)
|
type Position = (Double, Double)
|
||||||
|
|
||||||
type Radius = Double
|
type Radius = Double
|
||||||
|
|
||||||
data Camera = Flat Position
|
type Height = Double
|
||||||
|
|
||||||
|
data Camera = Flat Position Height
|
||||||
| Sphere Position Radius
|
| Sphere Position Radius
|
||||||
|
|
||||||
-- | create a Flatcam-Camera starting at given x/z-Coordinates
|
-- | create a Flatcam-Camera starting at given x/z-Coordinates
|
||||||
createFlatCam :: Double -> Double -> Camera
|
createFlatCam :: Double -> Double -> PlayMap -> Camera
|
||||||
createFlatCam x z = Flat (x,z)
|
createFlatCam x z map' = Flat (x,z) (float2Double $ giveMapHeight map' (double2Float x,double2Float z))
|
||||||
|
|
||||||
-- | create a Flatcam-Camera starting at given pitch/azimuth/radius
|
-- | create a Flatcam-Camera starting at given pitch/azimuth/radius
|
||||||
createSphereCam :: Double -> Double -> Double -> Camera
|
createSphereCam :: Double -> Double -> Double -> Camera
|
||||||
createSphereCam p a r = Sphere (p,a) r
|
createSphereCam p a = Sphere (p,a)
|
||||||
|
|
||||||
|
|
||||||
instance GLCamera Camera where
|
instance GLCamera Camera where
|
||||||
getCam (Flat (x',z')) dist' xa' ya' =
|
getCam (Flat (x',z') y') dist' xa' ya' =
|
||||||
lookAt (cpos ^+^ at') at' up
|
lookAt (cpos ^+^ at') at' up
|
||||||
where
|
where
|
||||||
at' = V3 x (y+1) z
|
at' = V3 x (y+1) z
|
||||||
@ -44,6 +50,7 @@ instance GLCamera Camera where
|
|||||||
upmap = ((fromQuaternion $ axisAngle (V3 0 1 0) (ya::CFloat)) :: M33 CFloat)
|
upmap = ((fromQuaternion $ axisAngle (V3 0 1 0) (ya::CFloat)) :: M33 CFloat)
|
||||||
!* (V3 1 0 0)
|
!* (V3 1 0 0)
|
||||||
x = realToFrac x'
|
x = realToFrac x'
|
||||||
|
y = realToFrac y'
|
||||||
z = realToFrac z'
|
z = realToFrac z'
|
||||||
dist = realToFrac dist'
|
dist = realToFrac dist'
|
||||||
xa = realToFrac xa'
|
xa = realToFrac xa'
|
||||||
@ -68,9 +75,13 @@ instance GLCamera Camera where
|
|||||||
dist = realToFrac dist'
|
dist = realToFrac dist'
|
||||||
xa = realToFrac xa'
|
xa = realToFrac xa'
|
||||||
ya = realToFrac ya'
|
ya = realToFrac ya'
|
||||||
moveBy (Sphere (inc, az) r) f = undefined
|
moveBy (Sphere (inc, az) r) f map = undefined
|
||||||
moveBy (Flat (x', z')) f = Flat (f (x',z'))
|
moveBy (Flat (x', z') y) f map = Flat (x,z) (float2Double y)
|
||||||
move c (x', z') = moveBy c (\(x,z) -> (x+x',z+z'))
|
where
|
||||||
|
(x,z) = f (x', z')
|
||||||
|
y = giveMapHeight map (fc x,fc z)
|
||||||
|
fc = double2Float
|
||||||
|
move c (x', z') map = moveBy c (\(x,z) -> (x+x',z+z')) map
|
||||||
|
|
||||||
sphereToCart :: (Floating a) => a -> a -> a -> V3 a
|
sphereToCart :: (Floating a) => a -> a -> a -> V3 a
|
||||||
sphereToCart r inc az = V3
|
sphereToCart r inc az = V3
|
||||||
|
64
src/Types.hs
64
src/Types.hs
@ -15,6 +15,7 @@ import Graphics.Rendering.OpenGL.GL.Texturing.Objects (TextureObject)
|
|||||||
import Render.Types
|
import Render.Types
|
||||||
import Importer.IQM.Types
|
import Importer.IQM.Types
|
||||||
import UI.UIBase
|
import UI.UIBase
|
||||||
|
import Map.Types (PlayMap)
|
||||||
|
|
||||||
data Coord3D a = Coord3D a a a
|
data Coord3D a = Coord3D a a a
|
||||||
|
|
||||||
@ -56,7 +57,7 @@ data IOState = IOState
|
|||||||
}
|
}
|
||||||
|
|
||||||
data GameState = GameState
|
data GameState = GameState
|
||||||
{
|
{ _currentMap :: !PlayMap
|
||||||
}
|
}
|
||||||
|
|
||||||
data MouseState = MouseState
|
data MouseState = MouseState
|
||||||
@ -155,6 +156,7 @@ data UIState = UIState
|
|||||||
{ _uiHasChanged :: !Bool
|
{ _uiHasChanged :: !Bool
|
||||||
, _uiMap :: Map.HashMap UIId (GUIWidget Pioneers)
|
, _uiMap :: Map.HashMap UIId (GUIWidget Pioneers)
|
||||||
, _uiRoots :: [UIId]
|
, _uiRoots :: [UIId]
|
||||||
|
, _uiButtonState :: UIButtonState
|
||||||
}
|
}
|
||||||
|
|
||||||
data State = State
|
data State = State
|
||||||
@ -186,63 +188,3 @@ $(makeLenses ''Position)
|
|||||||
$(makeLenses ''Env)
|
$(makeLenses ''Env)
|
||||||
$(makeLenses ''UIState)
|
$(makeLenses ''UIState)
|
||||||
|
|
||||||
data Structure = Flag -- Flag
|
|
||||||
| Woodcutter -- Huts
|
|
||||||
| Forester
|
|
||||||
| Stonemason
|
|
||||||
| Fisher
|
|
||||||
| Hunter
|
|
||||||
| Barracks
|
|
||||||
| Guardhouse
|
|
||||||
| LookoutTower
|
|
||||||
| Well
|
|
||||||
| Sawmill -- Houses
|
|
||||||
| Slaughterhouse
|
|
||||||
| Mill
|
|
||||||
| Bakery
|
|
||||||
| IronSmelter
|
|
||||||
| Metalworks
|
|
||||||
| Armory
|
|
||||||
| Mint
|
|
||||||
| Shipyard
|
|
||||||
| Brewery
|
|
||||||
| Storehouse
|
|
||||||
| Watchtower
|
|
||||||
| Catapult
|
|
||||||
| GoldMine -- Mines
|
|
||||||
| IronMine
|
|
||||||
| GraniteMine
|
|
||||||
| CoalMine
|
|
||||||
| Farm -- Castles
|
|
||||||
| PigFarm
|
|
||||||
| DonkeyBreeder
|
|
||||||
| Harbor
|
|
||||||
| Fortress
|
|
||||||
deriving (Show, Eq)
|
|
||||||
|
|
||||||
data Amount = Infinite -- Neverending supply
|
|
||||||
| Finite Int -- Finite supply
|
|
||||||
|
|
||||||
-- Extremely preliminary, expand when needed
|
|
||||||
data Commodity = WoodPlank
|
|
||||||
| Sword
|
|
||||||
| Fish
|
|
||||||
deriving Eq
|
|
||||||
|
|
||||||
data Resource = Coal
|
|
||||||
| Iron
|
|
||||||
| Gold
|
|
||||||
| Granite
|
|
||||||
| Water
|
|
||||||
| Fishes
|
|
||||||
deriving (Show, Eq)
|
|
||||||
|
|
||||||
instance Show Amount where
|
|
||||||
show (Infinite) = "inexhaustable supply"
|
|
||||||
show (Finite n) = show n ++ " left"
|
|
||||||
|
|
||||||
instance Show Commodity where
|
|
||||||
show WoodPlank = "wooden plank"
|
|
||||||
show Sword = "sword"
|
|
||||||
show Fish = "fish"
|
|
||||||
|
|
||||||
|
@ -134,6 +134,37 @@ eventCallback e = do
|
|||||||
_ -> liftIO $ putStrLn $ unwords ["Not processing Event:", show e]
|
_ -> liftIO $ putStrLn $ unwords ["Not processing Event:", show e]
|
||||||
|
|
||||||
|
|
||||||
|
mouseButtonHandler :: (EventHandler Pioneers -> MouseButton -> Pixel -> GUIWidget Pioneers -> Pioneers (GUIWidget Pioneers))
|
||||||
|
-> MouseButton -> Pixel -> Pioneers ()
|
||||||
|
mouseButtonHandler transFunc btn px = do
|
||||||
|
modify $ ui.uiButtonState %~ (mousePressed %~ (+1)) -- TODO: what happens if released outside window? not reset properly?
|
||||||
|
state <- get
|
||||||
|
let hMap = state ^. ui.uiMap
|
||||||
|
currentWidget = state ^. ui.uiButtonState.mouseCurrentWidget
|
||||||
|
case currentWidget of
|
||||||
|
Just (wui, px') -> do
|
||||||
|
let target = toGUIAny hMap wui
|
||||||
|
target' <- case target ^. eventHandlers.(at MouseEvent) of
|
||||||
|
Just ma -> transFunc ma btn (px -: px') target -- TODO unsafe fromJust
|
||||||
|
Nothing -> return target
|
||||||
|
modify $ ui.uiMap %~ Map.insert wui target'
|
||||||
|
return ()
|
||||||
|
Nothing -> return ()
|
||||||
|
|
||||||
|
mousePressHandler :: MouseButton -> Pixel -> Pioneers ()
|
||||||
|
mousePressHandler btn px = do
|
||||||
|
modify $ ui.uiButtonState %~ (mousePressed %~ (+1)) -- TODO: what happens if released outside window? not reset properly?
|
||||||
|
mouseButtonHandler (\ma -> fromJust (ma ^? onMousePress)) btn px
|
||||||
|
|
||||||
|
mouseReleaseHandler :: MouseButton -> Pixel -> Pioneers ()
|
||||||
|
mouseReleaseHandler btn px = do
|
||||||
|
modify $ ui.uiButtonState %~ (mousePressed %~ flip (-) 1) -- TODO: what happens if pressed outside window? not set properly?
|
||||||
|
mouseButtonHandler (\ma -> fromJust (ma ^? onMouseRelease)) btn px
|
||||||
|
-- TODO: trigger move/enter/leave
|
||||||
|
|
||||||
|
mouseMoveHandler :: Pixel -> Pioneers ()
|
||||||
|
mouseMoveHandler px = undefined
|
||||||
|
|
||||||
-- | Handler for UI-Inputs.
|
-- | Handler for UI-Inputs.
|
||||||
-- Indicates a primary click on something (e.g. left-click, touch on Touchpad, fire on Gamepad, ...
|
-- Indicates a primary click on something (e.g. left-click, touch on Touchpad, fire on Gamepad, ...
|
||||||
clickHandler :: MouseButton -> Pixel -> Pioneers ()
|
clickHandler :: MouseButton -> Pixel -> Pioneers ()
|
||||||
@ -154,7 +185,7 @@ clickHandler btn pos@(x,y) = do
|
|||||||
++ show prio ++ " at [" ++ show x ++ "," ++ show y ++ "]"
|
++ show prio ++ " at [" ++ show x ++ "," ++ show y ++ "]"
|
||||||
case w ^. eventHandlers.(at MouseEvent) of
|
case w ^. eventHandlers.(at MouseEvent) of
|
||||||
Just ma -> do w' <- fromJust (ma ^? onMousePress) btn pos' w -- TODO unsafe fromJust
|
Just ma -> do w' <- fromJust (ma ^? onMousePress) btn pos' w -- TODO unsafe fromJust
|
||||||
w'' <- fromJust (ma ^? onMouseRelease) btn pos' True w' -- TODO unsafe fromJust
|
w'' <- fromJust (ma ^? onMouseRelease) btn pos' w' -- TODO unsafe fromJust
|
||||||
return $ Just (uid, w'')
|
return $ Just (uid, w'')
|
||||||
Nothing -> return Nothing
|
Nothing -> return Nothing
|
||||||
) hits
|
) hits
|
||||||
|
@ -70,6 +70,15 @@ instance Hashable WidgetStateKey where -- TODO: generic deriving creates functio
|
|||||||
hash = fromEnum
|
hash = fromEnum
|
||||||
hashWithSalt salt x = (salt * 16777619) `xor` hash x
|
hashWithSalt salt x = (salt * 16777619) `xor` hash x
|
||||||
|
|
||||||
|
-- |Global tracking of mouse actions to determine event handling.
|
||||||
|
data UIButtonState = UIButtonState
|
||||||
|
{ _mousePressed :: Int -- ^amount of currently pressed buttons
|
||||||
|
, _mouseCurrentWidget :: Maybe (UIId, Pixel)
|
||||||
|
-- ^the current mouse-active widget and its global coordinates.
|
||||||
|
-- If @_mousePressed == 0@: widget the mouse is hovering over,
|
||||||
|
-- otherwise: widget the first button has been pressed on.
|
||||||
|
} deriving (Show, Eq)
|
||||||
|
|
||||||
-- |The button dependant state of a 'MouseState'.
|
-- |The button dependant state of a 'MouseState'.
|
||||||
data MouseButtonState = MouseButtonState
|
data MouseButtonState = MouseButtonState
|
||||||
{ _mouseIsDragging :: Bool -- ^firing if pressed but not confirmed
|
{ _mouseIsDragging :: Bool -- ^firing if pressed but not confirmed
|
||||||
@ -107,19 +116,22 @@ data EventHandler m =
|
|||||||
MouseHandler
|
MouseHandler
|
||||||
{
|
{
|
||||||
-- |The function 'onMousePressed' is called when a button is pressed
|
-- |The function 'onMousePressed' is called when a button is pressed
|
||||||
-- while inside a screen coordinate within the widget ('isInside').
|
-- while the widget is mouse-active.
|
||||||
|
--
|
||||||
|
-- A widget becomes mouse-active if no other button is currently pressed and the mouse
|
||||||
|
-- coordinates are within the widget's extent ('isInside') until no button is pressed any
|
||||||
|
-- more.
|
||||||
_onMousePress :: MouseButton -- ^the pressed button
|
_onMousePress :: MouseButton -- ^the pressed button
|
||||||
-> Pixel -- ^screen position
|
-> Pixel -- ^screen position
|
||||||
-> GUIWidget m -- ^widget the event is invoked on
|
-> GUIWidget m -- ^widget the event is invoked on
|
||||||
-> m (GUIWidget m) -- ^widget after the event and the possibly altered mouse handler
|
-> m (GUIWidget m) -- ^widget after the event and the possibly altered mouse handler
|
||||||
,
|
,
|
||||||
-- |The function 'onMouseReleased' is called when a button is released
|
-- |The function 'onMouseReleased' is called when a button is released
|
||||||
-- while the pressing event occured within the widget ('isInside').
|
-- while the widget is mouse-active.
|
||||||
--
|
--
|
||||||
-- Thus, the mouse is either within the widget or outside while still dragging.
|
-- Thus, the mouse is either within the widget or outside while still dragging.
|
||||||
_onMouseRelease :: MouseButton -- ^the released button
|
_onMouseRelease :: MouseButton -- ^the released button
|
||||||
-> Pixel -- ^screen position
|
-> Pixel -- ^screen position
|
||||||
-> Bool -- ^@True@ if the event occured inside the widget
|
|
||||||
-> GUIWidget m -- ^widget the event is invoked on
|
-> GUIWidget m -- ^widget the event is invoked on
|
||||||
-> m (GUIWidget m) -- ^widget after the event and the altered handler
|
-> m (GUIWidget m) -- ^widget after the event and the altered handler
|
||||||
}
|
}
|
||||||
@ -128,19 +140,22 @@ data EventHandler m =
|
|||||||
MouseMotionHandler
|
MouseMotionHandler
|
||||||
{
|
{
|
||||||
-- |The function 'onMouseMove' is invoked when the mouse is moved inside the
|
-- |The function 'onMouseMove' is invoked when the mouse is moved inside the
|
||||||
-- widget's space ('isInside').
|
-- widget's extent ('isInside') while no button is pressed or when the mouse is inside the
|
||||||
|
-- widget's extent while another button loses its mouse-active state. Triggered after
|
||||||
|
-- '_onMouseEnter'.
|
||||||
_onMouseMove :: Pixel -- ^screen position
|
_onMouseMove :: Pixel -- ^screen position
|
||||||
-> GUIWidget m -- ^widget the event is invoked on
|
-> GUIWidget m -- ^widget the event is invoked on
|
||||||
-> m (GUIWidget m) -- ^widget after the event and the altered handler
|
-> m (GUIWidget m) -- ^widget after the event and the altered handler
|
||||||
,
|
,
|
||||||
-- |The function 'onMouseMove' is invoked when the mouse enters the
|
-- |The function 'onMouseMove' is invoked when the mouse enters the
|
||||||
-- widget's space ('isInside').
|
-- widget's extent ('isInside') or when the mouse is inside the
|
||||||
|
-- widget's extent while another button loses its mouse-active state..
|
||||||
_onMouseEnter :: Pixel -- ^screen position
|
_onMouseEnter :: Pixel -- ^screen position
|
||||||
-> GUIWidget m -- ^widget the event is invoked on
|
-> GUIWidget m -- ^widget the event is invoked on
|
||||||
-> m (GUIWidget m) -- ^widget after the event and the altered handler
|
-> m (GUIWidget m) -- ^widget after the event and the altered handler
|
||||||
,
|
,
|
||||||
-- |The function 'onMouseMove' is invoked when the mouse leaves the
|
-- |The function 'onMouseLeave' is invoked when the mouse leaves the
|
||||||
-- widget's space ('isInside').
|
-- widget's extent ('isInside') while no other widget is mouse-active.
|
||||||
_onMouseLeave :: Pixel -- ^screen position
|
_onMouseLeave :: Pixel -- ^screen position
|
||||||
-> GUIWidget m -- ^widget the event is invoked on
|
-> GUIWidget m -- ^widget the event is invoked on
|
||||||
-> m (GUIWidget m) -- ^widget after the event and the altered handler
|
-> m (GUIWidget m) -- ^widget after the event and the altered handler
|
||||||
@ -199,10 +214,9 @@ data GUIBaseProperties m = BaseProperties
|
|||||||
data GUIGraphics m = Graphics
|
data GUIGraphics m = Graphics
|
||||||
{temp :: m Int}
|
{temp :: m Int}
|
||||||
|
|
||||||
$(makeLenses ''WidgetStateKey)
|
$(makeLenses ''UIButtonState)
|
||||||
$(makeLenses ''WidgetState)
|
$(makeLenses ''WidgetState)
|
||||||
$(makeLenses ''MouseButtonState)
|
$(makeLenses ''MouseButtonState)
|
||||||
$(makeLenses ''EventKey)
|
|
||||||
$(makeLenses ''EventHandler)
|
$(makeLenses ''EventHandler)
|
||||||
$(makeLenses ''GUIWidget)
|
$(makeLenses ''GUIWidget)
|
||||||
$(makeLenses ''GUIBaseProperties)
|
$(makeLenses ''GUIBaseProperties)
|
||||||
@ -221,6 +235,7 @@ initialMouseState = MouseState (array (minBound, maxBound) [(i, initialButtonSta
|
|||||||
|
|
||||||
-- TODO: combined mouse handler
|
-- TODO: combined mouse handler
|
||||||
|
|
||||||
|
-- TODO? breaks if button array not of sufficient size -- will be avoided by excluding constructor export
|
||||||
-- |Creates a 'MouseHandler' that sets a widget's 'MouseButtonState' properties if present,
|
-- |Creates a 'MouseHandler' that sets a widget's 'MouseButtonState' properties if present,
|
||||||
-- only fully functional in conjunction with 'setMouseMotionStateActions'.
|
-- only fully functional in conjunction with 'setMouseMotionStateActions'.
|
||||||
setMouseStateActions :: (Monad m) => EventHandler m
|
setMouseStateActions :: (Monad m) => EventHandler m
|
||||||
@ -231,7 +246,7 @@ setMouseStateActions = MouseHandler press' release'
|
|||||||
return $ w & widgetStates.(ix MouseStateKey).mouseStates.(ix b).mouseIsDragging .~ True
|
return $ w & widgetStates.(ix MouseStateKey).mouseStates.(ix b).mouseIsDragging .~ True
|
||||||
|
|
||||||
-- |Change 'MouseButtonState's '_mouseIsDragging' and '_mouseIsDeferred' to @False@.
|
-- |Change 'MouseButtonState's '_mouseIsDragging' and '_mouseIsDeferred' to @False@.
|
||||||
release' b _ _ w =
|
release' b _ w =
|
||||||
return $ w & widgetStates.(ix MouseStateKey).mouseStates.(ix b) %~
|
return $ w & widgetStates.(ix MouseStateKey).mouseStates.(ix b) %~
|
||||||
(mouseIsDragging .~ False) . (mouseIsDeferred .~ False)
|
(mouseIsDragging .~ False) . (mouseIsDeferred .~ False)
|
||||||
|
|
||||||
@ -260,8 +275,7 @@ setMouseMotionStateActions = MouseMotionHandler move' enter' leave'
|
|||||||
-- following line executed BEFORE above line
|
-- following line executed BEFORE above line
|
||||||
. (\sState -> sState & mouseIsDeferred .~ not (sState ^. mouseIsDragging)))
|
. (\sState -> sState & mouseIsDeferred .~ not (sState ^. mouseIsDragging)))
|
||||||
|
|
||||||
|
-- TODO: make only fire if press started within widget
|
||||||
-- TODO? breaks if array not of sufficient size -- will be avoided by excluding constructor export
|
|
||||||
-- |Creates a MouseHandler that reacts on mouse clicks.
|
-- |Creates a MouseHandler that reacts on mouse clicks.
|
||||||
--
|
--
|
||||||
-- Does /not/ update 'WidgetState MouseState'!
|
-- Does /not/ update 'WidgetState MouseState'!
|
||||||
@ -271,10 +285,21 @@ buttonMouseActions a = MouseHandler press' release'
|
|||||||
where
|
where
|
||||||
press' _ _ = return
|
press' _ _ = return
|
||||||
|
|
||||||
release' b p isIn w =
|
release' b p w = do fire <- (w ^. baseProperties.isInside) w p
|
||||||
if isIn
|
if fire then a b w p else return w
|
||||||
then a b w p
|
|
||||||
else return w
|
-- TODO: make only fire if press started within widget
|
||||||
|
-- |Creates a MouseHandler that reacts on mouse clicks.
|
||||||
|
--
|
||||||
|
-- Does /not/ update 'WidgetState MouseState'!
|
||||||
|
buttonSingleMouseActions :: (Monad m) => (GUIWidget m -> Pixel -> m (GUIWidget m)) -- ^action on button press
|
||||||
|
-> MouseButton -> EventHandler m
|
||||||
|
buttonSingleMouseActions a btn = MouseHandler press' release'
|
||||||
|
where
|
||||||
|
press' _ _ = return
|
||||||
|
|
||||||
|
release' b p w = do fire <- liftM (b == btn &&) $ (w ^. baseProperties.isInside) w p
|
||||||
|
if fire then a w p else return w
|
||||||
|
|
||||||
emptyGraphics :: (Monad m) => GUIGraphics m
|
emptyGraphics :: (Monad m) => GUIGraphics m
|
||||||
emptyGraphics = Graphics (return 3)
|
emptyGraphics = Graphics (return 3)
|
||||||
|
@ -10,7 +10,7 @@ import UI.UIBase
|
|||||||
|
|
||||||
-- TODO: test GUI function to scan for overlapping widgets
|
-- TODO: test GUI function to scan for overlapping widgets
|
||||||
|
|
||||||
toGUIAny :: Map.HashMap UIId (GUIWidget m) -> UIId -> GUIWidget m
|
toGUIAny :: Map.HashMap UIId (GUIWidget m) -> UIId -> GUIWidget m -- TODO: what to do if widget not inside map -> inconsistent state
|
||||||
toGUIAny m uid = fromMaybe (error "map does not contain requested key") (Map.lookup uid m)
|
toGUIAny m uid = fromMaybe (error "map does not contain requested key") (Map.lookup uid m)
|
||||||
{-# INLINABLE toGUIAny #-}
|
{-# INLINABLE toGUIAny #-}
|
||||||
|
|
||||||
@ -46,4 +46,8 @@ getInsideId hMap px uid = do
|
|||||||
else return []
|
else return []
|
||||||
--TODO: Priority queue?
|
--TODO: Priority queue?
|
||||||
|
|
||||||
|
getLeadingWidget :: [(UIId, Pixel)] -- ^widgets and their screen positions
|
||||||
|
-> Pioneers (Maybe (UIId, Pixel)) -- ^the leading widget
|
||||||
|
getLeadingWidget [] = return Nothing
|
||||||
|
getLeadingWidget (x:_) = return $ Just x
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user