Haskell Graphics Library that works in GHCi on MacOS X

前端 未结 5 2021
滥情空心
滥情空心 2021-01-30 07:30

Does there exist a Haskell graphics library or binding to an external library that fulfills the following requirements:

  1. Can be used from ghci, i.e. I
相关标签:
5条回答
  • 2021-01-30 07:34

    More information on Haskell+GUI+OpenGL is available in this discussion: http://www.haskell.org/pipermail/haskell-cafe/2011-May/091991.html

    0 讨论(0)
  • 2021-01-30 07:38

    As of early 2014, I wasn't able to use @heinrich-apfelmus answer in Mac OS X. This GLFW-b example (link) however worked.

    So, ensure you have:

    $ cabal install glfw-b
    

    and, if you tried Apfelmus' answer, you may need to

    $ ghc-pkg list
    $ ghc-pkg unregister GLFW-x.x.x.x
    

    as both provide Graphics.UI.GLFW, and you will get an "Ambiguous module name 'Graphics.UI.GLFW'" from ghc. Then I just tried the sample program above and it worked (Mac OS X, 10.9, Mavericks)

    0 讨论(0)
  • 2021-01-30 07:54

    EDIT: Actually, I'm no longer sure. Several versions later, it seems that GLFW no longer works in GHCi on OS X.

    It turns out that GLFW+OpenGL fulfills all four requirements!

    1. You need to invoke ghci with ghci -framework Carbon.
    2. You need the EnableGUI.hs file, which you can get here. Note that you can't load it right into GHCi, you have to comiple it, first.
    3. OpenGL has a 2D projection mode where you can draw lines and polygons.
    4. Bitmaps can be loaded as textures and put on polygons.

    Here is a small example that puts a bitmap onto the screen. There are some restrictions on the bitmap: its dimensions must be a power of two (here 256) and it must be a .tga file (here "Bitmap.tga"). But since transparency is supported, this is not much of a problem.

    You should be able to call main multiple times without problem. The key point is that you should not call GLFW.terminate.

    import Graphics.Rendering.OpenGL as GL
    import qualified Graphics.UI.GLFW as GLFW
    import Graphics.Rendering.OpenGL (($=))
    
    import Control.Monad
    import EnableGUI
    
    main = do
        enableGUI
        GLFW.initialize
        -- open window
        GLFW.openWindow (GL.Size 400 400) [GLFW.DisplayAlphaBits 8] GLFW.Window
        GLFW.windowTitle $= "Bitmap Test"
    
        -- enable alpha channel
        GL.blend         $= GL.Enabled
        GL.blendFunc     $= (GL.SrcAlpha, GL.OneMinusSrcAlpha)
        -- set the color to clear background
        GL.clearColor    $= GL.Color4 0.8 0.8 0.8 0
    
        -- set 2D orthogonal view inside windowSizeCallback because
        -- any change to the Window size should result in different
        -- OpenGL Viewport.
        GLFW.windowSizeCallback $= \ size@(GL.Size w h) ->
          do
            GL.viewport   $= (GL.Position 0 0, size)
            GL.matrixMode $= GL.Projection
            GL.loadIdentity
            GL.ortho2D 0 (realToFrac w) (realToFrac h) 0
    
        render <- initialize
        loop render
    
        GLFW.closeWindow
    
    loop render = do
        -- draw the entire screen
        render
        -- swap buffer
        GLFW.swapBuffers
        -- check whether ESC is pressed for termination
        p <- GLFW.getKey GLFW.ESC
        unless (p == GLFW.Press) $ do
            -- sleep for 1ms to yield CPU to other applications
            GLFW.sleep 0.001
            -- only continue when the window is not closed
            windowOpenStatus <- GLFW.getParam GLFW.Opened
            unless (windowOpenStatus == False) $
                loop render
    
    -- rendering
    initialize = do
        -- load texture from file
        GL.texture GL.Texture2D $= Enabled
        [textureName] <- GL.genObjectNames 1
        GL.textureBinding GL.Texture2D $= Just textureName
        GL.textureFilter  GL.Texture2D $= ((GL.Nearest, Nothing), GL.Nearest)
        GLFW.loadTexture2D "Bitmap.tga" []
    
        return $ do
            GL.clear [GL.ColorBuffer]
            GL.renderPrimitive GL.Quads $ do
                GL.texCoord $ texCoord2 0 0
                GL.vertex   $ vertex3 (0) 256 0
                GL.texCoord $ texCoord2 0 1
                GL.vertex   $ vertex3 (0) (0) 0
                GL.texCoord $ texCoord2 1 1
                GL.vertex   $ vertex3 256 (0) 0
                GL.texCoord $ texCoord2 1 0
                GL.vertex   $ vertex3 256 256 0
    
    -- type signatures to avoid ambiguity
    vertex3 :: GLfloat -> GLfloat -> GLfloat -> GL.Vertex3 GLfloat
    vertex3 = GL.Vertex3
    
    texCoord2 :: GLfloat -> GLfloat -> GL.TexCoord2 GLfloat
    texCoord2 = GL.TexCoord2
    
    color3 :: GLfloat -> GLfloat -> GLfloat -> GL.Color3 GLfloat
    color3 = GL.Color3
    

    Here an example bitmap (which you need to convert to .tga).

    Sample bitmap

    0 讨论(0)
  • 2021-01-30 07:55

    Have you seen the GLFW as referenced http://plucky.cs.yale.edu/soe/software1.htm

    0 讨论(0)
  • 2021-01-30 07:58

    The Gtk2Hs library fulfills all the requirements if you use the X11 version of the gtk2 framework.

    Concerning the requirements:

    1. Using X11 avoids many problems.
    2. Install gtk2 via MacPorts and use the +x11 option (default). (That said, I've had numerous problems installing gtk2 in the past, but this time it seemed to work.)
    3. I would be surprised if GTK+ can't do that.
    4. Ditto.

    Here a minimal example

    import Graphics.UI.Gtk
    
    hello :: (ButtonClass o) => o -> IO ()
    hello b = set b [buttonLabel := "Hello World"]
    
    main :: IO ()
    main = do
        initGUI
        window <- windowNew
        button <- buttonNew
        set window [windowDefaultWidth := 200, windowDefaultHeight := 200,
                  containerChild := button, containerBorderWidth := 10]
        onClicked button (hello button)
        onDestroy window mainQuit
        widgetShowAll window
        mainGUI
    
    0 讨论(0)
提交回复
热议问题