mirror of
https://github.com/Drezil/dear-imgui.hs.git
synced 2024-12-25 14:06:35 +00:00
bb94341ad5
* Separate font utils, add glyph support (#113) * Implement font glyph ranges builder * Implement raw font config binds * Implement font atlas module * Rewrite font altas rebuilder in Managed
151 lines
4.2 KiB
Haskell
151 lines
4.2 KiB
Haskell
{-# language BlockArguments #-}
|
|
{-# language LambdaCase #-}
|
|
{-# language OverloadedStrings #-}
|
|
{-# language RecordWildCards #-}
|
|
{-# language NamedFieldPuns #-}
|
|
{-# language DeriveTraversable #-}
|
|
|
|
{- | Font usage example.
|
|
|
|
Loads two non-standard fonts
|
|
|
|
This example uses NotoSansJP-Regular.otf from Google Fonts
|
|
Licensed under the SIL Open Font License, Version 1.1
|
|
https://fonts.google.com/noto/specimen/Noto+Sans+JP
|
|
-}
|
|
|
|
module Main ( main ) where
|
|
|
|
import Control.Exception
|
|
import Control.Monad
|
|
import Control.Monad.IO.Class
|
|
import Control.Monad.Managed
|
|
import Data.IORef
|
|
import DearImGui
|
|
import qualified DearImGui.FontAtlas as FontAtlas
|
|
import DearImGui.OpenGL2
|
|
import DearImGui.SDL
|
|
import DearImGui.SDL.OpenGL
|
|
import Graphics.GL
|
|
import SDL
|
|
|
|
-- Rebuild syntax enables us to keep fonts in any
|
|
-- traversable type, so let's make our life a little easier.
|
|
-- But feel free to use lists or maps.
|
|
data FontSet a = FontSet
|
|
{ droidFont :: a
|
|
, defaultFont :: a
|
|
, notoFont :: a
|
|
}
|
|
deriving (Functor, Foldable, Traversable)
|
|
|
|
main :: IO ()
|
|
main = do
|
|
-- Window initialization is similar to another examples.
|
|
initializeAll
|
|
runManaged do
|
|
window <- do
|
|
let title = "Hello, Dear ImGui!"
|
|
let config = defaultWindow { windowGraphicsContext = OpenGLContext defaultOpenGL }
|
|
managed $ bracket (createWindow title config) destroyWindow
|
|
glContext <- managed $ bracket (glCreateContext window) glDeleteContext
|
|
_ <- managed $ bracket createContext destroyContext
|
|
_ <- managed_ $ bracket_ (sdl2InitForOpenGL window glContext) sdl2Shutdown
|
|
_ <- managed_ $ bracket_ openGL2Init openGL2Shutdown
|
|
|
|
-- We use high-level syntax to build font atlas and
|
|
-- get handles to use in the main loop.
|
|
fontSet <- FontAtlas.rebuild FontSet
|
|
{ -- The first mentioned font is loaded first
|
|
-- and set as a global default.
|
|
droidFont =
|
|
FontAtlas.FromTTF
|
|
"./imgui/misc/fonts/DroidSans.ttf"
|
|
15
|
|
Nothing
|
|
FontAtlas.Cyrillic
|
|
|
|
-- You also may use a default hardcoded font for
|
|
-- some purposes (i.e. as fallback)
|
|
, defaultFont =
|
|
FontAtlas.DefaultFont
|
|
|
|
-- To optimize atlas size, use ranges builder and
|
|
-- provide source localization data.
|
|
, notoFont =
|
|
FontAtlas.FromTTF
|
|
"./examples/fonts/NotoSansJP-Regular.otf"
|
|
20
|
|
Nothing
|
|
( FontAtlas.RangesBuilder $ mconcat
|
|
[ FontAtlas.addRanges FontAtlas.Latin
|
|
, FontAtlas.addText "私をクリックしてください"
|
|
, FontAtlas.addText "こんにちは"
|
|
]
|
|
)
|
|
}
|
|
|
|
liftIO $ do
|
|
fontFlag <- newIORef False
|
|
mainLoop window do
|
|
let FontSet{..} = fontSet
|
|
withWindowOpen "Hello, ImGui!" do
|
|
-- To use a font for widget text, you may either put it
|
|
-- into a 'withFont' block:
|
|
withFont defaultFont do
|
|
text "Hello, ImGui!"
|
|
|
|
text "Привет, ImGui!"
|
|
|
|
-- ...or you can explicitly push and pop a font.
|
|
-- Though it's not recommended.
|
|
toggled <- readIORef fontFlag
|
|
|
|
when toggled $
|
|
pushFont notoFont
|
|
|
|
-- Some of those are only present in Noto font range
|
|
-- and will render as `?`s.
|
|
text "こんにちは, ImGui!"
|
|
|
|
let buttonText = if toggled then "私をクリックしてください" else "Click Me!"
|
|
button buttonText >>= \clicked ->
|
|
when clicked $
|
|
modifyIORef' fontFlag not
|
|
|
|
when toggled
|
|
popFont
|
|
|
|
showDemoWindow
|
|
|
|
mainLoop :: Window -> IO () -> IO ()
|
|
mainLoop window frameAction = loop
|
|
where
|
|
loop = unlessQuit do
|
|
openGL2NewFrame
|
|
sdl2NewFrame
|
|
newFrame
|
|
|
|
frameAction
|
|
|
|
glClear GL_COLOR_BUFFER_BIT
|
|
render
|
|
openGL2RenderDrawData =<< getDrawData
|
|
glSwapWindow window
|
|
|
|
loop
|
|
|
|
unlessQuit action = do
|
|
shouldQuit <- checkEvents
|
|
if shouldQuit then pure () else action
|
|
|
|
checkEvents = do
|
|
pollEventWithImGui >>= \case
|
|
Nothing ->
|
|
return False
|
|
Just event ->
|
|
(isQuit event ||) <$> checkEvents
|
|
|
|
isQuit event =
|
|
SDL.eventPayload event == SDL.QuitEvent
|