diff --git a/ChangeLog.md b/ChangeLog.md index b76435a..60c3ab4 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -9,6 +9,8 @@ + Added `ImGui_ImplVulkan_DestroyFontsTexture`, but it shouldn't be needed as it is called from impl internals. * Breaking: ImplVulkan moved RenderPass into InitInfo structure. + Breaking: Haskell API is now using `Either RenderPass RenderingPipelineCreateInfo` to switch between RP/dynamic rendering. +- Added lots of missing widgets and their wrappers. +- Breaking: a few functions in `DearImGui` switched away from using CFloat/CBool wrappers. ## [2.2.1] diff --git a/dear-imgui.cabal b/dear-imgui.cabal index 6ce56d6..f66f2c1 100644 --- a/dear-imgui.cabal +++ b/dear-imgui.cabal @@ -162,6 +162,7 @@ library DearImGui.FontAtlas DearImGui.Internal.Text DearImGui.Raw + DearImGui.Raw.DragDrop DearImGui.Raw.DrawList DearImGui.Raw.Font DearImGui.Raw.Font.Config diff --git a/src/DearImGui.hs b/src/DearImGui.hs index b03e9c0..2a27628 100644 --- a/src/DearImGui.hs +++ b/src/DearImGui.hs @@ -32,11 +32,19 @@ module DearImGui -- * Demo, Debug, Information , Raw.showDemoWindow + , Raw.showIDStackToolWindow , Raw.showMetricsWindow , Raw.showAboutWindow + , Raw.showStyleSelector + , Raw.showFontSelector , Raw.showUserGuide , getVersion + -- * Logging + , Raw.showDebugLogWindow + , Raw.logButtons + , logText + -- * Styles , Raw.styleColorsDark , Raw.styleColorsLight @@ -57,8 +65,11 @@ module DearImGui , Raw.getWindowDrawList , Raw.getWindowPos , Raw.getWindowSize - , Raw.getWindowWidth - , Raw.getWindowHeight + , getWindowWidth + , getWindowHeight + , Raw.isWindowAppearing + , Raw.isWindowCollapsed + , Raw.isWindowFocused -- ** Manipulation , setNextWindowPos @@ -67,7 +78,13 @@ module DearImGui , setNextWindowContentSize , setNextWindowSizeConstraints , setNextWindowCollapsed + , Raw.setNextWindowFocus + , setNextWindowScroll , setNextWindowBgAlpha + , Raw.getContentRegionAvail + , Raw.getContentRegionMax + , Raw.getWindowContentRegionMin + , Raw.getWindowContentRegionMax -- ** Child Windows , withChild @@ -84,6 +101,9 @@ module DearImGui , withStyleVar , pushStyleVar , popStyleVar + , withTabStop + , pushTabStop + , Raw.popTabStop , withFont , Raw.Font.pushFont @@ -105,14 +125,28 @@ module DearImGui , withItemWidth , pushItemWidth , Raw.popItemWidth + , Raw.calcItemWidth + , withTextWrapPos + , pushTextWrapPos + , Raw.popTextWrapPos , withGroup , Raw.beginGroup , Raw.endGroup , setCursorPos + , setCursorPosX + , setCursorPosY + , setCursorScreenPos , Raw.getCursorPos + , getCursorPosX + , getCursorPosY + , Raw.getCursorStartPos , Raw.alignTextToFramePadding + , getTextLineHeight + , getTextLineHeightWithSpacing + , getFrameHeight + , getFrameHeightWithSpacing -- * ID stack , withID @@ -126,6 +160,11 @@ module DearImGui , textWrapped , labelText , bulletText + , separatorText + , valueBool + , valueFloat + , valueInt32 + , valueWord32 -- ** Main , button @@ -134,6 +173,10 @@ module DearImGui , arrowButton , Raw.image , checkbox + , checkboxFlags + , checkboxFlagsU + , radioButton + , radioButtonI , progressBar , Raw.bullet @@ -178,10 +221,24 @@ module DearImGui , inputText , inputTextMultiline , inputTextWithHint + , inputFloat + , inputFloat2 + , inputFloat3 + , inputFloat4 + , inputInt + , inputInt2 + , inputInt3 + , inputInt4 + , inputScalar + , inputScalarN -- ** Color Editor/Picker + , colorEdit3 + , colorEdit4 , colorPicker3 + , colorPicker4 , colorButton + , Raw.setColorEditOptions -- ** Tables , withTable @@ -229,6 +286,8 @@ module DearImGui , treePush , Raw.treePop , setNextItemOpen + , collapsingHeader + , getTreeNodeToLabelSpacing -- ** Selectables , selectable @@ -275,13 +334,15 @@ module DearImGui , setTabItemClosed -- ** Tooltips + , setItemTooltip + , withItemTooltip , withTooltip , Raw.beginTooltip , Raw.endTooltip -- ** Disabled blocks , withDisabled - , Raw.beginDisabled + , beginDisabled , Raw.endDisabled -- * Popups/Modals @@ -327,10 +388,38 @@ module DearImGui -- * Item/Widgets Utilities , Raw.isItemHovered + , Raw.isItemActive + , Raw.isItemFocused + , Raw.isItemClicked + , Raw.isItemVisible + , Raw.isItemEdited + , Raw.isItemActivated + , Raw.isItemDeactivated + , Raw.isItemDeactivatedAfterEdit + , Raw.isItemToggledOpen + , Raw.isAnyItemHovered + , Raw.isAnyItemActive + , Raw.isAnyItemFocused + , Raw.getItemID + , Raw.getItemRectMin + , Raw.getItemRectMax + , Raw.getItemRectSize + + -- * Utilities , Raw.wantCaptureMouse + , Raw.getMousePos + , Raw.getMousePosOnOpeningCurrentPopup + , Raw.isMouseDragging + , Raw.getMouseDragDelta + , Raw.resetMouseDragDelta + , Raw.wantCaptureKeyboard + , Raw.shortcut + , Raw.setNextItemShortcut - -- * Utilities + , Raw.setItemDefaultFocus + , Raw.setKeyboardFocusHere + , Raw.setNextItemAllowOverlap -- ** ListClipper , withListClipper @@ -342,6 +431,9 @@ module DearImGui , Raw.getForegroundDrawList , Raw.imCol32 , Raw.framerate + , Raw.getTime + , Raw.getFrameCount + , calcTextSize -- * Types , module DearImGui.Enums @@ -393,6 +485,11 @@ getVersion :: MonadIO m => m Text getVersion = liftIO do Raw.getVersion >>= Text.peekCString +-- | Send text to logs. +logText :: MonadIO m => Text -> m () +logText t = liftIO do + Text.withCString t Raw.logText + -- | Push window to the stack and start appending to it. -- -- Returns 'False' to indicate the window is collapsed or fully clipped, so you @@ -558,6 +655,33 @@ bulletText :: MonadIO m => Text -> m () bulletText t = liftIO do Text.withCString t Raw.bulletText +-- | Text with an horizontal line. +separatorText :: MonadIO m => Text -> m () +separatorText t = liftIO do + Text.withCString t Raw.separatorText + +-- | Shortcut for a labelled Bool. +valueBool :: MonadIO m => Text -> Bool -> m () +valueBool t b = liftIO do + Text.withCString t \tPtr -> Raw.valueBool tPtr (bool 0 1 b) + +-- | Shortcut for a labelled Int. +valueInt32 :: MonadIO m => Text -> Int32 -> m () +valueInt32 t i = liftIO do + Text.withCString t \tPtr -> Raw.valueInt tPtr (CInt i) + +-- | Shortcut for a labelled Word. +valueWord32 :: MonadIO m => Text -> Word32 -> m () +valueWord32 t w = liftIO do + Text.withCString t \tPtr -> Raw.valueUInt tPtr (CUInt w) + +-- | Shortcut for a labelled Float. +valueFloat :: MonadIO m => Text -> Float -> Text -> m () +valueFloat t f format = liftIO do + Text.withCString t \tPtr -> + Text.withCString format \formatPtr -> + Raw.valueFloat tPtr (CFloat f) formatPtr + -- | A button. Returns 'True' when clicked. -- -- Wraps @ImGui::Button()@. @@ -611,6 +735,55 @@ checkbox label ref = liftIO do return changed +-- | Checkbox for a bit mask inside a signed value. +checkboxFlags :: (HasSetter ref Int32, HasGetter ref Int32, MonadIO m) => Text -> ref -> Int32 -> m Bool +checkboxFlags label ref flagsValue = liftIO do + currentValue <- get ref + Text.withCString label \labelPtr -> + with (CInt currentValue) \flagsPtr -> do + changed <- Raw.checkboxFlags labelPtr flagsPtr (CInt flagsValue) + + when changed do + CInt newValue <- peek flagsPtr + ref $=! newValue + + return changed + + +-- | Checkbox for a bit mask inside an unsigned value. +checkboxFlagsU :: (HasSetter ref Word32, HasGetter ref Word32, MonadIO m) => Text -> ref -> Word32 -> m Bool +checkboxFlagsU label ref flagsValue = liftIO do + currentValue <- get ref + Text.withCString label \labelPtr -> + with (CUInt currentValue) \flagsPtr -> do + changed <- Raw.checkboxFlagsU labelPtr flagsPtr (CUInt flagsValue) + + when changed do + CUInt newValue <- peek flagsPtr + ref $=! newValue + + return changed + +radioButton :: MonadIO m => Text -> Bool -> m Bool +radioButton label b = liftIO do + Text.withCString label \labelPtr -> + Raw.radioButton labelPtr (bool 0 1 b) + + +radioButtonI :: (HasSetter ref Int32, HasGetter ref Int32, MonadIO m) => Text -> ref -> Int32 -> m Bool +radioButtonI label ref vButton = liftIO do + currentValue <- get ref + Text.withCString label \labelPtr -> + with (CInt currentValue) \valuePtr -> do + changed <- Raw.radioButtonI labelPtr valuePtr (CInt vButton) + + when changed do + CInt newValue <- peek valuePtr + ref $=! newValue + + return changed + + progressBar :: MonadIO m => Float -> Maybe Text -> m () progressBar progress overlay = liftIO do Text.withCStringOrNull overlay \overlayPtr -> @@ -1309,18 +1482,225 @@ withInputString ref bufSize action = liftIO do max refSize bufSize + 5 -- XXX: max size of UTF8 code point + NUL terminator +inputFloat :: (MonadIO m, HasSetter ref Float, HasGetter ref Float) => Text -> ref -> Float -> Float -> m Bool +inputFloat desc ref step stepFast = liftIO do + currentValue <- get ref + with (CFloat currentValue) \floatPtr -> do + changed <- Text.withCString desc \descPtr -> + Raw.inputFloat descPtr floatPtr (CFloat step) (CFloat stepFast) nullPtr ImGuiInputTextFlags_None + + when changed do + CFloat newValue <- peek floatPtr + ref $=! newValue + + return changed + +inputFloat2 :: (MonadIO m, HasSetter ref (Float, Float), HasGetter ref (Float, Float)) => Text -> ref -> m Bool +inputFloat2 desc ref = liftIO do + (x, y) <- get ref + withArray [ CFloat x, CFloat y ] \floatPtr -> do + changed <- Text.withCString desc \descPtr -> + Raw.inputFloat2 descPtr floatPtr nullPtr ImGuiInputTextFlags_None + + when changed do + [CFloat x', CFloat y'] <- peekArray 2 floatPtr + ref $=! (x', y') + + return changed + +inputFloat3 :: (MonadIO m, HasSetter ref (Float, Float, Float), HasGetter ref (Float, Float, Float)) => Text -> ref -> m Bool +inputFloat3 desc ref = liftIO do + (x, y, z) <- get ref + withArray [ CFloat x, CFloat y, CFloat z ] \floatPtr -> do + changed <- Text.withCString desc \descPtr -> + Raw.inputFloat3 descPtr floatPtr nullPtr ImGuiInputTextFlags_None + + when changed do + [CFloat x', CFloat y', CFloat z'] <- peekArray 3 floatPtr + ref $=! (x', y', z') + + return changed + +inputFloat4 :: (MonadIO m, HasSetter ref (Float, Float, Float, Float), HasGetter ref (Float, Float, Float, Float)) => Text -> ref -> m Bool +inputFloat4 desc ref = liftIO do + (x, y, z, u) <- get ref + withArray [ CFloat x, CFloat y, CFloat z, CFloat u ] \floatPtr -> do + changed <- Text.withCString desc \descPtr -> + Raw.inputFloat4 descPtr floatPtr nullPtr ImGuiInputTextFlags_None + + when changed do + [CFloat x', CFloat y', CFloat z', CFloat u'] <- peekArray 4 floatPtr + ref $=! (x', y', z', u') + + return changed + +inputInt :: (MonadIO m, HasSetter ref Int32, HasGetter ref Int32) => Text -> ref -> Int32 -> Int32 -> m Bool +inputInt desc ref step stepFast = liftIO do + currentValue <- get ref + with (CInt currentValue) \intPtr -> do + changed <- Text.withCString desc \descPtr -> + Raw.inputInt descPtr intPtr (CInt step) (CInt stepFast) ImGuiInputTextFlags_None + + when changed do + CInt newValue <- peek intPtr + ref $=! newValue + + return changed + +inputInt2 :: (MonadIO m, HasSetter ref (Int32, Int32), HasGetter ref (Int32, Int32)) => Text -> ref -> m Bool +inputInt2 desc ref = liftIO do + (x, y) <- get ref + withArray [ CInt x, CInt y ] \intPtr -> do + changed <- Text.withCString desc \descPtr -> + Raw.inputInt2 descPtr intPtr ImGuiInputTextFlags_None + + when changed do + [CInt x', CInt y'] <- peekArray 2 intPtr + ref $=! (x', y') + + return changed + +inputInt3 :: (MonadIO m, HasSetter ref (Int32, Int32, Int32), HasGetter ref (Int32, Int32, Int32)) => Text -> ref -> m Bool +inputInt3 desc ref = liftIO do + (x, y, z) <- get ref + withArray [ CInt x, CInt y, CInt z ] \intPtr -> do + changed <- Text.withCString desc \descPtr -> + Raw.inputInt3 descPtr intPtr ImGuiInputTextFlags_None + + when changed do + [CInt x', CInt y', CInt z'] <- peekArray 3 intPtr + ref $=! (x', y', z') + + return changed + +inputInt4 :: (MonadIO m, HasSetter ref (Int32, Int32, Int32, Int32), HasGetter ref (Int32, Int32, Int32, Int32)) => Text -> ref -> m Bool +inputInt4 desc ref = liftIO do + (x, y, z, u) <- get ref + withArray [ CInt x, CInt y, CInt z, CInt u ] \intPtr -> do + changed <- Text.withCString desc \descPtr -> + Raw.inputInt4 descPtr intPtr ImGuiInputTextFlags_None + + when changed do + [CInt x', CInt y', CInt z', CInt u'] <- peekArray 4 intPtr + ref $=! (x', y', z', u') + + return changed + +inputScalar + :: (HasGetter ref a, HasSetter ref a, HasGetter range a, Storable a, MonadIO m) + => Text -> ImGuiDataType -> ref -> range -> range -> Text -> ImGuiInputTextFlags -> m Bool +inputScalar label dataType ref refMin refMax format flags = liftIO do + currentValue <- get ref + minValue <- get refMin + maxValue <- get refMax + + with currentValue \dataPtr -> + with minValue \minPtr -> + with maxValue \maxPtr -> do + changed <- + Text.withCString label \labelPtr -> + Text.withCString format \formatPtr -> + Raw.inputScalar + labelPtr + dataType + dataPtr + minPtr + maxPtr + formatPtr + flags + + when changed do + newValue <- peek dataPtr + ref $=! newValue + + return changed + +inputScalarN + :: (HasSetter value [a], HasGetter value [a], HasGetter range a, Storable a, MonadIO m) + => Text -> ImGuiDataType -> value -> range -> range -> Text -> ImGuiInputTextFlags -> m Bool +inputScalarN label dataType ref refMin refMax format flags = liftIO do + currentValues <- get ref + minValue <- get refMin + maxValue <- get refMax + + withArrayLen currentValues \components dataPtr -> + with minValue \minPtr -> + with maxValue \maxPtr -> do + changed <- + Text.withCString label \labelPtr -> + Text.withCString format \formatPtr -> + Raw.inputScalarN + labelPtr + dataType + dataPtr + (fromIntegral components) + minPtr + maxPtr + formatPtr + flags + + when changed do + newValue <- peekArray components dataPtr + ref $=! newValue + + return changed + +-- | Wraps @ImGui::ColorPicker3()@. +colorEdit3 :: (MonadIO m, HasSetter ref ImVec3, HasGetter ref ImVec3) => Text -> ref -> m Bool +colorEdit3 desc ref = liftIO do + currentValue <- get ref + with currentValue \refPtr -> do + changed <- Text.withCString desc \descPtr -> + Raw.colorEdit3 descPtr (castPtr refPtr) ImGuiColorEditFlags_None + + when changed do + newValue <- peek refPtr + ref $=! newValue + + return changed + + +-- | Wraps @ImGui::ColorEdit3()@. +colorEdit4 :: (MonadIO m, HasSetter ref ImVec4, HasGetter ref ImVec4) => Text -> ref -> m Bool +colorEdit4 desc ref = liftIO do + currentValue <- get ref + with currentValue \refPtr -> do + changed <- Text.withCString desc \descPtr -> + Raw.colorEdit4 descPtr (castPtr refPtr) ImGuiColorEditFlags_None + + when changed do + newValue <- peek refPtr + ref $=! newValue + + return changed + -- | Wraps @ImGui::ColorPicker3()@. colorPicker3 :: (MonadIO m, HasSetter ref ImVec3, HasGetter ref ImVec3) => Text -> ref -> m Bool colorPicker3 desc ref = liftIO do - ImVec3{x, y, z} <- get ref - withArray (realToFrac <$> [x, y, z]) \refPtr -> do + currentValue <- get ref + with currentValue \refPtr -> do changed <- Text.withCString desc \descPtr -> - Raw.colorPicker3 descPtr refPtr + Raw.colorPicker3 descPtr (castPtr refPtr) ImGuiColorEditFlags_None when changed do - [x', y', z'] <- peekArray 3 refPtr - ref $=! ImVec3 (realToFrac x') (realToFrac y') (realToFrac z') + newValue <- peek refPtr + ref $=! newValue + + return changed + +-- | Wraps @ImGui::ColorPicker3()@. +colorPicker4 :: (MonadIO m, HasSetter ref ImVec4, HasGetter ref ImVec4) => Text -> ref -> Maybe ImVec4 -> m Bool +colorPicker4 desc ref refColor = liftIO do + currentValue <- get ref + with currentValue \refPtr -> do + changed <- Text.withCString desc \descPtr -> + maybeWith with refColor \refColorPtr -> + Raw.colorPicker4 descPtr (castPtr refPtr) ImGuiColorEditFlags_None (castPtr refColorPtr) + + when changed do + newValue <- peek refPtr + ref $=! newValue return changed @@ -1575,6 +1955,17 @@ treePush :: MonadIO m => Text -> m () treePush label = liftIO do Text.withCString label Raw.treePush +getTreeNodeToLabelSpacing :: (MonadIO m) => m Float +getTreeNodeToLabelSpacing = liftIO do + CFloat x <- Raw.getTreeNodeToLabelSpacing + pure x + +collapsingHeader :: (MonadIO m) => Text -> Maybe Bool -> m Bool +collapsingHeader label visible = liftIO do + Text.withCString label \labelPtr -> + maybeWith with (bool 0 1 <$> visible) \visiblePtr -> + Raw.collapsingHeader labelPtr visiblePtr ImGuiTreeNodeFlags_None + -- | Wraps @ImGui::SetNextItemOpen()@. setNextItemOpen :: MonadIO m => Bool -> m () setNextItemOpen is_open = Raw.setNextItemOpen (bool 0 1 is_open) @@ -1761,12 +2152,24 @@ setTabItemClosed :: MonadIO m => Text -> m () setTabItemClosed tabName = liftIO do Text.withCString tabName Raw.setTabItemClosed +-- | Set a text-only tooltip if preceding item was hovered. +setItemTooltip :: MonadIO m => Text -> m () +setItemTooltip tabName = liftIO do + Text.withCString tabName Raw.setItemTooltip + +-- | Create a tooltip if a previous item is hovered. +-- +-- Those are windows that follow a mouse and don't take focus away. +-- Can contain any kind of items. +withItemTooltip :: MonadUnliftIO m => m () -> m () +withItemTooltip action = bracket Raw.beginItemTooltip (`when` Raw.endTooltip) (`when` action) + -- | Create a tooltip. -- -- Those are windows that follow a mouse and don't take focus away. -- Can contain any kind of items. -withTooltip :: MonadUnliftIO m => m a -> m a -withTooltip = bracket_ Raw.beginTooltip Raw.endTooltip +withTooltip :: MonadUnliftIO m => m () -> m () +withTooltip action = bracket Raw.beginItemTooltip (`when` Raw.endTooltip) (`when` action) -- | Action wrapper for disabled blocks. @@ -1777,7 +2180,12 @@ withDisabled disabledRef action = do disabled <- get disabledRef if disabled then bracket_ (Raw.beginDisabled 1) Raw.endDisabled action else action - +-- | Begin a block that may be disabled. This disables all user interactions +-- and dims item visuals. +-- +-- Always call a matching 'endDisabled' for each 'beginDisabled' call. +beginDisabled :: MonadIO m => Bool -> m () +beginDisabled = Raw.beginDisabled . bool 0 1 -- | Returns 'True' if the popup is open, and you can start outputting to it. -- @@ -1921,6 +2329,15 @@ isAnyLevelPopupOpen popupId = liftIO do Raw.isPopupOpen idPtr $ ImGuiPopupFlags_AnyPopupId .|. ImGuiPopupFlags_AnyPopupLevel +getWindowWidth :: MonadIO m => m Float +getWindowWidth = liftIO do + CFloat w <- Raw.getWindowWidth + pure w + +getWindowHeight :: MonadIO m => m Float +getWindowHeight = liftIO do + CFloat w <- Raw.getWindowHeight + pure w -- | Set next window position. Call before `begin` Use pivot=(0.5,0.5) to center on given point, etc. -- @@ -1979,6 +2396,9 @@ setNextWindowCollapsed :: (MonadIO m) => Bool -> ImGuiCond -> m () setNextWindowCollapsed b cond = liftIO do Raw.setNextWindowCollapsed (bool 0 1 b) cond +setNextWindowScroll :: (MonadIO m) => ImVec2 -> m () +setNextWindowScroll scroll = liftIO do + with scroll Raw.setNextWindowScroll -- | Set next window background color alpha. helper to easily override the Alpha component of `ImGuiCol_WindowBg`, `ChildBg`, `PopupBg`. you may also use `ImGuiWindowFlags_NoBackground`. -- @@ -2033,6 +2453,18 @@ pushItemWidth :: (MonadIO m) => Float -> m () pushItemWidth itemWidth = liftIO do Raw.pushItemWidth (CFloat itemWidth) +withTextWrapPos :: MonadUnliftIO m => Float -> m a -> m a +withTextWrapPos width = + bracket_ (pushTextWrapPos width) Raw.popTextWrapPos + +-- | Push word-wrapping position for Text commands. +-- +-- Negative: no wrapping. +-- Zero: wrap to end of window (or column). +-- Positive: wrap at 'wrap_pos_x' position in window local space. +pushTextWrapPos :: (MonadIO m) => Float -> m () +pushTextWrapPos wrapLocalPosX = liftIO do + Raw.pushTextWrapPos (CFloat wrapLocalPosX) -- | Lock horizontal starting position -- @@ -2048,6 +2480,46 @@ setCursorPos posRef = liftIO do pos <- get posRef with pos Raw.setCursorPos +setCursorPosX :: (MonadIO m) => Float -> m () +setCursorPosX x = Raw.setCursorPosX (CFloat x) + +setCursorPosY :: (MonadIO m) => Float -> m () +setCursorPosY y = Raw.setCursorPosY (CFloat y) + +setCursorScreenPos :: (MonadIO m) => ImVec2 -> m () +setCursorScreenPos pos = liftIO do + with pos Raw.setCursorScreenPos + +getCursorPosX :: (MonadIO m) => m Float +getCursorPosX = liftIO do + CFloat x <- Raw.getCursorPosX + pure x + +getCursorPosY :: (MonadIO m) => m Float +getCursorPosY = liftIO do + CFloat y <- Raw.getCursorPosY + pure y + +getTextLineHeight :: (MonadIO m) => m Float +getTextLineHeight = liftIO do + CFloat h <- Raw.getTextLineHeight + pure h + +getTextLineHeightWithSpacing :: (MonadIO m) => m Float +getTextLineHeightWithSpacing = liftIO do + CFloat h <- Raw.getTextLineHeightWithSpacing + pure h + +getFrameHeight :: (MonadIO m) => m Float +getFrameHeight = liftIO do + CFloat h <- Raw.getFrameHeight + pure h + +getFrameHeightWithSpacing :: (MonadIO m) => m Float +getFrameHeightWithSpacing = liftIO do + CFloat h <- Raw.getFrameHeightWithSpacing + pure h + -- | Add an element to a ID stack -- -- Read the FAQ (http://dearimgui.org/faq) for more details @@ -2106,6 +2578,15 @@ withStyleVar :: (MonadUnliftIO m, HasGetter ref ImVec2) => ImGuiStyleVar -> ref withStyleVar style ref = bracket_ (pushStyleVar style ref) (Raw.popStyleVar 1) +-- | Allow/disable focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets. +withTabStop :: MonadUnliftIO m => Bool -> m a -> m a +withTabStop enabled = + bracket_ (pushTabStop enabled) Raw.popTabStop + +-- | Allow/disable focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets. +pushTabStop :: (MonadIO m) => Bool -> m () +pushTabStop = Raw.pushTabStop . bool 0 1 + -- | Modify a style variable by pushing to the shared stack. -- -- Always use this if you modify the style after `newFrame`. @@ -2156,6 +2637,11 @@ withListClipper itemHeight items action = go clipper +calcTextSize :: MonadIO m => Text -> Bool -> Float -> m ImVec2 +calcTextSize t hideAfterDoubleHash wrapWidth = liftIO do + Text.withCStringLen t \(textPtr, textLen) -> + Raw.calcTextSize textPtr (textPtr `plusPtr` textLen) (bool 0 1 hideAfterDoubleHash) (CFloat wrapWidth) + -- | Containers usable with 'ListClipper'. class ClipItems t a where itemCount :: t a -> Maybe Int diff --git a/src/DearImGui/Raw.hs b/src/DearImGui/Raw.hs index e4c8392..fe58a12 100644 --- a/src/DearImGui/Raw.hs +++ b/src/DearImGui/Raw.hs @@ -35,9 +35,15 @@ module DearImGui.Raw -- * Demo, Debug, Information , showDemoWindow , showMetricsWindow + , showDebugLogWindow + , showIDStackToolWindow , showAboutWindow + , showStyleSelector + , showFontSelector , showUserGuide , getVersion + , logButtons + , logText -- * Styles , styleColorsDark @@ -55,6 +61,9 @@ module DearImGui.Raw , getWindowSize , getWindowWidth , getWindowHeight + , isWindowAppearing + , isWindowCollapsed + , isWindowFocused -- ** Manipulation @@ -64,10 +73,21 @@ module DearImGui.Raw , setNextWindowContentSize , setNextWindowSizeConstraints , setNextWindowCollapsed + , setNextWindowFocus + , setNextWindowScroll , setNextWindowBgAlpha + , getContentRegionAvail + , getContentRegionMax + , getWindowContentRegionMin + , getWindowContentRegionMax , beginDisabled , endDisabled + , setItemDefaultFocus + , setKeyboardFocusHere + + , setNextItemAllowOverlap + -- ** Child Windows , beginChild , beginChildContext @@ -78,6 +98,8 @@ module DearImGui.Raw , popStyleColor , pushStyleVar , popStyleVar + , pushTabStop + , popTabStop -- * Cursor/Layout , separator @@ -90,12 +112,25 @@ module DearImGui.Raw , setNextItemWidth , pushItemWidth , popItemWidth + , calcItemWidth + , pushTextWrapPos + , popTextWrapPos , beginGroup , endGroup , getCursorPos - , setCursorPos + , getCursorPosX + , getCursorPosY , getCursorScreenPos + , getCursorStartPos + , setCursorPos + , setCursorPosX + , setCursorPosY + , setCursorScreenPos , alignTextToFramePadding + , getTextLineHeight + , getTextLineHeightWithSpacing + , getFrameHeight + , getFrameHeightWithSpacing -- * Widgets -- ** Text @@ -105,6 +140,11 @@ module DearImGui.Raw , textWrapped , labelText , bulletText + , separatorText + , valueBool + , valueInt + , valueUInt + , valueFloat -- ** Main , button @@ -114,6 +154,10 @@ module DearImGui.Raw , image , imageButton , checkbox + , checkboxFlags + , checkboxFlagsU + , radioButton + , radioButtonI , progressBar , bullet @@ -156,10 +200,25 @@ module DearImGui.Raw , inputText , inputTextMultiline , inputTextWithHint + , inputFloat + , inputFloat2 + , inputFloat3 + , inputFloat4 + , inputInt + , inputInt2 + , inputInt3 + , inputInt4 + , inputDouble + , inputScalar + , inputScalarN -- * Color Editor/Picker + , colorEdit3 + , colorEdit4 , colorPicker3 + , colorPicker4 , colorButton + , setColorEditOptions -- * Tables , beginTable @@ -188,6 +247,8 @@ module DearImGui.Raw , treeNode , treePush , treePop + , getTreeNodeToLabelSpacing + , collapsingHeader , setNextItemOpen -- ** Selectables @@ -218,6 +279,8 @@ module DearImGui.Raw , setTabItemClosed -- * Tooltips + , setItemTooltip + , beginItemTooltip , beginTooltip , endTooltip @@ -242,9 +305,37 @@ module DearImGui.Raw -- * Item/Widgets Utilities , isItemHovered + , isItemActive + , isItemFocused + , isItemClicked + , isItemVisible + , isItemEdited + , isItemActivated + , isItemDeactivated + , isItemDeactivatedAfterEdit + , isItemToggledOpen + , isAnyItemHovered + , isAnyItemActive + , isAnyItemFocused + , getItemID + , getItemRectMin + , getItemRectMax + , getItemRectSize + , wantCaptureMouse + , getMousePos + , getMousePosOnOpeningCurrentPopup + , isMouseDragging + , getMouseDragDelta + , resetMouseDragDelta + , wantCaptureKeyboard + -- ** Inputs Utilities: Shortcut Testing & Routing @BETA@ + , ImGuiKeyChord + , shortcut + , setNextItemShortcut + -- * Utilities -- ** Miscellaneous @@ -252,6 +343,11 @@ module DearImGui.Raw , getForegroundDrawList , imCol32 , framerate + , getTime + , getFrameCount + + -- ** Text utilities + , calcTextSize -- * Types , module DearImGui.Enums @@ -367,6 +463,15 @@ showMetricsWindow :: (MonadIO m) => m () showMetricsWindow = liftIO do [C.exp| void { ShowMetricsWindow(); } |] +-- | Create Debug Log window. display a simplified log of important dear imgui events. +showDebugLogWindow :: (MonadIO m) => m () +showDebugLogWindow = liftIO do + [C.exp| void { ShowDebugLogWindow(); } |] + +-- | Create Stack Tool window. hover items with mouse to query information about the source of their unique ID. +showIDStackToolWindow :: (MonadIO m) => m () +showIDStackToolWindow = liftIO do + [C.exp| void { ShowIDStackToolWindow(); } |] -- | Create About window. display Dear ImGui version, credits and build/system -- information. @@ -374,6 +479,34 @@ showAboutWindow :: (MonadIO m) => m () showAboutWindow = liftIO do [C.exp| void { ShowAboutWindow(); } |] +{- TODO: requires ImGuiStyle. +-- | Add style editor block (not a window). you can pass in a reference "ImGuiStyle" structure to compare to, revert to and save to (else it uses the default style). +showStyleEditor :: (MonadIO m) => Ptr ImGuiStyle -> m () +showStyleEditor = liftIO do + [C.exp| void { ShowStyleEditor(); } |] +-} + +-- | Add style selector block (not a window), essentially a combo listing the default styles. +showStyleSelector :: (MonadIO m) => CString -> m Bool +showStyleSelector labelPtr = liftIO do + (0 /=) <$> [C.exp| + bool { + ShowStyleSelector( + $(char* labelPtr) + ) + } + |] + +-- | Add font selector block (not a window), essentially a combo listing the loaded fonts. +showFontSelector :: (MonadIO m) => CString -> m () +showFontSelector labelPtr = liftIO do + [C.exp| + void { + ShowFontSelector( + $(char* labelPtr) + ) + } + |] -- | Add basic help/info block (not a window): how to manipulate ImGui as a -- end-user (mouse/keyboard controls). @@ -388,6 +521,15 @@ getVersion :: (MonadIO m) => m CString getVersion = liftIO do [C.exp| const char* { GetVersion() } |] +-- | Helper to display buttons for logging to tty/file/clipboard. +logButtons :: (MonadIO m) => m () +logButtons = liftIO do + [C.block| void { LogButtons(); } |] + +-- | Pass text data straight to log (without being displayed). +logText :: (MonadIO m) => CString -> m () +logText textPtr = liftIO do + [C.block| void { LogText("%s", $(char* textPtr) ); }|] -- | New, recommended style (default). -- @@ -487,6 +629,29 @@ endChild :: (MonadIO m) => m () endChild = liftIO do [C.exp| void { EndChild(); } |] +isWindowAppearing :: (MonadIO m) => m Bool +isWindowAppearing = liftIO do + (0 /=) <$> [C.exp| + bool { + IsWindowAppearing() + } + |] + +isWindowCollapsed :: (MonadIO m) => m Bool +isWindowCollapsed = liftIO do + (0 /=) <$> [C.exp| + bool { + IsWindowCollapsed() + } + |] + +isWindowFocused :: (MonadIO m) => ImGuiFocusedFlags -> m Bool +isWindowFocused flags = liftIO do + (0 /=) <$> [C.exp| + bool { + IsWindowFocused($(ImGuiFocusedFlags flags)) + } + |] -- | Separator, generally horizontal. inside a menu bar or in horizontal layout -- mode, this becomes a vertical separator. @@ -565,6 +730,27 @@ bulletText :: (MonadIO m) => CString -> m () bulletText textPtr = liftIO do [C.exp| void { BulletText("%s", $(char* textPtr)) } |] +-- | Text with an horizontal line. +separatorText :: (MonadIO m) => CString -> m () +separatorText textPtr = liftIO do + [C.block| void { SeparatorText($(char* textPtr)); } |] + +valueBool :: (MonadIO m) => CString -> CBool -> m () +valueBool labelPtr b = liftIO do + [C.block| void { Value($(char* labelPtr), $(bool b)); } |] + +valueInt :: (MonadIO m) => CString -> CInt -> m () +valueInt labelPtr v = liftIO do + [C.block| void { Value($(char* labelPtr), $(int v)); } |] + +valueUInt :: (MonadIO m) => CString -> CUInt -> m () +valueUInt labelPtr v = liftIO do + [C.block| void { Value($(char* labelPtr), $(unsigned int v)); } |] + +valueFloat :: (MonadIO m) => CString -> CFloat -> CString -> m () +valueFloat labelPtr v formatPtr = liftIO do + [C.block| void { Value($(char* labelPtr), $(float v), $(char* formatPtr)); } |] + -- | A button. Returns 'True' when clicked. -- -- Wraps @ImGui::Button()@. @@ -656,6 +842,24 @@ checkbox :: (MonadIO m) => CString -> Ptr CBool -> m Bool checkbox labelPtr boolPtr = liftIO do (0 /=) <$> [C.exp| bool { Checkbox($(char* labelPtr), $(bool* boolPtr)) } |] +-- | A checkbox toggling a bit mask (signed). +checkboxFlags :: (MonadIO m) => CString -> Ptr CInt -> CInt -> m Bool +checkboxFlags labelPtr flagsPtr flagsValue = liftIO do + (0 /=) <$> [C.exp| bool { CheckboxFlags($(char* labelPtr), $(int* flagsPtr), $(int flagsValue)) } |] + +-- | A checkbox toggling a bit mask (unsigned). +checkboxFlagsU :: (MonadIO m) => CString -> Ptr CUInt -> CUInt -> m Bool +checkboxFlagsU labelPtr flagsPtr flagsValue = liftIO do + (0 /=) <$> [C.exp| bool { CheckboxFlags($(char* labelPtr), $(unsigned int* flagsPtr), $(unsigned int flagsValue)) } |] + +radioButton :: (MonadIO m) => CString -> CBool -> m Bool +radioButton labelPtr active = liftIO do + (0 /=) <$> [C.exp| bool { RadioButton($(char* labelPtr), $(bool active)) } |] + +-- | A shortcut for "radioButton" when the value is an integer. +radioButtonI :: (MonadIO m) => CString -> Ptr CInt -> CInt -> m Bool +radioButtonI labelPtr v vButton = liftIO do + (0 /=) <$> [C.exp| bool { RadioButton($(char* labelPtr), $(int* v), $(int vButton)) } |] -- TODO: publish ImVec2(-FLT_MIN, 0) -- | Wraps @ImGui::ProgressBar()@. @@ -1083,12 +1287,103 @@ inputTextWithHint labelPtr hintPtr (bufPtr, fromIntegral -> bufSize) flags = lif } |] +inputFloat :: (MonadIO m) => CString -> Ptr CFloat -> CFloat -> CFloat -> CString -> ImGuiInputTextFlags -> m Bool +inputFloat descPtr floatPtr step stepFast formatPtr flags = liftIO do + (0 /=) <$> [C.exp| bool { InputFloat( $(char* descPtr), $(float* floatPtr), $(float step), $(float stepFast), $(char* formatPtr), $(ImGuiInputTextFlags flags)) } |] + +inputFloat2 :: (MonadIO m) => CString -> Ptr CFloat -> CString -> ImGuiInputTextFlags -> m Bool +inputFloat2 descPtr floatPtr formatPtr flags = liftIO do + (0 /=) <$> [C.exp| bool { InputFloat2( $(char* descPtr), $(float* floatPtr), $(char* formatPtr), $(ImGuiInputTextFlags flags)) } |] + +inputFloat3 :: (MonadIO m) => CString -> Ptr CFloat -> CString -> ImGuiInputTextFlags -> m Bool +inputFloat3 descPtr floatPtr formatPtr flags = liftIO do + (0 /=) <$> [C.exp| bool { InputFloat3( $(char* descPtr), $(float* floatPtr), $(char* formatPtr), $(ImGuiInputTextFlags flags)) } |] + +inputFloat4 :: (MonadIO m) => CString -> Ptr CFloat -> CString -> ImGuiInputTextFlags -> m Bool +inputFloat4 descPtr floatPtr formatPtr flags = liftIO do + (0 /=) <$> [C.exp| bool { InputFloat4( $(char* descPtr), $(float* floatPtr), $(char* formatPtr), $(ImGuiInputTextFlags flags)) } |] + +inputInt :: (MonadIO m) => CString -> Ptr CInt -> CInt -> CInt -> ImGuiInputTextFlags -> m Bool +inputInt descPtr intPtr step stepFast flags = liftIO do + (0 /=) <$> [C.exp| bool { InputInt( $(char* descPtr), $(int* intPtr), $(int step), $(int stepFast), $(ImGuiInputTextFlags flags)) } |] + +inputInt2 :: (MonadIO m) => CString -> Ptr CInt -> ImGuiInputTextFlags -> m Bool +inputInt2 descPtr intPtr flags = liftIO do + (0 /=) <$> [C.exp| bool { InputInt2( $(char* descPtr), $(int* intPtr), $(ImGuiInputTextFlags flags)) } |] + +inputInt3 :: (MonadIO m) => CString -> Ptr CInt -> ImGuiInputTextFlags -> m Bool +inputInt3 descPtr intPtr flags = liftIO do + (0 /=) <$> [C.exp| bool { InputInt3( $(char* descPtr), $(int* intPtr), $(ImGuiInputTextFlags flags)) } |] + +inputInt4 :: (MonadIO m) => CString -> Ptr CInt -> ImGuiInputTextFlags -> m Bool +inputInt4 descPtr intPtr flags = liftIO do + (0 /=) <$> [C.exp| bool { InputInt4( $(char* descPtr), $(int* intPtr), $(ImGuiInputTextFlags flags)) } |] + +inputDouble :: (MonadIO m) => CString -> Ptr CDouble -> CDouble -> CDouble -> CString -> ImGuiInputTextFlags -> m Bool +inputDouble descPtr doublePtr step stepFast formatPtr flags = liftIO do + (0 /=) <$> [C.exp| bool { InputDouble( $(char* descPtr), $(double* doublePtr), $(double step), $(double stepFast), $(char* formatPtr), $(ImGuiInputTextFlags flags)) } |] + +inputScalar :: (MonadIO m) => CString -> ImGuiDataType -> Ptr a -> Ptr a -> Ptr a -> CString -> ImGuiInputTextFlags -> m Bool +inputScalar labelPtr dataType dataPtr stepPtr stepMaxPtr formatPtr flags = liftIO do + (0 /=) <$> [C.exp| bool { + InputScalar( + $(char* labelPtr), + $(ImGuiDataType dataType), + $(void* dataPtr_), + $(void* stepPtr_), + $(void* stepMaxPtr_), + $(char* formatPtr), + $(ImGuiInputTextFlags flags) + ) + } |] + where + dataPtr_ = castPtr dataPtr + stepPtr_ = castPtr stepPtr + stepMaxPtr_ = castPtr stepMaxPtr + +inputScalarN :: (MonadIO m) => CString -> ImGuiDataType -> Ptr a -> CInt -> Ptr a -> Ptr a -> CString -> ImGuiInputTextFlags -> m Bool +inputScalarN labelPtr dataType dataPtr components stepPtr stepMaxPtr formatPtr flags = liftIO do + (0 /=) <$> [C.exp| bool { + InputScalarN( + $(char* labelPtr), + $(ImGuiDataType dataType), + $(void* dataPtr_), + $(int components), + $(void* stepPtr_), + $(void* stepMaxPtr_), + $(char* formatPtr), + $(ImGuiInputTextFlags flags) + ) + } |] + where + dataPtr_ = castPtr dataPtr + stepPtr_ = castPtr stepPtr + stepMaxPtr_ = castPtr stepMaxPtr -- | Wraps @ImGui::ColorPicker3()@. -colorPicker3 :: (MonadIO m) => CString -> Ptr CFloat -> m Bool -colorPicker3 descPtr refPtr = liftIO do - (0 /= ) <$> [C.exp| bool { ColorPicker3( $(char* descPtr), $(float* refPtr) ) } |] +colorEdit3 :: (MonadIO m) => CString -> Ptr CFloat -> ImGuiColorEditFlags -> m Bool +colorEdit3 descPtr refPtr flags = liftIO do + (0 /= ) <$> [C.exp| bool { ColorEdit3( $(char* descPtr), $(float* refPtr), $(ImGuiColorEditFlags flags) ) } |] +colorEdit4 :: (MonadIO m) => CString -> Ptr CFloat -> ImGuiColorEditFlags -> m Bool +colorEdit4 descPtr refPtr flags = liftIO do + (0 /= ) <$> [C.exp| bool { ColorEdit4( $(char* descPtr), $(float* refPtr), $(ImGuiColorEditFlags flags) ) } |] + +-- | Wraps @ImGui::ColorPicker3()@. +colorPicker3 :: (MonadIO m) => CString -> Ptr CFloat -> ImGuiColorEditFlags -> m Bool +colorPicker3 descPtr refPtr flags = liftIO do + (0 /= ) <$> [C.exp| bool { ColorPicker3( $(char* descPtr), $(float* refPtr), $(ImGuiColorEditFlags flags) ) } |] + +colorPicker4 :: (MonadIO m) => CString -> Ptr CFloat -> ImGuiColorEditFlags -> Ptr CFloat -> m Bool +colorPicker4 descPtr refPtr flags refColPtr = liftIO do + (0 /= ) <$> [C.exp| bool { ColorPicker4( $(char* descPtr), $(float* refPtr), $(ImGuiColorEditFlags flags), $(float* refColPtr) ) } |] + +-- | Initialize current options (generally on application startup) if you want to select a default format, picker type, etc. +-- +-- User will be able to change many settings, unless you pass the `ImGuiColorEditFlags_NoOptions` flag to your calls. +setColorEditOptions :: (MonadIO m) => ImGuiColorEditFlags -> m () +setColorEditOptions flags = liftIO do + [C.block| void { SetColorEditOptions( $(ImGuiColorEditFlags flags) ); } |] -- | Display a color square/button, hover for details, return true when pressed. -- @@ -1237,6 +1532,22 @@ treePop :: (MonadIO m) => m () treePop = liftIO do [C.exp| void { TreePop() } |] +getTreeNodeToLabelSpacing :: (MonadIO m) => m CFloat +getTreeNodeToLabelSpacing = liftIO do + [C.exp| float { GetTreeNodeToLabelSpacing() } |] + +-- | CollapsingHeader returns True when opened but do not indent nor push into the ID stack (because of the `ImGuiTreeNodeFlags_NoTreePushOnOpen` flag). +-- +-- This is basically the same as calling `treeNodeEx` with `ImGuiTreeNodeFlags_CollapsingHeader`. You can remove the `ImGuiTreeNodeFlags_NoTreePushOnOpen` flag if you want behavior closer to normal `treeNode`. +-- +-- @p_visible == NULL @ - regular collapsing header. +-- @p_visible != NULL && *p_visible == true @ - show a small close button on the corner of the header, clicking the button will set @*p_visible = false@. +-- @p_visible != NULL && *p_visible == false @ - do not show the header at all. +-- +-- Do not mistake this with the Open state of the header itself, which you can adjust with SetNextItemOpen() or ImGuiTreeNodeFlags_DefaultOpen. +collapsingHeader :: (MonadIO m) => CString -> Ptr CBool -> ImGuiTreeNodeFlags -> m Bool +collapsingHeader labelPtr visiblePtr flags = liftIO do + (0 /=) <$> [C.exp| bool { CollapsingHeader($(char* labelPtr), $(bool* visiblePtr), $(ImGuiTreeNodeFlags flags)) } |] -- | Wraps @ImGui::SetNextItemOpen()@. setNextItemOpen :: (MonadIO m) => CBool -> m () @@ -1379,20 +1690,25 @@ setTabItemClosed namePtr = liftIO do [C.exp| void { SetTabItemClosed($(char* namePtr)); } |] --- | Begin/append a tooltip window to create full-featured tooltip (with any --- kind of items). --- --- Wraps @ImGui::BeginTooltip()@ -beginTooltip :: (MonadIO m) => m () +-- | Begin/append a tooltip window to create full-featured tooltip (with any kind of items). +beginTooltip :: (MonadIO m) => m Bool beginTooltip = liftIO do - [C.exp| void { BeginTooltip() } |] + (0 /=) <$> [C.exp| bool { BeginTooltip() } |] +-- | A shortcut for the @if (IsItemHovered(ImGuiHoveredFlags_ForTooltip) && BeginTooltip())@ idiom. +beginItemTooltip :: (MonadIO m) => m Bool +beginItemTooltip = liftIO do + (0 /=) <$> [C.exp| bool { BeginItemTooltip() } |] --- | Wraps @ImGui::EndTooltip()@ +-- | Only call if 'beginTooltip'/'beginItemTooltip' returns True! endTooltip :: (MonadIO m) => m () endTooltip = liftIO do [C.exp| void { EndTooltip() } |] +-- | Set a text-only tooltip if preceding item was hovered. Overrides any previous call to 'setTooltip'. +setItemTooltip :: (MonadIO m) => CString -> m () +setItemTooltip textPtr = liftIO do + [C.exp| void { SetItemTooltip("%s", $(char* textPtr)); } |] -- | Returns 'True' if the popup is open, and you can start outputting to it. -- @@ -1481,6 +1797,86 @@ isItemHovered :: (MonadIO m) => m Bool isItemHovered = liftIO do (0 /=) <$> [C.exp| bool { IsItemHovered() } |] +-- | Is the last item hovered? (and usable, aka not blocked by a popup, etc.). +isItemActive :: (MonadIO m) => m Bool +isItemActive = liftIO do + (0 /=) <$> [C.exp| bool { IsItemActive() } |] + +isItemFocused :: (MonadIO m) => m Bool +isItemFocused = liftIO do + (0 /=) <$> [C.exp| bool { IsItemFocused() } |] + +isItemClicked :: (MonadIO m) => ImGuiMouseButton -> m Bool +isItemClicked mouseButton = liftIO do + (0 /=) <$> [C.exp| bool { IsItemClicked( $(ImGuiMouseButton mouseButton) ) } |] + +isItemVisible :: (MonadIO m) => m Bool +isItemVisible = liftIO do + (0 /=) <$> [C.exp| bool { IsItemVisible() } |] + +isItemEdited :: (MonadIO m) => m Bool +isItemEdited = liftIO do + (0 /=) <$> [C.exp| bool { IsItemEdited() } |] + +isItemActivated :: (MonadIO m) => m Bool +isItemActivated = liftIO do + (0 /=) <$> [C.exp| bool { IsItemActivated() } |] + +isItemDeactivated :: (MonadIO m) => m Bool +isItemDeactivated = liftIO do + (0 /=) <$> [C.exp| bool { IsItemDeactivated() } |] + +isItemDeactivatedAfterEdit :: (MonadIO m) => m Bool +isItemDeactivatedAfterEdit = liftIO do + (0 /=) <$> [C.exp| bool { IsItemDeactivatedAfterEdit() } |] + +isItemToggledOpen :: (MonadIO m) => m Bool +isItemToggledOpen = liftIO do + (0 /=) <$> [C.exp| bool { IsItemToggledOpen() } |] + +isAnyItemHovered :: (MonadIO m) => m Bool +isAnyItemHovered = liftIO do + (0 /=) <$> [C.exp| bool { IsAnyItemHovered() } |] + +-- | Is the last item hovered? (and usable, aka not blocked by a popup, etc.). +isAnyItemActive :: (MonadIO m) => m Bool +isAnyItemActive = liftIO do + (0 /=) <$> [C.exp| bool { IsAnyItemActive() } |] + +isAnyItemFocused :: (MonadIO m) => m Bool +isAnyItemFocused = liftIO do + (0 /=) <$> [C.exp| bool { IsAnyItemFocused() } |] + +getItemID :: (MonadIO m) => m ImGuiID +getItemID = liftIO do + [C.exp| ImGuiID { GetItemID() } |] + +getItemRectMin :: (MonadIO m) => m ImVec2 +getItemRectMin = liftIO do + C.withPtr_ \ptr -> + [C.block| + void { + *$(ImVec2 * ptr) = GetItemRectMin(); + } + |] + +getItemRectMax :: (MonadIO m) => m ImVec2 +getItemRectMax = liftIO do + C.withPtr_ \ptr -> + [C.block| + void { + *$(ImVec2 * ptr) = GetItemRectMin(); + } + |] + +getItemRectSize :: (MonadIO m) => m ImVec2 +getItemRectSize = liftIO do + C.withPtr_ \ptr -> + [C.block| + void { + *$(ImVec2 * ptr) = GetItemRectSize(); + } + |] -- | Get draw list associated to the current window. getWindowDrawList :: (MonadIO m) => m DrawList @@ -1567,7 +1963,6 @@ setNextWindowSizeConstraints :: (MonadIO m) => Ptr ImVec2 -> Ptr ImVec2 -> m () setNextWindowSizeConstraints sizeMinPtr sizeMaxPtr = liftIO do [C.exp| void { SetNextWindowSizeConstraints(*$(ImVec2* sizeMinPtr), *$(ImVec2* sizeMaxPtr)) } |] - -- | Set next window collapsed state. call before `begin` -- -- Wraps @ImGui::SetNextWindowCollapsed()@ @@ -1575,6 +1970,15 @@ setNextWindowCollapsed :: (MonadIO m) => CBool -> ImGuiCond -> m () setNextWindowCollapsed b cond = liftIO do [C.exp| void { SetNextWindowCollapsed($(bool b), $(ImGuiCond cond)) } |] +-- | Set next window to be focused / top-most. call before `begin` +setNextWindowFocus :: (MonadIO m) => m () +setNextWindowFocus = liftIO do + [C.exp| void { SetNextWindowFocus() } |] + +-- | Set next window scrolling value (use < 0.0f to not affect a given axis). +setNextWindowScroll :: (MonadIO m) => Ptr ImVec2 -> m () +setNextWindowScroll posPtr = liftIO do + [C.exp| void { SetNextWindowScroll(*$(ImVec2* posPtr)) } |] -- | Set next window background color alpha. helper to easily override the Alpha component of `ImGuiCol_WindowBg`, `ChildBg`, `PopupBg`. you may also use `ImGuiWindowFlags_NoBackground`. -- @@ -1583,6 +1987,47 @@ setNextWindowBgAlpha :: (MonadIO m) => CFloat -> m () setNextWindowBgAlpha alpha = liftIO do [C.exp| void { SetNextWindowBgAlpha($(float alpha)) } |] +-- | Retrieve available space from a given point. +-- +-- @== GetContentRegionMax() - GetCursorPos()@ +getContentRegionAvail :: (MonadIO m) => m ImVec2 +getContentRegionAvail = liftIO do + C.withPtr_ \ptr -> + [C.block| + void { + *$(ImVec2 * ptr) = GetContentRegionAvail(); + } + |] + +-- | Current content boundaries (typically window boundaries including scrolling, or current column boundaries), in window coordinates. +getContentRegionMax :: (MonadIO m) => m ImVec2 +getContentRegionMax = liftIO do + C.withPtr_ \ptr -> + [C.block| + void { + *$(ImVec2 * ptr) = GetContentRegionMax(); + } + |] + +-- | Content boundaries min for the full window (roughly @(0,0) - Scroll@), in window coordinates. +getWindowContentRegionMin :: (MonadIO m) => m ImVec2 +getWindowContentRegionMin = liftIO do + C.withPtr_ \ptr -> + [C.block| + void { + *$(ImVec2 * ptr) = GetWindowContentRegionMin(); + } + |] + +-- | Content boundaries max for the full window (roughly @(0,0) + Size - Scroll@) where Size can be overridden with SetNextWindowContentSize(), in window coordinates. +getWindowContentRegionMax :: (MonadIO m) => m ImVec2 +getWindowContentRegionMax = liftIO do + C.withPtr_ \ptr -> + [C.block| + void { + *$(ImVec2 * ptr) = GetWindowContentRegionMax(); + } + |] -- | Begin a block that may be disabled. This disables all user interactions -- and dims item visuals. @@ -1606,6 +2051,26 @@ endDisabled :: (MonadIO m) => m () endDisabled = liftIO do [C.exp| void { EndDisabled() } |] +-- | Make last item the default focused item of a window. +setItemDefaultFocus :: (MonadIO m) => m () +setItemDefaultFocus = liftIO do + [C.block| void { SetItemDefaultFocus(); } |] + +-- | Focus keyboard on the next widget. +-- +-- Use positive 'offset' to access sub components of a multiple component widget. +-- Use -1 to access previous widget. +setKeyboardFocusHere :: (MonadIO m) => CInt -> m () +setKeyboardFocusHere offset = liftIO do + [C.block| void { SetKeyboardFocusHere( $(int offset)); } |] + +-- | Allow next item to be overlapped by a subsequent item. +-- +-- Useful with invisible buttons, selectable, treenode covering an area where subsequent items may need to be added. +-- Note that both `selectable` and `treeNode` have dedicated flags doing this. +setNextItemAllowOverlap :: (MonadIO m) => m () +setNextItemAllowOverlap = liftIO do + [C.block| void { SetNextItemAllowOverlap(); } |] -- | undo a sameLine or force a new line when in an horizontal-layout context. -- @@ -1666,6 +2131,23 @@ popItemWidth :: (MonadIO m) => m () popItemWidth = liftIO do [C.exp| void { PopItemWidth() } |] +-- | Width of item given pushed settings and current cursor position. NOT necessarily the width of last item unlike most Item functions. +calcItemWidth :: MonadIO m => m Float +calcItemWidth = liftIO do + realToFrac <$> [C.exp| float { CalcItemWidth() } |] + +-- | Push word-wrapping position for Text commands. +-- +-- Negative: no wrapping. +-- Zero: wrap to end of window (or column). +-- Positive: wrap at 'wrap_pos_x' position in window local space. +pushTextWrapPos :: (MonadIO m) => CFloat -> m () +pushTextWrapPos wrapLocalPosX = liftIO do + [C.exp| void { PushTextWrapPos($(float wrapLocalPosX)) } |] + +popTextWrapPos :: (MonadIO m) => m () +popTextWrapPos = liftIO do + [C.exp| void { PopTextWrapPos() } |] -- | lock horizontal starting position -- @@ -1690,6 +2172,29 @@ alignTextToFramePadding :: (MonadIO m) => m () alignTextToFramePadding = liftIO do [C.exp| void { AlignTextToFramePadding() } |] +-- | ~ @FontSize@ +getTextLineHeight :: (MonadIO m) => m CFloat +getTextLineHeight = liftIO do + [C.exp| float { GetTextLineHeight() } |] + +-- | Distance in pixels between 2 consecutive lines of text. +-- +-- ~ @FontSize + style.ItemSpacing.y@ () +getTextLineHeightWithSpacing :: (MonadIO m) => m CFloat +getTextLineHeightWithSpacing = liftIO do + [C.exp| float { GetTextLineHeightWithSpacing() } |] + +-- | ~ @FontSize + style.FramePadding.y * 2@ +getFrameHeight :: (MonadIO m) => m CFloat +getFrameHeight = liftIO do + [C.exp| float { GetFrameHeight() } |] + +-- | Distance in pixels between 2 consecutive lines of framed widgets +-- +-- ~ @FontSize + style.FramePadding.y * 2 + style.ItemSpacing.y@ +getFrameHeightWithSpacing :: (MonadIO m) => m CFloat +getFrameHeightWithSpacing = liftIO do + [C.exp| float { GetFrameHeightWithSpacing() } |] -- | Set cursor position in window-local coordinates -- @@ -1698,6 +2203,14 @@ setCursorPos :: (MonadIO m) => Ptr ImVec2 -> m () setCursorPos posPtr = liftIO do [C.exp| void { SetCursorPos(*$(ImVec2* posPtr)) } |] +setCursorPosX :: (MonadIO m) => CFloat -> m () +setCursorPosX localX = liftIO do + [C.exp| void { SetCursorPosX($(float localX)) } |] + +setCursorPosY :: (MonadIO m) => CFloat -> m () +setCursorPosY localY = liftIO do + [C.exp| void { SetCursorPosY($(float localY)) } |] + -- | Get cursor position in window-local coordinates. -- -- Useful to overlap draw using 'setCursorPos'. @@ -1712,6 +2225,14 @@ getCursorPos = liftIO do } |] +getCursorPosX :: (MonadIO m) => m CFloat +getCursorPosX = liftIO do + [C.exp| float { GetCursorPosX() } |] + +getCursorPosY :: (MonadIO m) => m CFloat +getCursorPosY = liftIO do + [C.exp| float { GetCursorPosY() } |] + -- | Cursor position in absolute coordinates. -- -- Useful to work with 'DrawList' API. @@ -1727,6 +2248,21 @@ getCursorScreenPos = liftIO do } |] +-- | Initial cursor position, in window coordinates. +getCursorStartPos :: (MonadIO m) => m ImVec2 +getCursorStartPos = liftIO do + C.withPtr_ \ptr -> + [C.block| + void { + *$(ImVec2 * ptr) = GetCursorStartPos(); + } + |] + +-- | Set cursor position in absolute coordinates. +setCursorScreenPos :: (MonadIO m) => Ptr ImVec2 -> m () +setCursorScreenPos posPtr = liftIO do + [C.exp| void { SetCursorScreenPos(*$(ImVec2* posPtr)) } |] + -- | Modify a style color by pushing to the shared stack. always use this if you modify the style after `newFrame` -- @@ -1759,6 +2295,14 @@ popStyleVar :: (MonadIO m) => CInt -> m () popStyleVar n = liftIO do [C.exp| void { PopStyleVar($(int n)) } |] +-- | Allow/disable focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets. +pushTabStop :: (MonadIO m) => CBool -> m () +pushTabStop b = liftIO do + [C.exp| void { PushTabStop($(bool b)) } |] + +popTabStop :: (MonadIO m) => m () +popTabStop = liftIO do + [C.exp| void { PopTabStop() } |] -- | Push integer into the ID stack (will hash int). -- @@ -1796,11 +2340,56 @@ popID :: (MonadIO m) => m () popID = liftIO do [C.exp| void { PopID() } |] +getMousePos :: (MonadIO m) => m ImVec2 +getMousePos = liftIO do + C.withPtr_ \ptr -> + [C.block| + void { + *$(ImVec2 * ptr) = GetMousePos(); + } + |] + +-- | Retrieve mouse position at the time of opening popup we have 'beginPopup' into (helper to avoid user backing that value themselves). +getMousePosOnOpeningCurrentPopup :: (MonadIO m) => m ImVec2 +getMousePosOnOpeningCurrentPopup = liftIO do + C.withPtr_ \ptr -> + [C.block| + void { + *$(ImVec2 * ptr) = GetMousePosOnOpeningCurrentPopup(); + } + |] + +isMouseDragging :: MonadIO m => ImGuiMouseButton -> CFloat -> m Bool +isMouseDragging btn lockThreshold = liftIO do + (0 /=) <$> [C.exp| bool { IsMouseDragging( $(ImGuiMouseButton btn), $(float lockThreshold) ) } |] + +getMouseDragDelta :: (MonadIO m) => ImGuiMouseButton -> CFloat -> m ImVec2 +getMouseDragDelta btn lockThreshold = liftIO do + C.withPtr_ \ptr -> + [C.block| + void { + *$(ImVec2 * ptr) = GetMouseDragDelta( $(ImGuiMouseButton btn), $(float lockThreshold) ); + } + |] + +resetMouseDragDelta :: MonadIO m => ImGuiMouseButton -> m () +resetMouseDragDelta btn = liftIO do + [C.block| void { ResetMouseDragDelta( $(ImGuiMouseButton btn) ); } |] wantCaptureMouse :: MonadIO m => m Bool wantCaptureMouse = liftIO do (0 /=) <$> [C.exp| bool { GetIO().WantCaptureMouse } |] +type ImGuiKeyChord = Int + +shortcut :: MonadIO m => ImGuiKeyChord -> ImGuiInputFlags -> m Bool +shortcut keyChord flags = liftIO do + (0 /=) <$> [C.exp| bool { Shortcut( $(ImGuiKeyChord keyChord), $(ImGuiInputFlags flags) ) } |] + +setNextItemShortcut :: MonadIO m => ImGuiKeyChord -> ImGuiInputFlags -> m () +setNextItemShortcut keyChord flags = liftIO do + [C.block| void { SetNextItemShortcut( $(ImGuiKeyChord keyChord), $(ImGuiInputFlags flags) ); } |] + wantCaptureKeyboard :: MonadIO m => m Bool wantCaptureKeyboard = liftIO do (0 /=) <$> [C.exp| bool { GetIO().WantCaptureKeyboard } |] @@ -1811,6 +2400,34 @@ framerate :: MonadIO m => m Float framerate = liftIO do realToFrac <$> [C.exp| float { GetIO().Framerate } |] +-- | Get global imgui time. +-- +-- Incremented by io.DeltaTime every frame. +getTime :: MonadIO m => m Double +getTime = liftIO do + realToFrac <$> [C.exp| double { GetTime() } |] + +-- | Get global imgui frame count. +-- +-- Incremented by 1 every frame. +getFrameCount :: MonadIO m => m Int +getFrameCount = liftIO do + fromIntegral <$> [C.exp| int { GetFrameCount() } |] + +calcTextSize :: MonadIO m => CString -> CString -> CBool -> CFloat -> m ImVec2 +calcTextSize textPtr textEndPtr hideAfterDoubleHash wrapWidth = liftIO do + C.withPtr_ \ptr -> + [C.block| + void { + *$(ImVec2 * ptr) = CalcTextSize( + $(char* textPtr), + $(char* textEndPtr), + $(bool hideAfterDoubleHash), + $(float wrapWidth) + ); + } + |] + -- | This draw list will be the first rendering one. -- -- Useful to quickly draw shapes/text behind dear imgui contents. diff --git a/src/DearImGui/Raw/Context.hs b/src/DearImGui/Raw/Context.hs index eb6c5cd..1df423d 100644 --- a/src/DearImGui/Raw/Context.hs +++ b/src/DearImGui/Raw/Context.hs @@ -43,5 +43,7 @@ imguiContext = mempty , ( TypeName "ImFontGlyphRangesBuilder", [t| ImFontGlyphRangesBuilder |] ) , ( TypeName "ImGuiListClipper", [t| ImGuiListClipper |] ) , ( TypeName "ImGuiTableSortSpecs", [t| ImGuiTableSortSpecs |] ) + , ( TypeName "ImGuiPayload", [t| ImGuiPayload |] ) + , ( TypeName "ImGuiKeyChord", [t| Int |] ) ] } diff --git a/src/DearImGui/Raw/DragDrop.hs b/src/DearImGui/Raw/DragDrop.hs new file mode 100644 index 0000000..d218d36 --- /dev/null +++ b/src/DearImGui/Raw/DragDrop.hs @@ -0,0 +1,81 @@ +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE DuplicateRecordFields #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE PatternSynonyms #-} +{-# LANGUAGE QuasiQuotes #-} +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE ViewPatterns #-} + +module DearImGui.Raw.DragDrop + ( Payload(..) + , beginSource + , setPayload + , endSource + , beginTarget + , acceptPayload + , endTarget + , getPayload + ) + where + +-- base +import Control.Monad.IO.Class + ( MonadIO, liftIO ) +import Foreign + ( Ptr, castPtr ) +import Foreign.C + +-- dear-imgui +import DearImGui.Raw.Context + ( imguiContext ) +import DearImGui.Enums +import DearImGui.Structs + +-- inline-c +import qualified Language.C.Inline as C + +-- inline-c-cpp +import qualified Language.C.Inline.Cpp as Cpp + +C.context (Cpp.cppCtx <> C.bsCtx <> imguiContext) +C.include "imgui.h" +Cpp.using "namespace ImGui" + +-- | Font configuration data handle +-- +-- Wraps @ImGuiPayload*@. +newtype Payload = Payload (Ptr ImGuiPayload) + + +beginSource :: MonadIO m => ImGuiDragDropFlags -> m Bool +beginSource flags = liftIO do + (0 /=) <$> [C.exp| bool { BeginDragDropSource( $(ImGuiDragDropFlags flags) ) } |] + +setPayload :: MonadIO m => CString -> Ptr a -> CSize -> ImGuiCond -> m Bool +setPayload typePtr dataPtr sz cond = liftIO do + (0 /=) <$> [C.exp| bool { SetDragDropPayload( $(char* typePtr), $(void* dataPtr'), $(size_t sz), $(ImGuiCond cond) ) } |] + where + dataPtr' = castPtr dataPtr + +endSource :: MonadIO m => m () +endSource = liftIO do + [C.block| void { EndDragDropSource( ); } |] + +beginTarget :: MonadIO m => m () +beginTarget = liftIO do + [C.block| void { BeginDragDropTarget(); } |] + +acceptPayload :: MonadIO m => CString -> ImGuiDragDropFlags -> m Payload +acceptPayload typePtr flags = liftIO do + Payload <$> [C.exp| const ImGuiPayload* { AcceptDragDropPayload( $(char* typePtr), $(ImGuiDragDropFlags flags) ) } |] + +endTarget :: MonadIO m => m () +endTarget = liftIO do + [C.block| void { EndDragDropTarget(); } |] + +getPayload :: MonadIO m => m Payload +getPayload = liftIO do + Payload <$> [C.exp| const ImGuiPayload* { GetDragDropPayload() } |] diff --git a/src/DearImGui/Structs.hs b/src/DearImGui/Structs.hs index 15a086b..6b92f5e 100644 --- a/src/DearImGui/Structs.hs +++ b/src/DearImGui/Structs.hs @@ -104,6 +104,9 @@ data ImDrawList -- | 'DearImGui.Raw.ListClipper.ListClipper' pointer tag. data ImGuiListClipper +-- | 'DearImGui.Raw.DragDrop.Payload' pointer tag. +data ImGuiPayload + -- | A unique ID used by widgets (typically the result of hashing a stack of string) -- unsigned Integer (same as ImU32) type ImGuiID = ImU32