{-# LANGUAGE FlexibleInstances, ScopedTypeVariables, TypeSynonymInstances #-}
-- |This module contains classes and functions to relate Haskell types
-- with OpenGL DataTypes (typically used to describe the values stored
-- in arrays) and VariableTypes (used as attributes and uniforms in
-- GLSL programs).
module Graphics.GLUtil.TypeMapping where
import Data.Int
import Data.Word
import Foreign.Storable (Storable)
import qualified Graphics.Rendering.OpenGL as GL
import Graphics.Rendering.OpenGL
import Linear (V1, V2, V3, V4, M22, M33, M44)

-- | A mapping from Haskell types to values of 'VariableType'. This
-- defines how Haskell values may be mapped to values that may be
-- bound to GLSL variables.
class HasVariableType a where
  variableType :: a -> VariableType

instance HasVariableType Float where variableType :: Float -> VariableType
variableType _ = VariableType
Float'
instance HasVariableType Int32 where variableType :: Int32 -> VariableType
variableType _ = VariableType
Int'
instance HasVariableType Word32 where variableType :: Word32 -> VariableType
variableType _ = VariableType
UnsignedInt'

instance HasVariableType (V1 GLfloat) where variableType :: V1 Float -> VariableType
variableType _ = VariableType
Float'
instance HasVariableType (V2 GLfloat) where variableType :: V2 Float -> VariableType
variableType _ = VariableType
FloatVec2
instance HasVariableType (V3 GLfloat) where variableType :: V3 Float -> VariableType
variableType _ = VariableType
FloatVec3
instance HasVariableType (V4 GLfloat) where variableType :: V4 Float -> VariableType
variableType _ = VariableType
FloatVec4

instance HasVariableType (V1 Int32) where variableType :: V1 Int32 -> VariableType
variableType _ = VariableType
Int'
instance HasVariableType (V2 Int32) where variableType :: V2 Int32 -> VariableType
variableType _ = VariableType
IntVec2
instance HasVariableType (V3 Int32) where variableType :: V3 Int32 -> VariableType
variableType _ = VariableType
IntVec3
instance HasVariableType (V4 Int32) where variableType :: V4 Int32 -> VariableType
variableType _ = VariableType
IntVec4

instance HasVariableType (V1 Word32) where variableType :: V1 Word32 -> VariableType
variableType _ = VariableType
UnsignedInt'
instance HasVariableType (V2 Word32) where variableType :: V2 Word32 -> VariableType
variableType _ = VariableType
UnsignedIntVec2
instance HasVariableType (V3 Word32) where variableType :: V3 Word32 -> VariableType
variableType _ = VariableType
UnsignedIntVec3
instance HasVariableType (V4 Word32) where variableType :: V4 Word32 -> VariableType
variableType _ = VariableType
UnsignedIntVec4

instance HasVariableType (M22 GLfloat) where variableType :: M22 Float -> VariableType
variableType _ = VariableType
FloatMat2
instance HasVariableType (M33 GLfloat) where variableType :: M33 Float -> VariableType
variableType _ = VariableType
FloatMat3
instance HasVariableType (M44 GLfloat) where variableType :: M44 Float -> VariableType
variableType _ = VariableType
FloatMat4

instance forall t. HasVariableType t => HasVariableType [t] where
  variableType :: [t] -> VariableType
variableType _ = t -> VariableType
forall a. HasVariableType a => a -> VariableType
variableType (t
forall a. HasCallStack => a
undefined::t)

-- | Maps each 'VariableType' to its corresponding
-- 'DataType'. Typically this indicates the element type of composite
-- variable types (e.g. @variableDataType FloatVec2 = Float@). Note
-- that this is a partial mapping as we are primarily supporting the
-- use of these types as inputs to GLSL programs where types such as
-- Bool are not supported.
variableDataType :: VariableType -> DataType
variableDataType :: VariableType -> DataType
variableDataType Float' = DataType
GL.Float
variableDataType FloatVec2 = DataType
GL.Float
variableDataType FloatVec3 = DataType
GL.Float
variableDataType FloatVec4 = DataType
GL.Float
variableDataType Int' = DataType
GL.Int
variableDataType IntVec2 = DataType
GL.Int
variableDataType IntVec3 = DataType
GL.Int
variableDataType IntVec4 = DataType
GL.Int
variableDataType UnsignedInt' = DataType
GL.UnsignedInt
variableDataType UnsignedIntVec2 = DataType
GL.UnsignedInt
variableDataType UnsignedIntVec3 = DataType
GL.UnsignedInt
variableDataType UnsignedIntVec4 = DataType
GL.UnsignedInt
variableDataType FloatMat2 = DataType
GL.Float
variableDataType FloatMat3 = DataType
GL.Float
variableDataType FloatMat4 = DataType
GL.Float
variableDataType FloatMat2x3 = DataType
GL.Float
variableDataType FloatMat2x4 = DataType
GL.Float
variableDataType FloatMat3x2 = DataType
GL.Float
variableDataType FloatMat3x4 = DataType
GL.Float
variableDataType FloatMat4x2 = DataType
GL.Float
variableDataType FloatMat4x3 = DataType
GL.Float
variableDataType _ = [Char] -> DataType
forall a. HasCallStack => [Char] -> a
error "Unsupported variable type!"

-- |Open mapping from Haskell types to OpenGL types.
class Storable a => HasGLType a where
  glType :: a -> DataType

instance HasGLType GLint where glType :: Int32 -> DataType
glType _ = DataType
GL.Int
instance HasGLType Word8 where glType :: Word8 -> DataType
glType _ = DataType
GL.UnsignedByte
instance HasGLType Word16 where glType :: Word16 -> DataType
glType _ = DataType
GL.UnsignedShort
instance HasGLType Word32 where glType :: Word32 -> DataType
glType _ = DataType
GL.UnsignedInt
instance HasGLType Float where glType :: Float -> DataType
glType _ = DataType
GL.Float