Графическая библиотека Haskell, которая работает в GHCi на MacOS X - PullRequest
33 голосов
/ 03 мая 2011

Существует ли графическая библиотека Haskell или привязка к внешней библиотеке, которая удовлетворяет следующим требованиям:

  1. Может использоваться с ghci, т.е. мне не нужно связывать и перезапускать программу.
  2. Работает на MacOS X. (Сложно в сочетании с 1!)
  3. Может создавать простую векторную графику (линии, многоугольники, простые заливки и обводки).
  4. Может выводить растровые изображения на экран. Пример: переверните изображение размером 17x12 .bmp.

Пожалуйста, включите минимальный пример исходного кода или ссылку на него (просто окно на экране, может быть, с зеленой линией, нарисованной внутри него), чтобы я мог проверить пункты 1. и 2. в частности. Кроме того, если один из этих запросов является более сложным (например, OpenGL + 4), пожалуйста, включите хорошую ссылку.


PS: Что касается 1 и 2, я знаю об уловке enableGUI и я готов ее использовать. Однако большинство библиотек имеют проблему, состоящую в том, что вы не можете запускать функцию main несколько раз и, следовательно, не подходите.


Редактировать: Чтобы не тратить свое время, вот список пакетов, которые я пробовал:

  • ш - GHCI дроссели на libstdc++
  • sdl - переопределяет main как макрос. Только во время компиляции.
  • GLFW (OpenGL) - Невозможно запустить main дважды, что-то из-за "сбоя, потому что он не может установить обработчик событий мыши".

Ответы [ 5 ]

15 голосов
/ 07 мая 2011

РЕДАКТИРОВАТЬ: На самом деле я больше не уверен. Несколько версий спустя, кажется, что GLFW больше не работает в GHCi на OS X.

Оказывается, GLFW + OpenGL соответствует всем четырем требованиям!

  1. Вам нужно вызвать ghci с помощью ghci -framework Carbon.
  2. Вам нужен файл EnableGUI.hs, который вы можете получить здесь . Обратите внимание, что вы не можете загрузить его прямо в GHCi, сначала вам нужно его скомпилировать.
  3. OpenGL имеет режим 2D-проекции, в котором вы можете рисовать линии и многоугольники.
  4. Растровые изображения можно загружать в виде текстур и накладывать на полигоны.

Вот небольшой пример, который выводит растровое изображение на экран. Существуют некоторые ограничения для растрового изображения: его размеры должны быть степенью двойки (здесь 256), и это должен быть файл .tga (здесь "Bitmap.tga"). Но поскольку прозрачность поддерживается, это не является большой проблемой.

Вы должны быть в состоянии звонить main несколько раз без проблем. Ключевым моментом является то, что вы не должны звонить 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

Вот пример растрового изображения (которое необходимо преобразовать в .tga).

Sample bitmap

3 голосов
/ 07 мая 2011

Библиотека Gtk2Hs удовлетворяет всем требованиям, если вы используете версию X11 фреймворка gtk2.

Относительно требований:

  1. Использование X11 позволяет избежать многих проблем.
  2. Установите gtk2 через MacPorts и используйте опцию + x11 (по умолчанию). (Тем не менее, у меня были многочисленные проблемы с установкой gtk2 в прошлом, но на этот раз, похоже, это сработало.)
  3. Я был бы удивлен, если бы GTK + не смог этого сделать.
  4. Ditto.

Вот минимальный пример

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
2 голосов
/ 07 апреля 2014

В начале 2014 года я не смог использовать ответ @ heinrich-apfelmus в Mac OS X. Однако этот пример GLFW-b ( ссылка ) сработал.

Итак,убедитесь, что у вас есть:

$ cabal install glfw-b

и, если вы попробовали ответ Апфельма, вам может потребоваться

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

, поскольку оба предоставляют Graphics.UI.GLFW, и вы получите "Неоднозначный модульназвание "Graphics.UI.GLFW" от GHC.Затем я просто попробовал приведенный выше пример программы, и она сработала (Mac OS X, 10.9, Mavericks)

1 голос
/ 18 мая 2011

Более подробная информация о Haskell + GUI + OpenGL доступна в этом обсуждении: http://www.haskell.org/pipermail/haskell-cafe/2011-May/091991.html

1 голос
/ 04 мая 2011

Вы видели GLFW, на который ссылаются http://plucky.cs.yale.edu/soe/software1.htm

...