mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-10-30 20:51:06 +01:00 
			
		
		
		
	Refactor: Moved Button/Image/Checkbox/RadioButton/Bullet/ProgressBar functions from imgui.cpp to imgui_widgets.cpp (#2036)
This commit is contained in:
		
							
								
								
									
										574
									
								
								imgui.cpp
									
									
									
									
									
								
							
							
						
						
									
										574
									
								
								imgui.cpp
									
									
									
									
									
								
							| @@ -7882,387 +7882,6 @@ void ImGui::AlignTextToFramePadding() | ||||
|     window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, g.Style.FramePadding.y); | ||||
| } | ||||
|  | ||||
| bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags) | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     ImGuiWindow* window = GetCurrentWindow(); | ||||
|  | ||||
|     if (flags & ImGuiButtonFlags_Disabled) | ||||
|     { | ||||
|         if (out_hovered) *out_hovered = false; | ||||
|         if (out_held) *out_held = false; | ||||
|         if (g.ActiveId == id) ClearActiveID(); | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     // Default behavior requires click+release on same spot | ||||
|     if ((flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick)) == 0) | ||||
|         flags |= ImGuiButtonFlags_PressedOnClickRelease; | ||||
|  | ||||
|     ImGuiWindow* backup_hovered_window = g.HoveredWindow; | ||||
|     if ((flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredRootWindow == window) | ||||
|         g.HoveredWindow = window; | ||||
|  | ||||
|     bool pressed = false; | ||||
|     bool hovered = ItemHoverable(bb, id); | ||||
|  | ||||
|     // Drag source doesn't report as hovered | ||||
|     if (hovered && g.DragDropActive && g.DragDropPayload.SourceId == id && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoDisableHover)) | ||||
|         hovered = false; | ||||
|  | ||||
|     // Special mode for Drag and Drop where holding button pressed for a long time while dragging another item triggers the button | ||||
|     if (g.DragDropActive && (flags & ImGuiButtonFlags_PressedOnDragDropHold) && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoHoldToOpenOthers)) | ||||
|         if (IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) | ||||
|         { | ||||
|             hovered = true; | ||||
|             SetHoveredID(id); | ||||
|             if (CalcTypematicPressedRepeatAmount(g.HoveredIdTimer + 0.0001f, g.HoveredIdTimer + 0.0001f - g.IO.DeltaTime, 0.01f, 0.70f)) // FIXME: Our formula for CalcTypematicPressedRepeatAmount() is fishy | ||||
|             { | ||||
|                 pressed = true; | ||||
|                 FocusWindow(window); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     if ((flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredRootWindow == window) | ||||
|         g.HoveredWindow = backup_hovered_window; | ||||
|  | ||||
|     // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where a later submitted widget overlaps a previous one. | ||||
|     if (hovered && (flags & ImGuiButtonFlags_AllowItemOverlap) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0)) | ||||
|         hovered = false; | ||||
|  | ||||
|     // Mouse | ||||
|     if (hovered) | ||||
|     { | ||||
|         if (!(flags & ImGuiButtonFlags_NoKeyModifiers) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt)) | ||||
|         { | ||||
|             //                        | CLICKING        | HOLDING with ImGuiButtonFlags_Repeat | ||||
|             // PressedOnClickRelease  |  <on release>*  |  <on repeat> <on repeat> .. (NOT on release)  <-- MOST COMMON! (*) only if both click/release were over bounds | ||||
|             // PressedOnClick         |  <on click>     |  <on click> <on repeat> <on repeat> .. | ||||
|             // PressedOnRelease       |  <on release>   |  <on repeat> <on repeat> .. (NOT on release) | ||||
|             // PressedOnDoubleClick   |  <on dclick>    |  <on dclick> <on repeat> <on repeat> .. | ||||
|             // FIXME-NAV: We don't honor those different behaviors. | ||||
|             if ((flags & ImGuiButtonFlags_PressedOnClickRelease) && g.IO.MouseClicked[0]) | ||||
|             { | ||||
|                 SetActiveID(id, window); | ||||
|                 if (!(flags & ImGuiButtonFlags_NoNavFocus)) | ||||
|                     SetFocusID(id, window); | ||||
|                 FocusWindow(window); | ||||
|             } | ||||
|             if (((flags & ImGuiButtonFlags_PressedOnClick) && g.IO.MouseClicked[0]) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[0])) | ||||
|             { | ||||
|                 pressed = true; | ||||
|                 if (flags & ImGuiButtonFlags_NoHoldingActiveID) | ||||
|                     ClearActiveID(); | ||||
|                 else | ||||
|                     SetActiveID(id, window); // Hold on ID | ||||
|                 FocusWindow(window); | ||||
|             } | ||||
|             if ((flags & ImGuiButtonFlags_PressedOnRelease) && g.IO.MouseReleased[0]) | ||||
|             { | ||||
|                 if (!((flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay))  // Repeat mode trumps <on release> | ||||
|                     pressed = true; | ||||
|                 ClearActiveID(); | ||||
|             } | ||||
|  | ||||
|             // 'Repeat' mode acts when held regardless of _PressedOn flags (see table above). | ||||
|             // Relies on repeat logic of IsMouseClicked() but we may as well do it ourselves if we end up exposing finer RepeatDelay/RepeatRate settings. | ||||
|             if ((flags & ImGuiButtonFlags_Repeat) && g.ActiveId == id && g.IO.MouseDownDuration[0] > 0.0f && IsMouseClicked(0, true)) | ||||
|                 pressed = true; | ||||
|         } | ||||
|  | ||||
|         if (pressed) | ||||
|             g.NavDisableHighlight = true; | ||||
|     } | ||||
|  | ||||
|     // Gamepad/Keyboard navigation | ||||
|     // We report navigated item as hovered but we don't set g.HoveredId to not interfere with mouse. | ||||
|     if (g.NavId == id && !g.NavDisableHighlight && g.NavDisableMouseHover && (g.ActiveId == 0 || g.ActiveId == id || g.ActiveId == window->MoveId)) | ||||
|         hovered = true; | ||||
|  | ||||
|     if (g.NavActivateDownId == id) | ||||
|     { | ||||
|         bool nav_activated_by_code = (g.NavActivateId == id); | ||||
|         bool nav_activated_by_inputs = IsNavInputPressed(ImGuiNavInput_Activate, (flags & ImGuiButtonFlags_Repeat) ? ImGuiInputReadMode_Repeat : ImGuiInputReadMode_Pressed); | ||||
|         if (nav_activated_by_code || nav_activated_by_inputs) | ||||
|             pressed = true; | ||||
|         if (nav_activated_by_code || nav_activated_by_inputs || g.ActiveId == id) | ||||
|         { | ||||
|             // Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button. | ||||
|             g.NavActivateId = id; // This is so SetActiveId assign a Nav source | ||||
|             SetActiveID(id, window); | ||||
|             if (!(flags & ImGuiButtonFlags_NoNavFocus)) | ||||
|                 SetFocusID(id, window); | ||||
|             g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right) | (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     bool held = false; | ||||
|     if (g.ActiveId == id) | ||||
|     { | ||||
|         if (g.ActiveIdSource == ImGuiInputSource_Mouse) | ||||
|         { | ||||
|             if (g.ActiveIdIsJustActivated) | ||||
|                 g.ActiveIdClickOffset = g.IO.MousePos - bb.Min; | ||||
|             if (g.IO.MouseDown[0]) | ||||
|             { | ||||
|                 held = true; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if (hovered && (flags & ImGuiButtonFlags_PressedOnClickRelease)) | ||||
|                     if (!((flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay))  // Repeat mode trumps <on release> | ||||
|                         if (!g.DragDropActive) | ||||
|                             pressed = true; | ||||
|                 ClearActiveID(); | ||||
|             } | ||||
|             if (!(flags & ImGuiButtonFlags_NoNavFocus)) | ||||
|                 g.NavDisableHighlight = true; | ||||
|         } | ||||
|         else if (g.ActiveIdSource == ImGuiInputSource_Nav) | ||||
|         { | ||||
|             if (g.NavActivateDownId != id) | ||||
|                 ClearActiveID(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (out_hovered) *out_hovered = hovered; | ||||
|     if (out_held) *out_held = held; | ||||
|  | ||||
|     return pressed; | ||||
| } | ||||
|  | ||||
| bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags flags) | ||||
| { | ||||
|     ImGuiWindow* window = GetCurrentWindow(); | ||||
|     if (window->SkipItems) | ||||
|         return false; | ||||
|  | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     const ImGuiStyle& style = g.Style; | ||||
|     const ImGuiID id = window->GetID(label); | ||||
|     const ImVec2 label_size = CalcTextSize(label, NULL, true); | ||||
|  | ||||
|     ImVec2 pos = window->DC.CursorPos; | ||||
|     if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrentLineTextBaseOffset) // Try to vertically align buttons that are smaller/have no padding so that text baseline matches (bit hacky, since it shouldn't be a flag) | ||||
|         pos.y += window->DC.CurrentLineTextBaseOffset - style.FramePadding.y; | ||||
|     ImVec2 size = CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f); | ||||
|  | ||||
|     const ImRect bb(pos, pos + size); | ||||
|     ItemSize(bb, style.FramePadding.y); | ||||
|     if (!ItemAdd(bb, id)) | ||||
|         return false; | ||||
|  | ||||
|     if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat) | ||||
|         flags |= ImGuiButtonFlags_Repeat; | ||||
|     bool hovered, held; | ||||
|     bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); | ||||
|     if (pressed) | ||||
|         MarkItemEdited(id); | ||||
|  | ||||
|     // Render | ||||
|     const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); | ||||
|     RenderNavHighlight(bb, id); | ||||
|     RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding); | ||||
|     RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, NULL, &label_size, style.ButtonTextAlign, &bb); | ||||
|  | ||||
|     // Automatically close popups | ||||
|     //if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup)) | ||||
|     //    CloseCurrentPopup(); | ||||
|  | ||||
|     return pressed; | ||||
| } | ||||
|  | ||||
| bool ImGui::Button(const char* label, const ImVec2& size_arg) | ||||
| { | ||||
|     return ButtonEx(label, size_arg, 0); | ||||
| } | ||||
|  | ||||
| // Small buttons fits within text without additional vertical spacing. | ||||
| bool ImGui::SmallButton(const char* label) | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     float backup_padding_y = g.Style.FramePadding.y; | ||||
|     g.Style.FramePadding.y = 0.0f; | ||||
|     bool pressed = ButtonEx(label, ImVec2(0,0), ImGuiButtonFlags_AlignTextBaseLine); | ||||
|     g.Style.FramePadding.y = backup_padding_y; | ||||
|     return pressed; | ||||
| } | ||||
|  | ||||
| bool ImGui::ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size, ImGuiButtonFlags flags) | ||||
| { | ||||
|     ImGuiWindow* window = GetCurrentWindow(); | ||||
|     if (window->SkipItems) | ||||
|         return false; | ||||
|  | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     const ImGuiID id = window->GetID(str_id); | ||||
|     const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); | ||||
|     const float default_size = GetFrameHeight(); | ||||
|     ItemSize(bb, (size.y >= default_size) ? g.Style.FramePadding.y : 0.0f); | ||||
|     if (!ItemAdd(bb, id)) | ||||
|         return false; | ||||
|  | ||||
|     if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat) | ||||
|         flags |= ImGuiButtonFlags_Repeat; | ||||
|  | ||||
|     bool hovered, held; | ||||
|     bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); | ||||
|  | ||||
|     // Render | ||||
|     const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); | ||||
|     RenderNavHighlight(bb, id); | ||||
|     RenderFrame(bb.Min, bb.Max, col, true, g.Style.FrameRounding); | ||||
|     RenderArrow(bb.Min + ImVec2(ImMax(0.0f, size.x - g.FontSize - g.Style.FramePadding.x), ImMax(0.0f, size.y - g.FontSize - g.Style.FramePadding.y)), dir); | ||||
|  | ||||
|     return pressed; | ||||
| } | ||||
|  | ||||
| bool ImGui::ArrowButton(const char* str_id, ImGuiDir dir) | ||||
| { | ||||
|     float sz = GetFrameHeight(); | ||||
|     return ArrowButtonEx(str_id, dir, ImVec2(sz, sz), 0); | ||||
| } | ||||
|  | ||||
| // Tip: use ImGui::PushID()/PopID() to push indices or pointers in the ID stack. | ||||
| // Then you can keep 'str_id' empty or the same for all your buttons (instead of creating a string based on a non-string id) | ||||
| bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg) | ||||
| { | ||||
|     ImGuiWindow* window = GetCurrentWindow(); | ||||
|     if (window->SkipItems) | ||||
|         return false; | ||||
|  | ||||
|     // Cannot use zero-size for InvisibleButton(). Unlike Button() there is not way to fallback using the label size. | ||||
|     IM_ASSERT(size_arg.x != 0.0f && size_arg.y != 0.0f); | ||||
|  | ||||
|     const ImGuiID id = window->GetID(str_id); | ||||
|     ImVec2 size = CalcItemSize(size_arg, 0.0f, 0.0f); | ||||
|     const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); | ||||
|     ItemSize(bb); | ||||
|     if (!ItemAdd(bb, id)) | ||||
|         return false; | ||||
|  | ||||
|     bool hovered, held; | ||||
|     bool pressed = ButtonBehavior(bb, id, &hovered, &held); | ||||
|  | ||||
|     return pressed; | ||||
| } | ||||
|  | ||||
| // Button to close a window | ||||
| bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius) | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     ImGuiWindow* window = g.CurrentWindow; | ||||
|  | ||||
|     // We intentionally allow interaction when clipped so that a mechanical Alt,Right,Validate sequence close a window. | ||||
|     // (this isn't the regular behavior of buttons, but it doesn't affect the user much because navigation tends to keep items visible). | ||||
|     const ImRect bb(pos - ImVec2(radius,radius), pos + ImVec2(radius,radius)); | ||||
|     bool is_clipped = !ItemAdd(bb, id); | ||||
|  | ||||
|     bool hovered, held; | ||||
|     bool pressed = ButtonBehavior(bb, id, &hovered, &held); | ||||
|     if (is_clipped) | ||||
|         return pressed; | ||||
|  | ||||
|     // Render | ||||
|     ImVec2 center = bb.GetCenter(); | ||||
|     if (hovered) | ||||
|         window->DrawList->AddCircleFilled(center, ImMax(2.0f, radius), GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered), 9); | ||||
|  | ||||
|     float cross_extent = (radius * 0.7071f) - 1.0f; | ||||
|     ImU32 cross_col = GetColorU32(ImGuiCol_Text); | ||||
|     center -= ImVec2(0.5f, 0.5f); | ||||
|     window->DrawList->AddLine(center + ImVec2(+cross_extent,+cross_extent), center + ImVec2(-cross_extent,-cross_extent), cross_col, 1.0f); | ||||
|     window->DrawList->AddLine(center + ImVec2(+cross_extent,-cross_extent), center + ImVec2(-cross_extent,+cross_extent), cross_col, 1.0f); | ||||
|  | ||||
|     return pressed; | ||||
| } | ||||
|  | ||||
| bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos) | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     ImGuiWindow* window = g.CurrentWindow; | ||||
|  | ||||
|     ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize) + g.Style.FramePadding * 2.0f); | ||||
|     ItemAdd(bb, id); | ||||
|     bool hovered, held; | ||||
|     bool pressed = ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_None); | ||||
|  | ||||
|     ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); | ||||
|     if (hovered || held) | ||||
|         window->DrawList->AddCircleFilled(bb.GetCenter() + ImVec2(0.0f, -0.5f), g.FontSize * 0.5f + 1.0f, col, 9); | ||||
|     RenderArrow(bb.Min + g.Style.FramePadding, window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down, 1.0f); | ||||
|  | ||||
|     // Switch to moving the window after mouse is moved beyond the initial drag threshold | ||||
|     if (IsItemActive() && IsMouseDragging()) | ||||
|         StartMouseMovingWindow(window); | ||||
|  | ||||
|     return pressed; | ||||
| } | ||||
|  | ||||
| void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col) | ||||
| { | ||||
|     ImGuiWindow* window = GetCurrentWindow(); | ||||
|     if (window->SkipItems) | ||||
|         return; | ||||
|  | ||||
|     ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); | ||||
|     if (border_col.w > 0.0f) | ||||
|         bb.Max += ImVec2(2,2); | ||||
|     ItemSize(bb); | ||||
|     if (!ItemAdd(bb, 0)) | ||||
|         return; | ||||
|  | ||||
|     if (border_col.w > 0.0f) | ||||
|     { | ||||
|         window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(border_col), 0.0f); | ||||
|         window->DrawList->AddImage(user_texture_id, bb.Min+ImVec2(1,1), bb.Max-ImVec2(1,1), uv0, uv1, GetColorU32(tint_col)); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         window->DrawList->AddImage(user_texture_id, bb.Min, bb.Max, uv0, uv1, GetColorU32(tint_col)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| // frame_padding < 0: uses FramePadding from style (default) | ||||
| // frame_padding = 0: no framing | ||||
| // frame_padding > 0: set framing size | ||||
| // The color used are the button colors. | ||||
| bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, int frame_padding, const ImVec4& bg_col, const ImVec4& tint_col) | ||||
| { | ||||
|     ImGuiWindow* window = GetCurrentWindow(); | ||||
|     if (window->SkipItems) | ||||
|         return false; | ||||
|  | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     const ImGuiStyle& style = g.Style; | ||||
|  | ||||
|     // Default to using texture ID as ID. User can still push string/integer prefixes. | ||||
|     // We could hash the size/uv to create a unique ID but that would prevent the user from animating UV. | ||||
|     PushID((void*)user_texture_id); | ||||
|     const ImGuiID id = window->GetID("#image"); | ||||
|     PopID(); | ||||
|  | ||||
|     const ImVec2 padding = (frame_padding >= 0) ? ImVec2((float)frame_padding, (float)frame_padding) : style.FramePadding; | ||||
|     const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size + padding*2); | ||||
|     const ImRect image_bb(window->DC.CursorPos + padding, window->DC.CursorPos + padding + size); | ||||
|     ItemSize(bb); | ||||
|     if (!ItemAdd(bb, id)) | ||||
|         return false; | ||||
|  | ||||
|     bool hovered, held; | ||||
|     bool pressed = ButtonBehavior(bb, id, &hovered, &held); | ||||
|  | ||||
|     // Render | ||||
|     const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); | ||||
|     RenderNavHighlight(bb, id); | ||||
|     RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, style.FrameRounding)); | ||||
|     if (bg_col.w > 0.0f) | ||||
|         window->DrawList->AddRectFilled(image_bb.Min, image_bb.Max, GetColorU32(bg_col)); | ||||
|     window->DrawList->AddImage(user_texture_id, image_bb.Min, image_bb.Max, uv0, uv1, GetColorU32(tint_col)); | ||||
|  | ||||
|     return pressed; | ||||
| } | ||||
|  | ||||
| // Start logging ImGui output to TTY | ||||
| void ImGui::LogToTTY(int max_depth) | ||||
| { | ||||
| @@ -8752,28 +8371,6 @@ ImGuiID ImGui::GetID(const void* ptr_id) | ||||
|     return GImGui->CurrentWindow->GetID(ptr_id); | ||||
| } | ||||
|  | ||||
| void ImGui::Bullet() | ||||
| { | ||||
|     ImGuiWindow* window = GetCurrentWindow(); | ||||
|     if (window->SkipItems) | ||||
|         return; | ||||
|  | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     const ImGuiStyle& style = g.Style; | ||||
|     const float line_height = ImMax(ImMin(window->DC.CurrentLineSize.y, g.FontSize + g.Style.FramePadding.y*2), g.FontSize); | ||||
|     const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize, line_height)); | ||||
|     ItemSize(bb); | ||||
|     if (!ItemAdd(bb, 0)) | ||||
|     { | ||||
|         SameLine(0, style.FramePadding.x*2); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     // Render and stay on same line | ||||
|     RenderBullet(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f)); | ||||
|     SameLine(0, style.FramePadding.x*2); | ||||
| } | ||||
|  | ||||
| static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* format) | ||||
| { | ||||
|     if (data_type == ImGuiDataType_S32 || data_type == ImGuiDataType_U32)   // Signedness doesn't matter when pushing the argument | ||||
| @@ -9995,177 +9592,6 @@ void ImGui::PlotHistogram(const char* label, float (*values_getter)(void* data, | ||||
|     PlotEx(ImGuiPlotType_Histogram, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); | ||||
| } | ||||
|  | ||||
| // size_arg (for each axis) < 0.0f: align to end, 0.0f: auto, > 0.0f: specified size | ||||
| void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* overlay) | ||||
| { | ||||
|     ImGuiWindow* window = GetCurrentWindow(); | ||||
|     if (window->SkipItems) | ||||
|         return; | ||||
|  | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     const ImGuiStyle& style = g.Style; | ||||
|  | ||||
|     ImVec2 pos = window->DC.CursorPos; | ||||
|     ImRect bb(pos, pos + CalcItemSize(size_arg, CalcItemWidth(), g.FontSize + style.FramePadding.y*2.0f)); | ||||
|     ItemSize(bb, style.FramePadding.y); | ||||
|     if (!ItemAdd(bb, 0)) | ||||
|         return; | ||||
|  | ||||
|     // Render | ||||
|     fraction = ImSaturate(fraction); | ||||
|     RenderFrame(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); | ||||
|     bb.Expand(ImVec2(-style.FrameBorderSize, -style.FrameBorderSize)); | ||||
|     const ImVec2 fill_br = ImVec2(ImLerp(bb.Min.x, bb.Max.x, fraction), bb.Max.y); | ||||
|     RenderRectFilledRangeH(window->DrawList, bb, GetColorU32(ImGuiCol_PlotHistogram), 0.0f, fraction, style.FrameRounding); | ||||
|  | ||||
|     // Default displaying the fraction as percentage string, but user can override it | ||||
|     char overlay_buf[32]; | ||||
|     if (!overlay) | ||||
|     { | ||||
|         ImFormatString(overlay_buf, IM_ARRAYSIZE(overlay_buf), "%.0f%%", fraction*100+0.01f); | ||||
|         overlay = overlay_buf; | ||||
|     } | ||||
|  | ||||
|     ImVec2 overlay_size = CalcTextSize(overlay, NULL); | ||||
|     if (overlay_size.x > 0.0f) | ||||
|         RenderTextClipped(ImVec2(ImClamp(fill_br.x + style.ItemSpacing.x, bb.Min.x, bb.Max.x - overlay_size.x - style.ItemInnerSpacing.x), bb.Min.y), bb.Max, overlay, NULL, &overlay_size, ImVec2(0.0f,0.5f), &bb); | ||||
| } | ||||
|  | ||||
| bool ImGui::Checkbox(const char* label, bool* v) | ||||
| { | ||||
|     ImGuiWindow* window = GetCurrentWindow(); | ||||
|     if (window->SkipItems) | ||||
|         return false; | ||||
|  | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     const ImGuiStyle& style = g.Style; | ||||
|     const ImGuiID id = window->GetID(label); | ||||
|     const ImVec2 label_size = CalcTextSize(label, NULL, true); | ||||
|  | ||||
|     const ImRect check_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(label_size.y + style.FramePadding.y*2, label_size.y + style.FramePadding.y*2)); // We want a square shape to we use Y twice | ||||
|     ItemSize(check_bb, style.FramePadding.y); | ||||
|  | ||||
|     ImRect total_bb = check_bb; | ||||
|     if (label_size.x > 0) | ||||
|         SameLine(0, style.ItemInnerSpacing.x); | ||||
|     const ImRect text_bb(window->DC.CursorPos + ImVec2(0,style.FramePadding.y), window->DC.CursorPos + ImVec2(0,style.FramePadding.y) + label_size); | ||||
|     if (label_size.x > 0) | ||||
|     { | ||||
|         ItemSize(ImVec2(text_bb.GetWidth(), check_bb.GetHeight()), style.FramePadding.y); | ||||
|         total_bb = ImRect(ImMin(check_bb.Min, text_bb.Min), ImMax(check_bb.Max, text_bb.Max)); | ||||
|     } | ||||
|  | ||||
|     if (!ItemAdd(total_bb, id)) | ||||
|         return false; | ||||
|  | ||||
|     bool hovered, held; | ||||
|     bool pressed = ButtonBehavior(total_bb, id, &hovered, &held); | ||||
|     if (pressed) | ||||
|     { | ||||
|         *v = !(*v); | ||||
|         MarkItemEdited(id); | ||||
|     } | ||||
|  | ||||
|     RenderNavHighlight(total_bb, id); | ||||
|     RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding); | ||||
|     if (*v) | ||||
|     { | ||||
|         const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight()); | ||||
|         const float pad = ImMax(1.0f, (float)(int)(check_sz / 6.0f)); | ||||
|         RenderCheckMark(check_bb.Min + ImVec2(pad,pad), GetColorU32(ImGuiCol_CheckMark), check_bb.GetWidth() - pad*2.0f); | ||||
|     } | ||||
|  | ||||
|     if (g.LogEnabled) | ||||
|         LogRenderedText(&text_bb.Min, *v ? "[x]" : "[ ]"); | ||||
|     if (label_size.x > 0.0f) | ||||
|         RenderText(text_bb.Min, label); | ||||
|  | ||||
|     return pressed; | ||||
| } | ||||
|  | ||||
| bool ImGui::CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value) | ||||
| { | ||||
|     bool v = ((*flags & flags_value) == flags_value); | ||||
|     bool pressed = Checkbox(label, &v); | ||||
|     if (pressed) | ||||
|     { | ||||
|         if (v) | ||||
|             *flags |= flags_value; | ||||
|         else | ||||
|             *flags &= ~flags_value; | ||||
|     } | ||||
|  | ||||
|     return pressed; | ||||
| } | ||||
|  | ||||
| bool ImGui::RadioButton(const char* label, bool active) | ||||
| { | ||||
|     ImGuiWindow* window = GetCurrentWindow(); | ||||
|     if (window->SkipItems) | ||||
|         return false; | ||||
|  | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     const ImGuiStyle& style = g.Style; | ||||
|     const ImGuiID id = window->GetID(label); | ||||
|     const ImVec2 label_size = CalcTextSize(label, NULL, true); | ||||
|  | ||||
|     const ImRect check_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(label_size.y + style.FramePadding.y*2-1, label_size.y + style.FramePadding.y*2-1)); | ||||
|     ItemSize(check_bb, style.FramePadding.y); | ||||
|  | ||||
|     ImRect total_bb = check_bb; | ||||
|     if (label_size.x > 0) | ||||
|         SameLine(0, style.ItemInnerSpacing.x); | ||||
|     const ImRect text_bb(window->DC.CursorPos + ImVec2(0, style.FramePadding.y), window->DC.CursorPos + ImVec2(0, style.FramePadding.y) + label_size); | ||||
|     if (label_size.x > 0) | ||||
|     { | ||||
|         ItemSize(ImVec2(text_bb.GetWidth(), check_bb.GetHeight()), style.FramePadding.y); | ||||
|         total_bb.Add(text_bb); | ||||
|     } | ||||
|  | ||||
|     if (!ItemAdd(total_bb, id)) | ||||
|         return false; | ||||
|  | ||||
|     ImVec2 center = check_bb.GetCenter(); | ||||
|     center.x = (float)(int)center.x + 0.5f; | ||||
|     center.y = (float)(int)center.y + 0.5f; | ||||
|     const float radius = check_bb.GetHeight() * 0.5f; | ||||
|  | ||||
|     bool hovered, held; | ||||
|     bool pressed = ButtonBehavior(total_bb, id, &hovered, &held); | ||||
|     if (pressed) | ||||
|         MarkItemEdited(id); | ||||
|  | ||||
|     RenderNavHighlight(total_bb, id); | ||||
|     window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16); | ||||
|     if (active) | ||||
|     { | ||||
|         const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight()); | ||||
|         const float pad = ImMax(1.0f, (float)(int)(check_sz / 6.0f)); | ||||
|         window->DrawList->AddCircleFilled(center, radius-pad, GetColorU32(ImGuiCol_CheckMark), 16); | ||||
|     } | ||||
|  | ||||
|     if (style.FrameBorderSize > 0.0f) | ||||
|     { | ||||
|         window->DrawList->AddCircle(center+ImVec2(1,1), radius, GetColorU32(ImGuiCol_BorderShadow), 16, style.FrameBorderSize); | ||||
|         window->DrawList->AddCircle(center, radius, GetColorU32(ImGuiCol_Border), 16, style.FrameBorderSize); | ||||
|     } | ||||
|  | ||||
|     if (g.LogEnabled) | ||||
|         LogRenderedText(&text_bb.Min, active ? "(x)" : "( )"); | ||||
|     if (label_size.x > 0.0f) | ||||
|         RenderText(text_bb.Min, label); | ||||
|  | ||||
|     return pressed; | ||||
| } | ||||
|  | ||||
| bool ImGui::RadioButton(const char* label, int* v, int v_button) | ||||
| { | ||||
|     const bool pressed = RadioButton(label, *v == v_button); | ||||
|     if (pressed) | ||||
|         *v = v_button; | ||||
|     return pressed; | ||||
| } | ||||
|  | ||||
| static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end) | ||||
| { | ||||
|     int line_count = 0; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user