@ -53,6 +53,7 @@ CODE
- ImGuiTextFilter
- ImGuiTextBuffer
- ImGuiListClipper
- Render Helpers
- Main Code ( most of the code ! lots of stuff , needs tidying up )
- Tooltips
- Popups
@ -2075,6 +2076,226 @@ bool ImGuiListClipper::Step()
return false ;
}
//-----------------------------------------------------------------------------
// RENDER HELPERS
// Those [Internal] functions are a terrible mess - their signature and behavior will change.
// Also see imgui_draw.cpp for some more which have been reworked to not rely on ImGui:: state.
//-----------------------------------------------------------------------------
const char * ImGui : : FindRenderedTextEnd ( const char * text , const char * text_end )
{
const char * text_display_end = text ;
if ( ! text_end )
text_end = ( const char * ) - 1 ;
while ( text_display_end < text_end & & * text_display_end ! = ' \0 ' & & ( text_display_end [ 0 ] ! = ' # ' | | text_display_end [ 1 ] ! = ' # ' ) )
text_display_end + + ;
return text_display_end ;
}
// Internal ImGui functions to render text
// RenderText***() functions calls ImDrawList::AddText() calls ImBitmapFont::RenderText()
void ImGui : : RenderText ( ImVec2 pos , const char * text , const char * text_end , bool hide_text_after_hash )
{
ImGuiContext & g = * GImGui ;
ImGuiWindow * window = g . CurrentWindow ;
// Hide anything after a '##' string
const char * text_display_end ;
if ( hide_text_after_hash )
{
text_display_end = FindRenderedTextEnd ( text , text_end ) ;
}
else
{
if ( ! text_end )
text_end = text + strlen ( text ) ; // FIXME-OPT
text_display_end = text_end ;
}
if ( text ! = text_display_end )
{
window - > DrawList - > AddText ( g . Font , g . FontSize , pos , GetColorU32 ( ImGuiCol_Text ) , text , text_display_end ) ;
if ( g . LogEnabled )
LogRenderedText ( & pos , text , text_display_end ) ;
}
}
void ImGui : : RenderTextWrapped ( ImVec2 pos , const char * text , const char * text_end , float wrap_width )
{
ImGuiContext & g = * GImGui ;
ImGuiWindow * window = g . CurrentWindow ;
if ( ! text_end )
text_end = text + strlen ( text ) ; // FIXME-OPT
if ( text ! = text_end )
{
window - > DrawList - > AddText ( g . Font , g . FontSize , pos , GetColorU32 ( ImGuiCol_Text ) , text , text_end , wrap_width ) ;
if ( g . LogEnabled )
LogRenderedText ( & pos , text , text_end ) ;
}
}
// Default clip_rect uses (pos_min,pos_max)
// Handle clipping on CPU immediately (vs typically let the GPU clip the triangles that are overlapping the clipping rectangle edges)
void ImGui : : RenderTextClipped ( const ImVec2 & pos_min , const ImVec2 & pos_max , const char * text , const char * text_end , const ImVec2 * text_size_if_known , const ImVec2 & align , const ImRect * clip_rect )
{
// Hide anything after a '##' string
const char * text_display_end = FindRenderedTextEnd ( text , text_end ) ;
const int text_len = ( int ) ( text_display_end - text ) ;
if ( text_len = = 0 )
return ;
ImGuiContext & g = * GImGui ;
ImGuiWindow * window = g . CurrentWindow ;
// Perform CPU side clipping for single clipped element to avoid using scissor state
ImVec2 pos = pos_min ;
const ImVec2 text_size = text_size_if_known ? * text_size_if_known : CalcTextSize ( text , text_display_end , false , 0.0f ) ;
const ImVec2 * clip_min = clip_rect ? & clip_rect - > Min : & pos_min ;
const ImVec2 * clip_max = clip_rect ? & clip_rect - > Max : & pos_max ;
bool need_clipping = ( pos . x + text_size . x > = clip_max - > x ) | | ( pos . y + text_size . y > = clip_max - > y ) ;
if ( clip_rect ) // If we had no explicit clipping rectangle then pos==clip_min
need_clipping | = ( pos . x < clip_min - > x ) | | ( pos . y < clip_min - > y ) ;
// Align whole block. We should defer that to the better rendering function when we'll have support for individual line alignment.
if ( align . x > 0.0f ) pos . x = ImMax ( pos . x , pos . x + ( pos_max . x - pos . x - text_size . x ) * align . x ) ;
if ( align . y > 0.0f ) pos . y = ImMax ( pos . y , pos . y + ( pos_max . y - pos . y - text_size . y ) * align . y ) ;
// Render
if ( need_clipping )
{
ImVec4 fine_clip_rect ( clip_min - > x , clip_min - > y , clip_max - > x , clip_max - > y ) ;
window - > DrawList - > AddText ( g . Font , g . FontSize , pos , GetColorU32 ( ImGuiCol_Text ) , text , text_display_end , 0.0f , & fine_clip_rect ) ;
}
else
{
window - > DrawList - > AddText ( g . Font , g . FontSize , pos , GetColorU32 ( ImGuiCol_Text ) , text , text_display_end , 0.0f , NULL ) ;
}
if ( g . LogEnabled )
LogRenderedText ( & pos , text , text_display_end ) ;
}
// Render a rectangle shaped with optional rounding and borders
void ImGui : : RenderFrame ( ImVec2 p_min , ImVec2 p_max , ImU32 fill_col , bool border , float rounding )
{
ImGuiContext & g = * GImGui ;
ImGuiWindow * window = g . CurrentWindow ;
window - > DrawList - > AddRectFilled ( p_min , p_max , fill_col , rounding ) ;
const float border_size = g . Style . FrameBorderSize ;
if ( border & & border_size > 0.0f )
{
window - > DrawList - > AddRect ( p_min + ImVec2 ( 1 , 1 ) , p_max + ImVec2 ( 1 , 1 ) , GetColorU32 ( ImGuiCol_BorderShadow ) , rounding , ImDrawCornerFlags_All , border_size ) ;
window - > DrawList - > AddRect ( p_min , p_max , GetColorU32 ( ImGuiCol_Border ) , rounding , ImDrawCornerFlags_All , border_size ) ;
}
}
void ImGui : : RenderFrameBorder ( ImVec2 p_min , ImVec2 p_max , float rounding )
{
ImGuiContext & g = * GImGui ;
ImGuiWindow * window = g . CurrentWindow ;
const float border_size = g . Style . FrameBorderSize ;
if ( border_size > 0.0f )
{
window - > DrawList - > AddRect ( p_min + ImVec2 ( 1 , 1 ) , p_max + ImVec2 ( 1 , 1 ) , GetColorU32 ( ImGuiCol_BorderShadow ) , rounding , ImDrawCornerFlags_All , border_size ) ;
window - > DrawList - > AddRect ( p_min , p_max , GetColorU32 ( ImGuiCol_Border ) , rounding , ImDrawCornerFlags_All , border_size ) ;
}
}
// Render an arrow aimed to be aligned with text (p_min is a position in the same space text would be positioned). To e.g. denote expanded/collapsed state
void ImGui : : RenderArrow ( ImVec2 p_min , ImGuiDir dir , float scale )
{
ImGuiContext & g = * GImGui ;
const float h = g . FontSize * 1.00f ;
float r = h * 0.40f * scale ;
ImVec2 center = p_min + ImVec2 ( h * 0.50f , h * 0.50f * scale ) ;
ImVec2 a , b , c ;
switch ( dir )
{
case ImGuiDir_Up :
case ImGuiDir_Down :
if ( dir = = ImGuiDir_Up ) r = - r ;
a = ImVec2 ( + 0.000f , + 0.750f ) * r ;
b = ImVec2 ( - 0.866f , - 0.750f ) * r ;
c = ImVec2 ( + 0.866f , - 0.750f ) * r ;
break ;
case ImGuiDir_Left :
case ImGuiDir_Right :
if ( dir = = ImGuiDir_Left ) r = - r ;
a = ImVec2 ( + 0.750f , + 0.000f ) * r ;
b = ImVec2 ( - 0.750f , + 0.866f ) * r ;
c = ImVec2 ( - 0.750f , - 0.866f ) * r ;
break ;
case ImGuiDir_None :
case ImGuiDir_COUNT :
IM_ASSERT ( 0 ) ;
break ;
}
g . CurrentWindow - > DrawList - > AddTriangleFilled ( center + a , center + b , center + c , GetColorU32 ( ImGuiCol_Text ) ) ;
}
void ImGui : : RenderBullet ( ImVec2 pos )
{
ImGuiContext & g = * GImGui ;
ImGuiWindow * window = g . CurrentWindow ;
window - > DrawList - > AddCircleFilled ( pos , g . FontSize * 0.20f , GetColorU32 ( ImGuiCol_Text ) , 8 ) ;
}
void ImGui : : RenderCheckMark ( ImVec2 pos , ImU32 col , float sz )
{
ImGuiContext & g = * GImGui ;
ImGuiWindow * window = g . CurrentWindow ;
float thickness = ImMax ( sz / 5.0f , 1.0f ) ;
sz - = thickness * 0.5f ;
pos + = ImVec2 ( thickness * 0.25f , thickness * 0.25f ) ;
float third = sz / 3.0f ;
float bx = pos . x + third ;
float by = pos . y + sz - third * 0.5f ;
window - > DrawList - > PathLineTo ( ImVec2 ( bx - third , by - third ) ) ;
window - > DrawList - > PathLineTo ( ImVec2 ( bx , by ) ) ;
window - > DrawList - > PathLineTo ( ImVec2 ( bx + third * 2 , by - third * 2 ) ) ;
window - > DrawList - > PathStroke ( col , false , thickness ) ;
}
void ImGui : : RenderNavHighlight ( const ImRect & bb , ImGuiID id , ImGuiNavHighlightFlags flags )
{
ImGuiContext & g = * GImGui ;
if ( id ! = g . NavId )
return ;
if ( g . NavDisableHighlight & & ! ( flags & ImGuiNavHighlightFlags_AlwaysDraw ) )
return ;
ImGuiWindow * window = ImGui : : GetCurrentWindow ( ) ;
if ( window - > DC . NavHideHighlightOneFrame )
return ;
float rounding = ( flags & ImGuiNavHighlightFlags_NoRounding ) ? 0.0f : g . Style . FrameRounding ;
ImRect display_rect = bb ;
display_rect . ClipWith ( window - > ClipRect ) ;
if ( flags & ImGuiNavHighlightFlags_TypeDefault )
{
const float THICKNESS = 2.0f ;
const float DISTANCE = 3.0f + THICKNESS * 0.5f ;
display_rect . Expand ( ImVec2 ( DISTANCE , DISTANCE ) ) ;
bool fully_visible = window - > ClipRect . Contains ( display_rect ) ;
if ( ! fully_visible )
window - > DrawList - > PushClipRect ( display_rect . Min , display_rect . Max ) ;
window - > DrawList - > AddRect ( display_rect . Min + ImVec2 ( THICKNESS * 0.5f , THICKNESS * 0.5f ) , display_rect . Max - ImVec2 ( THICKNESS * 0.5f , THICKNESS * 0.5f ) , GetColorU32 ( ImGuiCol_NavHighlight ) , rounding , ImDrawCornerFlags_All , THICKNESS ) ;
if ( ! fully_visible )
window - > DrawList - > PopClipRect ( ) ;
}
if ( flags & ImGuiNavHighlightFlags_TypeThin )
{
window - > DrawList - > AddRect ( display_rect . Min , display_rect . Max , GetColorU32 ( ImGuiCol_NavHighlight ) , rounding , ~ 0 , 1.0f ) ;
}
}
//-----------------------------------------------------------------------------
// MAIN CODE
// (this category is still too large and badly ordered, needs some tidying up)
@ -3469,320 +3690,106 @@ void ImGui::EndFrame()
{
ImGuiWindow * window = g . Windows [ i ] ;
if ( window = = modal )
break ;
if ( window = = g . HoveredWindow )
hovered_window_above_modal = true ;
}
ClosePopupsOverWindow ( hovered_window_above_modal ? g . HoveredWindow : modal ) ;
}
}
}
// Update user-facing viewport list
g . PlatformIO . MainViewport = g . Viewports [ 0 ] ;
g . PlatformIO . Viewports . resize ( 0 ) ;
for ( int i = 0 ; i < g . Viewports . Size ; i + + )
{
ImGuiViewportP * viewport = g . Viewports [ i ] ;
if ( viewport - > LastFrameActive < g . FrameCount | | viewport - > Size . x < = 0.0f | | viewport - > Size . y < = 0.0f )
continue ;
if ( viewport - > Window & & ! IsWindowActiveAndVisible ( viewport - > Window ) )
continue ;
if ( i > 0 )
IM_ASSERT ( viewport - > Window ! = NULL ) ;
g . PlatformIO . Viewports . push_back ( viewport ) ;
}
// Sort the window list so that all child windows are after their parent
// We cannot do that on FocusWindow() because childs may not exist yet
g . WindowsSortBuffer . resize ( 0 ) ;
g . WindowsSortBuffer . reserve ( g . Windows . Size ) ;
for ( int i = 0 ; i ! = g . Windows . Size ; i + + )
{
ImGuiWindow * window = g . Windows [ i ] ;
if ( window - > Active & & ( window - > Flags & ImGuiWindowFlags_ChildWindow ) ) // if a child is active its parent will add it
continue ;
AddWindowToSortedBuffer ( & g . WindowsSortBuffer , window ) ;
}
IM_ASSERT ( g . Windows . Size = = g . WindowsSortBuffer . Size ) ; // we done something wrong
g . Windows . swap ( g . WindowsSortBuffer ) ;
g . IO . MetricsActiveWindows = g . WindowsActiveCount ;
// Unlock font atlas
g . IO . Fonts - > Locked = false ;
// Clear Input data for next frame
g . IO . MouseWheel = g . IO . MouseWheelH = 0.0f ;
memset ( g . IO . InputCharacters , 0 , sizeof ( g . IO . InputCharacters ) ) ;
memset ( g . IO . NavInputs , 0 , sizeof ( g . IO . NavInputs ) ) ;
g . FrameScopeActive = false ;
g . FrameCountEnded = g . FrameCount ;
}
void ImGui : : Render ( )
{
ImGuiContext & g = * GImGui ;
IM_ASSERT ( g . Initialized ) ;
if ( g . FrameCountEnded ! = g . FrameCount )
ImGui : : EndFrame ( ) ;
g . FrameCountRendered = g . FrameCount ;
// Gather ImDrawList to render (for each active window)
g . IO . MetricsRenderVertices = g . IO . MetricsRenderIndices = g . IO . MetricsRenderWindows = 0 ;
for ( int n = 0 ; n ! = g . Viewports . Size ; n + + )
g . Viewports [ n ] - > DrawDataBuilder . Clear ( ) ;
ImGuiWindow * windows_to_render_front_most [ 2 ] ;
windows_to_render_front_most [ 0 ] = ( g . NavWindowingTarget & & ! ( g . NavWindowingTarget - > Flags & ImGuiWindowFlags_NoBringToFrontOnFocus ) ) ? g . NavWindowingTarget - > RootWindow : NULL ;
windows_to_render_front_most [ 1 ] = g . NavWindowingTarget ? g . NavWindowingList : NULL ;
for ( int n = 0 ; n ! = g . Windows . Size ; n + + )
{
ImGuiWindow * window = g . Windows [ n ] ;
if ( IsWindowActiveAndVisible ( window ) & & ( window - > Flags & ImGuiWindowFlags_ChildWindow ) = = 0 & & window ! = windows_to_render_front_most [ 0 ] & & window ! = windows_to_render_front_most [ 1 ] )
AddRootWindowToDrawData ( window ) ;
}
for ( int n = 0 ; n < IM_ARRAYSIZE ( windows_to_render_front_most ) ; n + + )
if ( windows_to_render_front_most [ n ] & & IsWindowActiveAndVisible ( windows_to_render_front_most [ n ] ) ) // NavWindowingTarget is always temporarily displayed as the front-most window
AddRootWindowToDrawData ( windows_to_render_front_most [ n ] ) ;
// Draw software mouse cursor if requested
if ( g . IO . MouseDrawCursor )
RenderMouseCursor ( g . IO . MousePos , g . Style . MouseCursorScale , g . MouseCursor ) ;
// Setup ImDrawData structures for end-user
g . IO . MetricsRenderVertices = g . IO . MetricsRenderIndices = 0 ;
for ( int n = 0 ; n < g . Viewports . Size ; n + + )
{
ImGuiViewportP * viewport = g . Viewports [ n ] ;
viewport - > DrawDataBuilder . FlattenIntoSingleLayer ( ) ;
if ( viewport - > OverlayDrawList ! = NULL )
AddDrawListToDrawData ( & viewport - > DrawDataBuilder . Layers [ 0 ] , GetOverlayDrawList ( viewport ) ) ;
SetupViewportDrawData ( viewport , & viewport - > DrawDataBuilder . Layers [ 0 ] ) ;
g . IO . MetricsRenderVertices + = viewport - > DrawData - > TotalVtxCount ;
g . IO . MetricsRenderIndices + = viewport - > DrawData - > TotalIdxCount ;
}
// Render. If user hasn't set a callback then they may retrieve the draw data via GetDrawData()
# ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
if ( g . Viewports [ 0 ] - > DrawData - > CmdListsCount > 0 & & g . IO . RenderDrawListsFn ! = NULL )
g . IO . RenderDrawListsFn ( g . Viewports [ 0 ] - > DrawData ) ;
# endif
}
const char * ImGui : : FindRenderedTextEnd ( const char * text , const char * text_end )
{
const char * text_display_end = text ;
if ( ! text_end )
text_end = ( const char * ) - 1 ;
while ( text_display_end < text_end & & * text_display_end ! = ' \0 ' & & ( text_display_end [ 0 ] ! = ' # ' | | text_display_end [ 1 ] ! = ' # ' ) )
text_display_end + + ;
return text_display_end ;
}
// Internal ImGui functions to render text
// RenderText***() functions calls ImDrawList::AddText() calls ImBitmapFont::RenderText()
void ImGui : : RenderText ( ImVec2 pos , const char * text , const char * text_end , bool hide_text_after_hash )
{
ImGuiContext & g = * GImGui ;
ImGuiWindow * window = g . CurrentWindow ;
// Hide anything after a '##' string
const char * text_display_end ;
if ( hide_text_after_hash )
{
text_display_end = FindRenderedTextEnd ( text , text_end ) ;
}
else
{
if ( ! text_end )
text_end = text + strlen ( text ) ; // FIXME-OPT
text_display_end = text_end ;
}
if ( text ! = text_display_end )
{
window - > DrawList - > AddText ( g . Font , g . FontSize , pos , GetColorU32 ( ImGuiCol_Text ) , text , text_display_end ) ;
if ( g . LogEnabled )
LogRenderedText ( & pos , text , text_display_end ) ;
}
}
void ImGui : : RenderTextWrapped ( ImVec2 pos , const char * text , const char * text_end , float wrap_width )
{
ImGuiContext & g = * GImGui ;
ImGuiWindow * window = g . CurrentWindow ;
if ( ! text_end )
text_end = text + strlen ( text ) ; // FIXME-OPT
if ( text ! = text_end )
{
window - > DrawList - > AddText ( g . Font , g . FontSize , pos , GetColorU32 ( ImGuiCol_Text ) , text , text_end , wrap_width ) ;
if ( g . LogEnabled )
LogRenderedText ( & pos , text , text_end ) ;
}
}
// Default clip_rect uses (pos_min,pos_max)
// Handle clipping on CPU immediately (vs typically let the GPU clip the triangles that are overlapping the clipping rectangle edges)
void ImGui : : RenderTextClipped ( const ImVec2 & pos_min , const ImVec2 & pos_max , const char * text , const char * text_end , const ImVec2 * text_size_if_known , const ImVec2 & align , const ImRect * clip_rect )
{
// Hide anything after a '##' string
const char * text_display_end = FindRenderedTextEnd ( text , text_end ) ;
const int text_len = ( int ) ( text_display_end - text ) ;
if ( text_len = = 0 )
return ;
ImGuiContext & g = * GImGui ;
ImGuiWindow * window = g . CurrentWindow ;
// Perform CPU side clipping for single clipped element to avoid using scissor state
ImVec2 pos = pos_min ;
const ImVec2 text_size = text_size_if_known ? * text_size_if_known : CalcTextSize ( text , text_display_end , false , 0.0f ) ;
const ImVec2 * clip_min = clip_rect ? & clip_rect - > Min : & pos_min ;
const ImVec2 * clip_max = clip_rect ? & clip_rect - > Max : & pos_max ;
bool need_clipping = ( pos . x + text_size . x > = clip_max - > x ) | | ( pos . y + text_size . y > = clip_max - > y ) ;
if ( clip_rect ) // If we had no explicit clipping rectangle then pos==clip_min
need_clipping | = ( pos . x < clip_min - > x ) | | ( pos . y < clip_min - > y ) ;
// Align whole block. We should defer that to the better rendering function when we'll have support for individual line alignment.
if ( align . x > 0.0f ) pos . x = ImMax ( pos . x , pos . x + ( pos_max . x - pos . x - text_size . x ) * align . x ) ;
if ( align . y > 0.0f ) pos . y = ImMax ( pos . y , pos . y + ( pos_max . y - pos . y - text_size . y ) * align . y ) ;
// Render
if ( need_clipping )
{
ImVec4 fine_clip_rect ( clip_min - > x , clip_min - > y , clip_max - > x , clip_max - > y ) ;
window - > DrawList - > AddText ( g . Font , g . FontSize , pos , GetColorU32 ( ImGuiCol_Text ) , text , text_display_end , 0.0f , & fine_clip_rect ) ;
}
else
{
window - > DrawList - > AddText ( g . Font , g . FontSize , pos , GetColorU32 ( ImGuiCol_Text ) , text , text_display_end , 0.0f , NULL ) ;
}
if ( g . LogEnabled )
LogRenderedText ( & pos , text , text_display_end ) ;
}
// Render a rectangle shaped with optional rounding and borders
void ImGui : : RenderFrame ( ImVec2 p_min , ImVec2 p_max , ImU32 fill_col , bool border , float rounding )
{
ImGuiContext & g = * GImGui ;
ImGuiWindow * window = g . CurrentWindow ;
window - > DrawList - > AddRectFilled ( p_min , p_max , fill_col , rounding ) ;
const float border_size = g . Style . FrameBorderSize ;
if ( border & & border_size > 0.0f )
{
window - > DrawList - > AddRect ( p_min + ImVec2 ( 1 , 1 ) , p_max + ImVec2 ( 1 , 1 ) , GetColorU32 ( ImGuiCol_BorderShadow ) , rounding , ImDrawCornerFlags_All , border_size ) ;
window - > DrawList - > AddRect ( p_min , p_max , GetColorU32 ( ImGuiCol_Border ) , rounding , ImDrawCornerFlags_All , border_size ) ;
break ;
if ( window = = g . HoveredWindow )
hovered_window_above_modal = true ;
}
ClosePopupsOverWindow ( hovered_window_above_modal ? g . HoveredWindow : modal ) ;
}
void ImGui : : RenderFrameBorder ( ImVec2 p_min , ImVec2 p_max , float rounding )
{
ImGuiContext & g = * GImGui ;
ImGuiWindow * window = g . CurrentWindow ;
const float border_size = g . Style . FrameBorderSize ;
if ( border_size > 0.0f )
{
window - > DrawList - > AddRect ( p_min + ImVec2 ( 1 , 1 ) , p_max + ImVec2 ( 1 , 1 ) , GetColorU32 ( ImGuiCol_BorderShadow ) , rounding , ImDrawCornerFlags_All , border_size ) ;
window - > DrawList - > AddRect ( p_min , p_max , GetColorU32 ( ImGuiCol_Border ) , rounding , ImDrawCornerFlags_All , border_size ) ;
}
}
// Render an arrow aimed to be aligned with text (p_min is a position in the same space text would be positioned). To e.g. denote expanded/collapsed state
void ImGui : : RenderArrow ( ImVec2 p_min , ImGuiDir dir , float scale )
{
ImGuiContext & g = * GImGui ;
const float h = g . FontSize * 1.00f ;
float r = h * 0.40f * scale ;
ImVec2 center = p_min + ImVec2 ( h * 0.50f , h * 0.50f * scale ) ;
ImVec2 a , b , c ;
switch ( dir )
// Update user-facing viewport list
g . PlatformIO . MainViewport = g . Viewports [ 0 ] ;
g . PlatformIO . Viewports . resize ( 0 ) ;
for ( int i = 0 ; i < g . Viewports . Size ; i + + )
{
case ImGuiDir_Up :
case ImGuiDir_Down :
if ( dir = = ImGuiDir_Up ) r = - r ;
a = ImVec2 ( + 0.000f , + 0.750f ) * r ;
b = ImVec2 ( - 0.866f , - 0.750f ) * r ;
c = ImVec2 ( + 0.866f , - 0.750f ) * r ;
break ;
case ImGuiDir_Left :
case ImGuiDir_Right :
if ( dir = = ImGuiDir_Left ) r = - r ;
a = ImVec2 ( + 0.750f , + 0.000f ) * r ;
b = ImVec2 ( - 0.750f , + 0.866f ) * r ;
c = ImVec2 ( - 0.750f , - 0.866f ) * r ;
break ;
case ImGuiDir_None :
case ImGuiDir_COUNT :
IM_ASSERT ( 0 ) ;
break ;
}
g . CurrentWindow - > DrawList - > AddTriangleFilled ( center + a , center + b , center + c , GetColorU32 ( ImGuiCol_Text ) ) ;
ImGuiViewportP * viewport = g . Viewports [ i ] ;
if ( viewport - > LastFrameActive < g . FrameCount | | viewport - > Size . x < = 0.0f | | viewport - > Size . y < = 0.0f )
continue ;
if ( viewport - > Window & & ! IsWindowActiveAndVisible ( viewport - > Window ) )
continue ;
if ( i > 0 )
IM_ASSERT ( viewport - > Window ! = NULL ) ;
g . PlatformIO . Viewports . push_back ( viewport ) ;
}
void ImGui : : RenderBullet ( ImVec2 pos )
// Sort the window list so that all child windows are after their parent
// We cannot do that on FocusWindow() because childs may not exist yet
g . WindowsSortBuffer . resize ( 0 ) ;
g . WindowsSortBuffer . reserve ( g . Windows . Size ) ;
for ( int i = 0 ; i ! = g . Windows . Size ; i + + )
{
ImGuiContext & g = * GImGui ;
ImGuiWindow * window = g . CurrentWindow ;
window - > DrawList - > AddCircleFilled ( pos , g . FontSize * 0.20f , GetColorU32 ( ImGuiCol_Text ) , 8 ) ;
ImGuiWindow * window = g . Windows [ i ] ;
if ( window - > Active & & ( window - > Flags & ImGuiWindowFlags_ChildWindow ) ) // if a child is active its parent will add it
continue ;
AddWindowToSortedBuffer ( & g . WindowsSortBuffer , window ) ;
}
void ImGui : : RenderCheckMark ( ImVec2 pos , ImU32 col , float sz )
{
ImGuiContext & g = * GImGui ;
ImGuiWindow * window = g . CurrentWindow ;
IM_ASSERT ( g . Windows . Size = = g . WindowsSortBuffer . Size ) ; // we done something wrong
g . Windows . swap ( g . WindowsSortBuffer ) ;
g . IO . MetricsActiveWindows = g . WindowsActiveCount ;
float thickness = ImMax ( sz / 5.0f , 1.0f ) ;
sz - = thickness * 0.5f ;
pos + = ImVec2 ( thickness * 0.25f , thickness * 0.25f ) ;
// Unlock font atlas
g . IO . Fonts - > Locked = false ;
float third = sz / 3.0f ;
float bx = pos . x + third ;
float by = pos . y + sz - third * 0.5f ;
window- > DrawList - > PathLineTo ( ImVec2 ( bx - third , by - third ) ) ;
window - > DrawList - > PathLineTo ( ImVec2 ( bx , by ) ) ;
window- > DrawList - > PathLineTo ( ImVec2 ( bx + third * 2 , by - third * 2 ) ) ;
window- > DrawList - > PathStroke ( col , false , thickness ) ;
// Clear Input data for next frame
g . IO . MouseWheel = g . IO . MouseWheelH = 0.0f ;
memset ( g . IO . InputCharacters , 0 , sizeof ( g . IO . InputCharacters ) ) ;
memset ( g . IO . NavInputs , 0 , sizeof ( g . IO . NavInputs ) ) ;
g . FrameScopeActive = false ;
g . FrameCountEnded = g . FrameCount ;
}
void ImGui : : Render NavHighlight ( const ImRect & bb , ImGuiID id , ImGuiNavHighlightFlags flags )
void ImGui : : Render ( )
{
ImGuiContext & g = * GImGui ;
if ( id ! = g . NavId )
return ;
if ( g . NavDisableHighlight & & ! ( flags & ImGuiNavHighlightFlags_AlwaysDraw ) )
return ;
ImGuiWindow * window = ImGui : : GetCurrentWindow ( ) ;
if ( window - > DC . NavHideHighlightOneFrame )
return ;
IM_ASSERT ( g . Initialized ) ;
float rounding = ( flags & ImGuiNavHighlightFlags_NoRounding ) ? 0.0f : g . Style . FrameRounding ;
ImRect display_rect = bb ;
display_rect . ClipWith ( window - > ClipRect ) ;
if ( flags & ImGuiNavHighlightFlags_TypeDefault )
if ( g . FrameCountEnded ! = g . FrameCount )
ImGui : : EndFrame ( ) ;
g . FrameCountRendered = g . FrameCount ;
// Gather ImDrawList to render (for each active window)
g . IO . MetricsRenderVertices = g . IO . MetricsRenderIndices = g . IO . MetricsRenderWindows = 0 ;
for ( int n = 0 ; n ! = g . Viewports . Size ; n + + )
g . Viewports [ n ] - > DrawDataBuilder . Clear ( ) ;
ImGuiWindow * windows_to_render_front_most [ 2 ] ;
windows_to_render_front_most [ 0 ] = ( g . NavWindowingTarget & & ! ( g . NavWindowingTarget - > Flags & ImGuiWindowFlags_NoBringToFrontOnFocus ) ) ? g . NavWindowingTarget - > RootWindow : NULL ;
windows_to_render_front_most [ 1 ] = g . NavWindowingTarget ? g . NavWindowingList : NULL ;
for ( int n = 0 ; n ! = g . Windows . Size ; n + + )
{
const float THICKNESS = 2.0f ;
const float DISTANCE = 3.0f + THICKNESS * 0.5f ;
display_rect . Expand ( ImVec2 ( DISTANCE , DISTANCE ) ) ;
bool fully_visible = window - > ClipRect . Contains ( display_rect ) ;
if ( ! fully_visible )
window - > DrawList - > PushClipRect ( display_rect . Min , display_rect . Max ) ;
window - > DrawList - > AddRect ( display_rect . Min + ImVec2 ( THICKNESS * 0.5f , THICKNESS * 0.5f ) , display_rect . Max - ImVec2 ( THICKNESS * 0.5f , THICKNESS * 0.5f ) , GetColorU32 ( ImGuiCol_NavHighlight ) , rounding , ImDrawCornerFlags_All , THICKNESS ) ;
if ( ! fully_visible )
window - > DrawList - > PopClipRect ( ) ;
ImGuiWindow * window = g . Windows [ n ] ;
if ( IsWindowActiveAndVisible ( window ) & & ( window - > Flags & ImGuiWindowFlags_ChildWindow ) = = 0 & & window ! = windows_to_render_front_most [ 0 ] & & window ! = windows_to_render_front_most [ 1 ] )
AddRootWindowToDrawData ( window ) ;
}
if ( flags & ImGuiNavHighlightFlags_TypeThin )
for ( int n = 0 ; n < IM_ARRAYSIZE ( windows_to_render_front_most ) ; n + + )
if ( windows_to_render_front_most [ n ] & & IsWindowActiveAndVisible ( windows_to_render_front_most [ n ] ) ) // NavWindowingTarget is always temporarily displayed as the front-most window
AddRootWindowToDrawData ( windows_to_render_front_most [ n ] ) ;
// Draw software mouse cursor if requested
if ( g . IO . MouseDrawCursor )
RenderMouseCursor ( g . IO . MousePos , g . Style . MouseCursorScale , g . MouseCursor ) ;
// Setup ImDrawData structures for end-user
g . IO . MetricsRenderVertices = g . IO . MetricsRenderIndices = 0 ;
for ( int n = 0 ; n < g . Viewports . Size ; n + + )
{
window - > DrawList - > AddRect ( display_rect . Min , display_rect . Max , GetColorU32 ( ImGuiCol_NavHighlight ) , rounding , ~ 0 , 1.0f ) ;
ImGuiViewportP * viewport = g . Viewports [ n ] ;
viewport - > DrawDataBuilder . FlattenIntoSingleLayer ( ) ;
if ( viewport - > OverlayDrawList ! = NULL )
AddDrawListToDrawData ( & viewport - > DrawDataBuilder . Layers [ 0 ] , GetOverlayDrawList ( viewport ) ) ;
SetupViewportDrawData ( viewport , & viewport - > DrawDataBuilder . Layers [ 0 ] ) ;
g . IO . MetricsRenderVertices + = viewport - > DrawData - > TotalVtxCount ;
g . IO . MetricsRenderIndices + = viewport - > DrawData - > TotalIdxCount ;
}
// Render. If user hasn't set a callback then they may retrieve the draw data via GetDrawData()
# ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
if ( g . Viewports [ 0 ] - > DrawData - > CmdListsCount > 0 & & g . IO . RenderDrawListsFn ! = NULL )
g . IO . RenderDrawListsFn ( g . Viewports [ 0 ] - > DrawData ) ;
# endif
}
// Calculate text size. Text can be multi-line. Optionally ignore text after a ## marker.
@ -4558,7 +4565,7 @@ const ImGuiResizeGripDef resize_grip_def[4] =
{ ImVec2 ( 1 , 0 ) , ImVec2 ( - 1 , + 1 ) , 9 , 12 } , // Upper right
} ;
static ImRect Get BorderRect( ImGuiWindow * window , int border_n , float perp_padding , float thickness )
static ImRect Get Resize BorderRect( ImGuiWindow * window , int border_n , float perp_padding , float thickness )
{
ImRect rect = window - > Rect ( ) ;
if ( thickness = = 0.0f ) rect . Max - = ImVec2 ( 1 , 1 ) ;
@ -4622,7 +4629,7 @@ static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_au
const float BORDER_SIZE = 5.0f ; // FIXME: Only works _inside_ window because of HoveredWindow check.
const float BORDER_APPEAR_TIMER = 0.05f ; // Reduce visual noise
bool hovered , held ;
ImRect border_rect = Get BorderRect( window , border_n , grip_hover_size , BORDER_SIZE ) ;
ImRect border_rect = Get Resize BorderRect( window , border_n , grip_hover_size , BORDER_SIZE ) ;
ButtonBehavior ( border_rect , window - > GetID ( ( void * ) ( intptr_t ) ( border_n + 4 ) ) , & hovered , & held , ImGuiButtonFlags_FlattenChildren ) ;
if ( ( hovered & & g . HoveredIdTimer > BORDER_APPEAR_TIMER ) | | held )
{
@ -5187,7 +5194,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window - > DrawList - > AddRect ( window - > Pos , window - > Pos + window - > Size , GetColorU32 ( ImGuiCol_Border ) , window_rounding , ImDrawCornerFlags_All , window_border_size ) ;
if ( border_held ! = - 1 )
{
ImRect border = Get BorderRect( window , border_held , grip_draw_size , 0.0f ) ;
ImRect border = Get Resize BorderRect( window , border_held , grip_draw_size , 0.0f ) ;
window - > DrawList - > AddLine ( border . Min , border . Max , GetColorU32 ( ImGuiCol_SeparatorActive ) , ImMax ( 1.0f , window_border_size ) ) ;
}
if ( style . FrameBorderSize > 0 & & ! ( flags & ImGuiWindowFlags_NoTitleBar ) )
@ -6383,17 +6390,6 @@ ImGuiStorage* ImGui::GetStateStorage()
return window - > DC . StateStorage ;
}
void ImGui : : AlignTextToFramePadding ( )
{
ImGuiWindow * window = GetCurrentWindow ( ) ;
if ( window - > SkipItems )
return ;
ImGuiContext & g = * GImGui ;
window - > DC . CurrentLineSize . y = ImMax ( window - > DC . CurrentLineSize . y , g . FontSize + g . Style . FramePadding . y * 2 ) ;
window - > DC . CurrentLineTextBaseOffset = ImMax ( window - > DC . CurrentLineTextBaseOffset , g . Style . FramePadding . y ) ;
}
void ImGui : : PushID ( const char * str_id )
{
ImGuiWindow * window = GetCurrentWindowRead ( ) ;
@ -6440,149 +6436,6 @@ ImGuiID ImGui::GetID(const void* ptr_id)
return GImGui - > CurrentWindow - > GetID ( ptr_id ) ;
}
// Horizontal/vertical separating line
void ImGui : : Separator ( )
{
ImGuiWindow * window = GetCurrentWindow ( ) ;
if ( window - > SkipItems )
return ;
ImGuiContext & g = * GImGui ;
// Those flags should eventually be overridable by the user
ImGuiSeparatorFlags flags = ( window - > DC . LayoutType = = ImGuiLayoutType_Horizontal ) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal ;
IM_ASSERT ( ImIsPowerOfTwo ( ( int ) ( flags & ( ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical ) ) ) ) ; // Check that only 1 option is selected
if ( flags & ImGuiSeparatorFlags_Vertical )
{
VerticalSeparator ( ) ;
return ;
}
// Horizontal Separator
if ( window - > DC . ColumnsSet )
PopClipRect ( ) ;
float x1 = window - > Pos . x ;
float x2 = window - > Pos . x + window - > Size . x ;
if ( ! window - > DC . GroupStack . empty ( ) )
x1 + = window - > DC . Indent . x ;
const ImRect bb ( ImVec2 ( x1 , window - > DC . CursorPos . y ) , ImVec2 ( x2 , window - > DC . CursorPos . y + 1.0f ) ) ;
ItemSize ( ImVec2 ( 0.0f , 0.0f ) ) ; // NB: we don't provide our width so that it doesn't get feed back into AutoFit, we don't provide height to not alter layout.
if ( ! ItemAdd ( bb , 0 ) )
{
if ( window - > DC . ColumnsSet )
PushColumnClipRect ( ) ;
return ;
}
window - > DrawList - > AddLine ( bb . Min , ImVec2 ( bb . Max . x , bb . Min . y ) , GetColorU32 ( ImGuiCol_Separator ) ) ;
if ( g . LogEnabled )
LogRenderedText ( NULL , IM_NEWLINE " -------------------------------- " ) ;
if ( window - > DC . ColumnsSet )
{
PushColumnClipRect ( ) ;
window - > DC . ColumnsSet - > LineMinY = window - > DC . CursorPos . y ;
}
}
void ImGui : : VerticalSeparator ( )
{
ImGuiWindow * window = GetCurrentWindow ( ) ;
if ( window - > SkipItems )
return ;
ImGuiContext & g = * GImGui ;
float y1 = window - > DC . CursorPos . y ;
float y2 = window - > DC . CursorPos . y + window - > DC . CurrentLineSize . y ;
const ImRect bb ( ImVec2 ( window - > DC . CursorPos . x , y1 ) , ImVec2 ( window - > DC . CursorPos . x + 1.0f , y2 ) ) ;
ItemSize ( ImVec2 ( bb . GetWidth ( ) , 0.0f ) ) ;
if ( ! ItemAdd ( bb , 0 ) )
return ;
window - > DrawList - > AddLine ( ImVec2 ( bb . Min . x , bb . Min . y ) , ImVec2 ( bb . Min . x , bb . Max . y ) , GetColorU32 ( ImGuiCol_Separator ) ) ;
if ( g . LogEnabled )
LogText ( " | " ) ;
}
// Using 'hover_visibility_delay' allows us to hide the highlight and mouse cursor for a short time, which can be convenient to reduce visual noise.
bool ImGui : : SplitterBehavior ( const ImRect & bb , ImGuiID id , ImGuiAxis axis , float * size1 , float * size2 , float min_size1 , float min_size2 , float hover_extend , float hover_visibility_delay )
{
ImGuiContext & g = * GImGui ;
ImGuiWindow * window = g . CurrentWindow ;
const ImGuiItemFlags item_flags_backup = window - > DC . ItemFlags ;
window - > DC . ItemFlags | = ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus ;
bool item_add = ItemAdd ( bb , id ) ;
window - > DC . ItemFlags = item_flags_backup ;
if ( ! item_add )
return false ;
bool hovered , held ;
ImRect bb_interact = bb ;
bb_interact . Expand ( axis = = ImGuiAxis_Y ? ImVec2 ( 0.0f , hover_extend ) : ImVec2 ( hover_extend , 0.0f ) ) ;
ButtonBehavior ( bb_interact , id , & hovered , & held , ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_AllowItemOverlap ) ;
if ( g . ActiveId ! = id )
SetItemAllowOverlap ( ) ;
if ( held | | ( g . HoveredId = = id & & g . HoveredIdPreviousFrame = = id & & g . HoveredIdTimer > = hover_visibility_delay ) )
SetMouseCursor ( axis = = ImGuiAxis_Y ? ImGuiMouseCursor_ResizeNS : ImGuiMouseCursor_ResizeEW ) ;
ImRect bb_render = bb ;
if ( held )
{
ImVec2 mouse_delta_2d = g . IO . MousePos - g . ActiveIdClickOffset - bb_interact . Min ;
float mouse_delta = ( axis = = ImGuiAxis_Y ) ? mouse_delta_2d . y : mouse_delta_2d . x ;
// Minimum pane size
float size_1_maximum_delta = ImMax ( 0.0f , * size1 - min_size1 ) ;
float size_2_maximum_delta = ImMax ( 0.0f , * size2 - min_size2 ) ;
if ( mouse_delta < - size_1_maximum_delta )
mouse_delta = - size_1_maximum_delta ;
if ( mouse_delta > size_2_maximum_delta )
mouse_delta = size_2_maximum_delta ;
// Apply resize
if ( mouse_delta ! = 0.0f )
{
if ( mouse_delta < 0.0f )
IM_ASSERT ( * size1 + mouse_delta > = min_size1 ) ;
if ( mouse_delta > 0.0f )
IM_ASSERT ( * size2 - mouse_delta > = min_size2 ) ;
* size1 + = mouse_delta ;
* size2 - = mouse_delta ;
bb_render . Translate ( ( axis = = ImGuiAxis_X ) ? ImVec2 ( mouse_delta , 0.0f ) : ImVec2 ( 0.0f , mouse_delta ) ) ;
MarkItemEdited ( id ) ;
}
}
// Render
const ImU32 col = GetColorU32 ( held ? ImGuiCol_SeparatorActive : ( hovered & & g . HoveredIdTimer > = hover_visibility_delay ) ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator ) ;
window - > DrawList - > AddRectFilled ( bb_render . Min , bb_render . Max , col , g . Style . FrameRounding ) ;
return held ;
}
void ImGui : : Spacing ( )
{
ImGuiWindow * window = GetCurrentWindow ( ) ;
if ( window - > SkipItems )
return ;
ItemSize ( ImVec2 ( 0 , 0 ) ) ;
}
void ImGui : : Dummy ( const ImVec2 & size )
{
ImGuiWindow * window = GetCurrentWindow ( ) ;
if ( window - > SkipItems )
return ;
const ImRect bb ( window - > DC . CursorPos , window - > DC . CursorPos + size ) ;
ItemSize ( bb ) ;
ItemAdd ( bb , 0 ) ;
}
bool ImGui : : IsRectVisible ( const ImVec2 & size )
{
ImGuiWindow * window = GetCurrentWindowRead ( ) ;
@ -6689,22 +6542,6 @@ void ImGui::SameLine(float pos_x, float spacing_w)
window - > DC . CurrentLineTextBaseOffset = window - > DC . PrevLineTextBaseOffset ;
}
void ImGui : : NewLine ( )
{
ImGuiWindow * window = GetCurrentWindow ( ) ;
if ( window - > SkipItems )
return ;
ImGuiContext & g = * GImGui ;
const ImGuiLayoutType backup_layout_type = window - > DC . LayoutType ;
window - > DC . LayoutType = ImGuiLayoutType_Vertical ;
if ( window - > DC . CurrentLineSize . y > 0.0f ) // In the event that we are on a line with items that is smaller that FontSize high, we will preserve its height.
ItemSize ( ImVec2 ( 0 , 0 ) ) ;
else
ItemSize ( ImVec2 ( 0.0f , g . FontSize ) ) ;
window - > DC . LayoutType = backup_layout_type ;
}
void ImGui : : Indent ( float indent_w )
{
ImGuiContext & g = * GImGui ;